addresses = new ArrayList<>();
- try {
- X509Certificate certificate = getCertificate();
- if (null != certificate) {
- Principal principal = certificate.getSubjectX500Principal();
- if (null != principal) {
- String name = principal.getName();
- StringTokenizer tokenizer = new StringTokenizer(name, ",");
- while (tokenizer.hasMoreTokens()) {
- String next = tokenizer.nextToken();
- if (next.startsWith("E="))
- addresses.add(next.substring(2));
- }
- }
- }
- } catch (Exception e) {
- }
- this.addresses = Collections.unmodifiableList(addresses);
- }
-
-}
diff --git a/src/main/java/org/simplejavamail/utils/mail/smime/SmimeKeyStore.java b/src/main/java/org/simplejavamail/utils/mail/smime/SmimeKeyStore.java
deleted file mode 100644
index ba0f689..0000000
--- a/src/main/java/org/simplejavamail/utils/mail/smime/SmimeKeyStore.java
+++ /dev/null
@@ -1,197 +0,0 @@
-package org.simplejavamail.utils.mail.smime;
-
-import java.io.InputStream;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.PrivateKey;
-import java.security.cert.Certificate;
-import java.security.cert.X509Certificate;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * A wrapper around a {@link KeyStore} that can be initialized with a PKCS12
- * keystore and is used to obtain {@link SmimeKey SmimeKeys}.
- *
- * @author Allen Petersen (akp at sourceforge dot net)
- * @author Torsten Krause (tk at markenwerk dot net)
- * @since 1.0.0
- */
-public class SmimeKeyStore {
-
- private final KeyStore keyStore;
-
- /**
- * Creates a new {@code SmimeKeyStore} by loading a PKCS12 keystore from
- * the given input stream.
- *
- *
- * The character array holding the password is overwritten with {@code 0s}
- * after it has been used.
- *
- * @param stream
- * The {@link InputStream} to read the PKCS12 keystore from.
- * @param password
- * The password to unlock the PKCS12 keystore with.
- */
- public SmimeKeyStore(InputStream stream, char[] password) {
- this(stream, password, true);
- }
-
- /**
- * Creates a new {@code SmimeKeyStore} by loading a PKCS12 keystore from
- * the given input stream.
- *
- *
- * If {@code discardPassword} is set to {@code true}, the character array
- * holding the password is overwritten with {@code 0s} after it has been
- * used.
- *
- * @param stream
- * The {@link InputStream} to read the PKCS12 keystore from.
- * @param password
- * The password to unlock the PKCS12 keystore with.
- * @param discardPassword
- * Whether to overwrite the {@code char[]} holding the password
- * after it has been used.
- */
- public SmimeKeyStore(InputStream stream, char[] password, boolean discardPassword) {
- try {
- keyStore = KeyStore.getInstance("PKCS12", "BC");
- keyStore.load(stream, password);
- } catch (Exception e) {
- throw new SmimeException("Couldn't initialize SmimeKeyStore", e);
- } finally {
- if (discardPassword) {
- overwrite(password);
- }
- }
- }
-
- private void overwrite(char[] password) {
- if (null != password) {
- for (int i = 0, n = password.length; i < n; i++) {
- password[i] = 0;
- }
- }
- }
-
- /**
- * Returns the number of entries in the underlying PKCS12 keystore.
- *
- * @return The number of entries in the underlying {@link KeyStore}.
- *
- */
- public int size() {
- try {
- return keyStore.size();
- } catch (KeyStoreException e) {
- throw new SmimeException("Couldn't retrieve the number of entries from SmimeKeyStore", e);
- }
- }
-
- /**
- * Returns the S/MIME key associated with the given alias, using the given
- * password to recover it.
- *
- *
- * The character array holding the password is overwritten with {@code 0s}
- * after it has been used.
- *
- * @param alias
- * The alias.
- * @param password
- * The password to unlock the {@link PrivateKey} keystore with.
- *
- * @return The requested {@link SmimeKey}, or null if the given alias does
- * not exist or does not identify a private key entry.
- */
- public SmimeKey getPrivateKey(String alias, char[] password) {
- return getPrivateKey(alias, password, true);
- }
-
- /**
- * Returns the S/MIME key associated with the given alias, using the given
- * password to recover it.
- *
- *
- * If {@code discardPassword} is set to {@code true}, the character array
- * holding the password is overwritten with {@code 0s} after it has been
- * used.
- *
- * @param alias
- * The alias.
- * @param password
- * The password to unlock the {@link PrivateKey} keystore with.
- * @param discardPassword
- * Whether to overwrite the {@code char[]} holding the password
- * after it has been used.
- *
- * @return The requested {@link SmimeKey}, or null if the given alias does
- * not exist or does not identify a private key entry.
- */
- public SmimeKey getPrivateKey(String alias, char[] password, boolean discardPassword) {
- try {
- if (containsPrivateKeyAlias(alias)) {
- PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, password);
- Certificate[] certificateChain = keyStore.getCertificateChain(alias);
- return new SmimeKey(privateKey, copy(certificateChain));
- }
- return null;
- } catch (Exception e) {
- throw new SmimeException("Couldn't recover SmimeKey from SmimeKeyStore", e);
- } finally {
- if (discardPassword) {
- overwrite(password);
- }
- }
- }
-
- private X509Certificate[] copy(Certificate[] certificateChain) {
- X509Certificate[] x509certificateChain = new X509Certificate[certificateChain.length];
- for (int i = 0, n = certificateChain.length; i < n; i++) {
- x509certificateChain[i] = (X509Certificate) certificateChain[i];
- }
- return x509certificateChain;
- }
-
- /**
- * Returns a set containing all aliases listed in the PKCS12 keystore.
- *
- * @return A {@link Collections#unmodifiableSet(Set) unmodifiable set} of
- * aliases.
- */
- public Set getPrivateKeyAliases() {
- try {
- Enumeration aliases = keyStore.aliases();
- Set aliasSet = new HashSet<>();
- while (aliases.hasMoreElements()) {
- String alias = aliases.nextElement();
- if (keyStore.isKeyEntry(alias))
- aliasSet.add(alias);
- }
- return Collections.unmodifiableSet(aliasSet);
- } catch (Exception e) {
- throw new SmimeException("Couldn't recover aliases from SmimeKeyStore", e);
- }
- }
-
- /**
- * Checks if the given alias exists in the PKCS12 keystore.
- *
- * @param alias
- * The alias to look for.
- *
- * @return {@code true} if the alias exists, {@code false} otherwise.
- */
- public boolean containsPrivateKeyAlias(String alias) {
- try {
- return keyStore.isKeyEntry(alias);
- } catch (Exception e) {
- throw new SmimeException("Couldn't recover aliases from SmimeKeyStore", e);
- }
- }
-
-}
diff --git a/src/main/java/org/simplejavamail/utils/mail/smime/SmimeMessageIdFixingMimeMessage.java b/src/main/java/org/simplejavamail/utils/mail/smime/SmimeMessageIdFixingMimeMessage.java
deleted file mode 100644
index b1d08cd..0000000
--- a/src/main/java/org/simplejavamail/utils/mail/smime/SmimeMessageIdFixingMimeMessage.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.simplejavamail.utils.mail.smime;
-
-import jakarta.mail.MessagingException;
-import jakarta.mail.Session;
-import jakarta.mail.internet.MimeMessage;
-import org.jetbrains.annotations.Nullable;
-
-import static java.lang.String.format;
-
-public class SmimeMessageIdFixingMimeMessage extends MimeMessage {
- @Nullable
- private final String messageId;
-
- public SmimeMessageIdFixingMimeMessage(Session session, @Nullable String messageId) {
- super(session);
- this.messageId = messageId;
- }
-
- @Override
- protected void updateMessageID() throws MessagingException {
- if (messageId == null || messageId.length() == 0) {
- super.updateMessageID();
- } else {
- setHeader("Message-ID", messageId);
- }
- }
-
- @Override
- public String toString() {
- try {
- return format("SmimeMimeMessage", super.getMessageID(), super.getSubject());
- } catch (MessagingException e) {
- throw new IllegalStateException("should not reach here");
- }
- }
-}
\ No newline at end of file
diff --git a/src/main/java/org/simplejavamail/utils/mail/smime/SmimeMessageIdFixingSMTPMessage.java b/src/main/java/org/simplejavamail/utils/mail/smime/SmimeMessageIdFixingSMTPMessage.java
deleted file mode 100644
index 745afe3..0000000
--- a/src/main/java/org/simplejavamail/utils/mail/smime/SmimeMessageIdFixingSMTPMessage.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.simplejavamail.utils.mail.smime;
-
-import jakarta.mail.MessagingException;
-import jakarta.mail.Session;
-import org.eclipse.angus.mail.smtp.SMTPMessage;
-import org.jetbrains.annotations.Nullable;
-
-import static java.lang.String.format;
-
-public class SmimeMessageIdFixingSMTPMessage extends SMTPMessage {
- @Nullable
- private final String messageId;
-
- public SmimeMessageIdFixingSMTPMessage(Session session, @Nullable String messageId) {
- super(session);
- this.messageId = messageId;
- }
-
- @Override
- protected void updateMessageID() throws MessagingException {
- if (messageId == null || messageId.length() == 0) {
- super.updateMessageID();
- } else {
- setHeader("Message-ID", messageId);
- }
- }
-
- @Override
- public String toString() {
- try {
- return format("SmimeSMTPMessage", super.getMessageID(), super.getSubject());
- } catch (MessagingException e) {
- throw new IllegalStateException("should not reach here");
- }
- }
-}
diff --git a/src/main/java/org/simplejavamail/utils/mail/smime/SmimeState.java b/src/main/java/org/simplejavamail/utils/mail/smime/SmimeState.java
deleted file mode 100644
index 40419bc..0000000
--- a/src/main/java/org/simplejavamail/utils/mail/smime/SmimeState.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package org.simplejavamail.utils.mail.smime;
-
-import jakarta.mail.internet.MimeMultipart;
-import jakarta.mail.internet.MimePart;
-
-/**
- * The {@code SmimeState} of a {@link MimePart} or {@link MimeMultipart} is
- * derived from the corresponding content type and can be obtained with
- * {@link SmimeUtil#checkSignature(MimePart) checkSignature()};
- *
- * @author Torsten Krause (tk at markenwerk dot net)
- * @since 1.0.0
- */
-public enum SmimeState {
-
- /**
- * Indicates that the {@link MimePart} or {@link MimeMultipart} is S/MIME
- * encrypted.
- */
- ENCRYPTED,
-
- /**
- * Indicates that the {@link MimePart} or {@link MimeMultipart} is probably S/MIME
- * signed (type was multipart/signed, but protocol was missing).
- */
- PROBABLY_SIGNED,
-
- /**
- * Indicates that the {@link MimePart} or {@link MimeMultipart} is S/MIME
- * signed.
- */
- SIGNED,
-
- /**
- * Indicates that the {@link MimePart} or {@link MimeMultipart} is S/MIME
- * signed using an envelope (content is wrapped, probably as base64).
- */
- SIGNED_ENVELOPED,
-
- /**
- * Indicates that the {@link MimePart} or {@link MimeMultipart} is neither
- * S/MIME encrypted nor S/MIME signed.
- */
- NEITHER
-
-}
diff --git a/src/main/java/org/simplejavamail/utils/mail/smime/SmimeUtil.java b/src/main/java/org/simplejavamail/utils/mail/smime/SmimeUtil.java
deleted file mode 100644
index 9be12d4..0000000
--- a/src/main/java/org/simplejavamail/utils/mail/smime/SmimeUtil.java
+++ /dev/null
@@ -1,714 +0,0 @@
-package org.simplejavamail.utils.mail.smime;
-
-import jakarta.activation.CommandMap;
-import jakarta.activation.MailcapCommandMap;
-import jakarta.mail.Header;
-import jakarta.mail.MessagingException;
-import jakarta.mail.Multipart;
-import jakarta.mail.Session;
-import jakarta.mail.internet.*;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.cms.AttributeTable;
-import org.bouncycastle.asn1.cms.IssuerAndSerialNumber;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-import org.bouncycastle.asn1.smime.SMIMECapabilitiesAttribute;
-import org.bouncycastle.asn1.smime.SMIMECapability;
-import org.bouncycastle.asn1.smime.SMIMECapabilityVector;
-import org.bouncycastle.asn1.smime.SMIMEEncryptionKeyPreferenceAttribute;
-import org.bouncycastle.asn1.x500.RDN;
-import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.asn1.x500.style.BCStyle;
-import org.bouncycastle.asn1.x500.style.IETFUtils;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.cert.X509CertificateHolder;
-import org.bouncycastle.cert.jcajce.JcaCertStore;
-import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
-import org.bouncycastle.cms.*;
-import org.bouncycastle.cms.jcajce.*;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.mail.smime.*;
-import org.bouncycastle.operator.OperatorCreationException;
-import org.bouncycastle.operator.OutputEncryptor;
-import org.bouncycastle.operator.jcajce.JcaAlgorithmParametersConverter;
-import org.bouncycastle.util.Store;
-import org.eclipse.angus.mail.smtp.SMTPMessage;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import javax.crypto.spec.OAEPParameterSpec;
-import javax.crypto.spec.PSource;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.Security;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-import java.security.spec.MGF1ParameterSpec;
-import java.util.*;
-
-/**
- * Utilities for handling S/MIME specific operations on MIME messages from
- * JavaMail.
- *
- * @author Allen Petersen (akp at sourceforge dot net)
- * @author Torsten Krause (tk at markenwerk dot net)
- * @since 1.0.0
- */
-public final class SmimeUtil {
-
- /**
- * Unfortunately, these constants are not available in the Bouncy Castle, and they have to be passed as strings.
- *
- * @see org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder for a list of supported algorithms.
- */
- public static final String DEFAULT_SIGNATURE_ALGORITHM_NAME = "SHA256withRSA";
- public static final KeyEncapsulationAlgorithm DEFAULT_KEY_ENCAPSULATION_ALGORITHM = KeyEncapsulationAlgorithm.RSA;
- public static final ASN1ObjectIdentifier DEFAULT_CIPHER = CMSAlgorithm.DES_EDE3_CBC;
-
- static {
- if (null == Security.getProvider(BouncyCastleProvider.PROVIDER_NAME)) {
- Security.addProvider(new BouncyCastleProvider());
- updateMailcapCommandMap();
- }
- }
-
- @SuppressWarnings("unused")
- private SmimeUtil() {
- }
-
- private static void updateMailcapCommandMap() {
- MailcapCommandMap map = (MailcapCommandMap) CommandMap.getDefaultCommandMap();
- map.addMailcap("application/pkcs7-signature;;x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_signature");
- map.addMailcap("application/pkcs7-mime;;x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_mime");
- map.addMailcap("application/x-pkcs7-signature;;x-java-content-handler=org.bouncycastle.mail.smime.handlers.x_pkcs7_signature");
- map.addMailcap("application/x-pkcs7-mime;;x-java-content-handler=org.bouncycastle.mail.smime.handlers.x_pkcs7_mime");
- map.addMailcap("multipart/signed;;x-java-content-handler=org.bouncycastle.mail.smime.handlers.multipart_signed");
- CommandMap.setDefaultCommandMap(map);
- }
-
- /**
- * Encrypts a MIME message and yields a new S/MIME encrypted MIME message.
- *
- * @param session The {@link Session} that is used in conjunction with the original {@link MimeMessage}.
- * @param messageId Optional MessageID that should be preserved on the encrypted MimeMessage result.
- * @param mimeMessage The original {@link MimeMessage} to be encrypted.
- * @param certificate The {@link X509Certificate} used to obtain the {@link PublicKey} to encrypt the original message with.
- * @return The new S/MIME encrypted {@link MimeMessage}.
- */
- public static MimeMessage encrypt(Session session, @Nullable String messageId, MimeMessage mimeMessage, X509Certificate certificate) {
- return encrypt(session, mimeMessage, messageId, certificate, DEFAULT_KEY_ENCAPSULATION_ALGORITHM, DEFAULT_CIPHER);
- }
-
- /**
- * Encrypts a MIME message and yields a new S/MIME encrypted MIME message.
- *
- * @param session The {@link Session} that is used in conjunction with the
- * original {@link MimeMessage}.
- * @param mimeMessage The original {@link MimeMessage} to be encrypted.
- * @param messageId Optional MessageID that should be preserved on the encrypted MimeMessage result.
- * @param certificate The {@link X509Certificate} used to obtain the
- * {@link PublicKey} to encrypt the original message with.
- * @param keyEncapsulationAlgorithm Algorithm used to encapsulate the symmetric encryption key.
- * Currently, RSA RSA-OAEP with various SHA digest lengths are supported.
- * @param cmsAlgorithm Encryption algorithm for symmetric content encryption.
- * @return The new S/MIME encrypted {@link MimeMessage}.
- */
- public static MimeMessage encrypt(Session session, MimeMessage mimeMessage, @Nullable String messageId, X509Certificate certificate, KeyEncapsulationAlgorithm keyEncapsulationAlgorithm, ASN1ObjectIdentifier cmsAlgorithm) {
- try {
- MimeMessage encryptedMimeMessage = new SmimeMessageIdFixingMimeMessage(session, messageId);
- copyHeaders(mimeMessage, encryptedMimeMessage);
-
- SMIMEEnvelopedGenerator generator = prepareGenerator(certificate, keyEncapsulationAlgorithm);
- OutputEncryptor encryptor = prepareEncryptor(cmsAlgorithm);
-
- MimeBodyPart encryptedMimeBodyPart = generator.generate(mimeMessage, encryptor);
- copyContent(encryptedMimeBodyPart, encryptedMimeMessage);
- copyHeaders(encryptedMimeBodyPart, encryptedMimeMessage);
- encryptedMimeMessage.saveChanges();
- return encryptedMimeMessage;
- } catch (Exception e) {
- throw handledException(e);
- }
- }
-
- /**
- * Encrypts a MIME body part and yields a new S/MIME encrypted MIME body
- * part.
- *
- * @param mimeBodyPart The original {@link MimeBodyPart} to be encrypted.
- * @param certificate The {@link X509Certificate} used to obtain the
- * {@link PublicKey} to encrypt the original body part with.
- * @return The new S/MIME encrypted {@link MimeBodyPart}.
- */
- public static MimeBodyPart encrypt(MimeBodyPart mimeBodyPart, X509Certificate certificate) {
- return encrypt(mimeBodyPart, certificate, DEFAULT_KEY_ENCAPSULATION_ALGORITHM, DEFAULT_CIPHER);
- }
-
- /**
- * Encrypts a MIME body part and yields a new S/MIME encrypted MIME body
- * part.
- *
- * @param mimeBodyPart The original {@link MimeBodyPart} to be encrypted.
- * @param certificate The {@link X509Certificate} used to obtain the
- * {@link PublicKey} to encrypt the original body part with.
- * @param keyEncapsulationAlgorithm Algorithm used to encapsulate the symmetric encryption key.
- * Currently, RSA RSA-OAEP with various SHA digest lengths are supported.
- * @param cmsAlgorithm Encryption algorithm for symmetric content encryption.
- * @return The new S/MIME encrypted {@link MimeBodyPart}.
- */
- public static MimeBodyPart encrypt(MimeBodyPart mimeBodyPart,
- X509Certificate certificate,
- KeyEncapsulationAlgorithm keyEncapsulationAlgorithm,
- ASN1ObjectIdentifier cmsAlgorithm) {
- try {
- SMIMEEnvelopedGenerator generator = prepareGenerator(certificate, keyEncapsulationAlgorithm);
- OutputEncryptor encryptor = prepareEncryptor(cmsAlgorithm);
-
- return generator.generate(mimeBodyPart, encryptor);
-
- } catch (Exception e) {
- throw handledException(e);
- }
- }
-
- private static void copyHeaders(MimeBodyPart fromBodyPart, MimeMessage toMessage) throws MessagingException {
- Enumeration headers = fromBodyPart.getAllHeaders();
- copyHeaders(headers, toMessage);
- }
-
- private static void copyHeaders(MimeMessage fromMessage, MimeMessage toMessage) throws MessagingException {
- Enumeration headers = fromMessage.getAllHeaders();
- copyHeaders(headers, toMessage);
- }
-
- private static void copyHeaders(Enumeration headers, MimeMessage toMessage) throws MessagingException {
- while (headers.hasMoreElements()) {
- Header header = headers.nextElement();
- toMessage.setHeader(header.getName(), header.getValue());
- }
- }
-
- private static SMIMEEnvelopedGenerator prepareGenerator(X509Certificate certificate,
- KeyEncapsulationAlgorithm keyEncapsulationAlgorithm)
- throws CertificateEncodingException, InvalidAlgorithmParameterException {
- final JceKeyTransRecipientInfoGenerator infoGenerator;
- if (keyEncapsulationAlgorithm == KeyEncapsulationAlgorithm.RSA) {
- infoGenerator = new JceKeyTransRecipientInfoGenerator(certificate);
- } else {
- String digestName = determineDigestName(keyEncapsulationAlgorithm);
- AlgorithmIdentifier oaepParams = new JcaAlgorithmParametersConverter().getAlgorithmIdentifier(
- PKCSObjectIdentifiers.id_RSAES_OAEP, new OAEPParameterSpec(
- digestName, "MGF1", new MGF1ParameterSpec(digestName), PSource.PSpecified.DEFAULT));
- infoGenerator = new JceKeyTransRecipientInfoGenerator(certificate, oaepParams);
- }
- infoGenerator.setProvider(BouncyCastleProvider.PROVIDER_NAME);
- SMIMEEnvelopedGenerator generator = new SMIMEEnvelopedGenerator();
- generator.addRecipientInfoGenerator(infoGenerator);
- return generator;
- }
-
- @NotNull
- private static String determineDigestName(KeyEncapsulationAlgorithm keyEncapsulationAlgorithm) throws InvalidAlgorithmParameterException {
- if (keyEncapsulationAlgorithm == KeyEncapsulationAlgorithm.RSA_OAEP_SHA224) {
- return "SHA-234";
- } else if (keyEncapsulationAlgorithm == KeyEncapsulationAlgorithm.RSA_OAEP_SHA256) {
- return "SHA-256";
- } else if (keyEncapsulationAlgorithm == KeyEncapsulationAlgorithm.RSA_OAEP_SHA384) {
- return "SHA-384";
- } else if (keyEncapsulationAlgorithm == KeyEncapsulationAlgorithm.RSA_OAEP_SHA512) {
- return "SHA-512";
- } else {
- throw new InvalidAlgorithmParameterException("Unknown S/MIME key encapsulation algorithm: "
- + keyEncapsulationAlgorithm.name());
- }
- }
-
- private static OutputEncryptor prepareEncryptor(ASN1ObjectIdentifier cmsAlgorithm) throws CMSException {
- return new JceCMSContentEncryptorBuilder(cmsAlgorithm).setProvider(BouncyCastleProvider.PROVIDER_NAME).build();
- }
-
- /**
- * Decrypts an S/MIME encrypted MIME message and yields a new MIME message.
- *
- * @param session The {@link Session} that is used in conjunction with the
- * encrypted {@link MimeMessage}.
- * @param mimeMessage The encrypted {@link MimeMessage} to be decrypted.
- * @param smimeKey The {@link SmimeKey} used to obtain the {@link PrivateKey} to
- * decrypt the encrypted message with.
- * @return The new S/MIME decrypted {@link MimeMessage}.
- */
- public static MimeMessage decrypt(Session session, MimeMessage mimeMessage, SmimeKey smimeKey) {
- try {
- byte[] content = decryptContent(new SMIMEEnveloped(mimeMessage), smimeKey);
- MimeBodyPart mimeBodyPart = SMIMEUtil.toMimeBodyPart(content);
-
- MimeMessage decryptedMessage = new MimeMessage(session);
- copyHeaderLines(mimeMessage, decryptedMessage);
- copyContent(mimeBodyPart, decryptedMessage);
- decryptedMessage.setHeader("Content-Type", mimeBodyPart.getContentType());
- return decryptedMessage;
-
- } catch (Exception e) {
- throw handledException(e);
- }
- }
-
- /**
- * Decrypts an S/MIME encrypted MIME body part and yields a new MIME body
- * part.
- *
- * @param mimeBodyPart The encrypted {@link MimeBodyPart} to be decrypted.
- * @param smimeKey The {@link SmimeKey} used to obtain the {@link PrivateKey} to
- * decrypt the encrypted body part with.
- * @return The new S/MIME decrypted {@link MimeBodyPart}.
- */
- public static MimeBodyPart decrypt(MimeBodyPart mimeBodyPart, SmimeKey smimeKey) {
- try {
- return SMIMEUtil.toMimeBodyPart(decryptContent(new SMIMEEnveloped(mimeBodyPart), smimeKey));
- } catch (Exception e) {
- throw handledException(e);
- }
- }
-
- /**
- * Decrypts an S/MIME encrypted MIME multipart and yields a new MIME body
- * part.
- *
- * @param mimeMultipart The encrypted {@link MimeMultipart} to be decrypted.
- * @param smimeKey The {@link SmimeKey} used to obtain the {@link PrivateKey} to
- * decrypt the encrypted multipart with.
- * @return The new S/MIME decrypted {@link MimeBodyPart}.
- */
- public static MimeBodyPart decrypt(MimeMultipart mimeMultipart, SmimeKey smimeKey) {
- try {
- MimeBodyPart mimeBodyPart = new MimeBodyPart();
- mimeBodyPart.setContent(mimeMultipart);
- mimeBodyPart.setHeader("Content-Type", mimeMultipart.getContentType());
- return decrypt(mimeBodyPart, smimeKey);
- } catch (Exception e) {
- throw handledException(e);
- }
- }
-
- private static byte[] decryptContent(SMIMEEnveloped smimeEnveloped, SmimeKey smimeKey) throws MessagingException, CMSException {
- X509Certificate certificate = smimeKey.getCertificate();
- PrivateKey privateKey = smimeKey.getPrivateKey();
-
- RecipientInformationStore recipients = smimeEnveloped.getRecipientInfos();
- RecipientInformation recipient = recipients.get(new JceKeyTransRecipientId(certificate));
-
- if (null == recipient) {
- throw new MessagingException("no recipient");
- }
-
- JceKeyTransRecipient transportRecipient = new JceKeyTransEnvelopedRecipient(privateKey);
- transportRecipient.setProvider(BouncyCastleProvider.PROVIDER_NAME);
- return recipient.getContent(transportRecipient);
- }
-
- private static void copyHeaderLines(MimeMessage fromMessage, MimeMessage toMessage) throws MessagingException {
- Enumeration headerLines = fromMessage.getAllHeaderLines();
- while (headerLines.hasMoreElements()) {
- String nextElement = headerLines.nextElement();
- toMessage.addHeaderLine(nextElement);
- }
- }
-
- private static void copyContent(MimeBodyPart fromBodyPart, MimeMessage toMessage) throws MessagingException, IOException {
- toMessage.setContent(fromBodyPart.getContent(), fromBodyPart.getContentType());
- }
-
- /**
- * Signs a MIME body part and yields a new S/MIME signed MIME body part.
- *
- * @param mimeBodyPart The original {@link MimeBodyPart} to be signed.
- * @param smimeKey The {@link SmimeKey} used to obtain the {@link PrivateKey} to
- * sign the original body part with.
- * @return The new S/MIME signed {@link MimeBodyPart}.
- */
- public static MimeBodyPart sign(MimeBodyPart mimeBodyPart, SmimeKey smimeKey) {
- return sign(mimeBodyPart, smimeKey, DEFAULT_SIGNATURE_ALGORITHM_NAME);
- }
-
- /**
- * Signs a MIME body part and yields a new S/MIME signed MIME body part.
- *
- * @param mimeBodyPart The original {@link MimeBodyPart} to be signed.
- * @param smimeKey The {@link SmimeKey} used to obtain the {@link PrivateKey} to
- * sign the original body part with.
- * @param algorithmName The name of the signature algorithm to use. Must be an algorithm
- * supported by the Bouncy Castle security provider.
- * @return The new S/MIME signed {@link MimeBodyPart}.
- */
- public static MimeBodyPart sign(MimeBodyPart mimeBodyPart, SmimeKey smimeKey, String algorithmName) {
- try {
- SMIMESignedGenerator generator = getGenerator(smimeKey, algorithmName);
- MimeMultipart signedMimeMultipart = generator.generate(MimeUtil.canonicalize(mimeBodyPart));
- MimeBodyPart signedMimeBodyPart = new MimeBodyPart();
- signedMimeBodyPart.setContent(signedMimeMultipart);
- return signedMimeBodyPart;
-
- } catch (Exception e) {
- throw handledException(e);
- }
-
- }
-
- private static SMIMESignedGenerator getGenerator(SmimeKey smimeKey, String algorithmName)
- throws CertificateEncodingException, OperatorCreationException {
- SMIMESignedGenerator generator = new SMIMESignedGenerator();
- generator.addCertificates(getCertificateStore(smimeKey));
- generator.addSignerInfoGenerator(getInfoGenerator(smimeKey, algorithmName));
- return generator;
- }
-
- private static SignerInfoGenerator getInfoGenerator(SmimeKey smimeKey, String algorithmName)
- throws OperatorCreationException, CertificateEncodingException {
- JcaSimpleSignerInfoGeneratorBuilder builder = new JcaSimpleSignerInfoGeneratorBuilder();
- builder.setSignedAttributeGenerator(new AttributeTable(getSignedAttributes(smimeKey)));
- builder.setProvider(BouncyCastleProvider.PROVIDER_NAME);
-
- PrivateKey privateKey = smimeKey.getPrivateKey();
- X509Certificate certificate = smimeKey.getCertificate();
- return builder.build(algorithmName, privateKey, certificate);
- }
-
- private static ASN1EncodableVector getSignedAttributes(SmimeKey smimeKey) {
- ASN1EncodableVector signedAttributes = new ASN1EncodableVector();
- IssuerAndSerialNumber issuerAndSerialNumber = getIssuerAndSerialNumber(smimeKey);
- signedAttributes.add(new SMIMEEncryptionKeyPreferenceAttribute(issuerAndSerialNumber));
- signedAttributes.add(new SMIMECapabilitiesAttribute(getCapabilityVector()));
- return signedAttributes;
- }
-
- private static SMIMECapabilityVector getCapabilityVector() {
- SMIMECapabilityVector capabilityVector = new SMIMECapabilityVector();
- capabilityVector.addCapability(SMIMECapability.dES_EDE3_CBC);
- capabilityVector.addCapability(SMIMECapability.rC2_CBC, 128);
- capabilityVector.addCapability(SMIMECapability.dES_CBC);
- return capabilityVector;
- }
-
- private static IssuerAndSerialNumber getIssuerAndSerialNumber(SmimeKey smimeKey) {
- X509Certificate certificate = smimeKey.getCertificate();
- BigInteger serialNumber = certificate.getSerialNumber();
- X500Name issuerName = new X500Name(certificate.getIssuerX500Principal().getName());
- return new IssuerAndSerialNumber(issuerName, serialNumber);
- }
-
- private static JcaCertStore getCertificateStore(SmimeKey smimeKey) throws CertificateEncodingException {
- Certificate[] certificateChain = smimeKey.getCertificateChain();
- X509Certificate certificate = smimeKey.getCertificate();
-
- final List certificateList;
- if (certificateChain != null && certificateChain.length > 0) {
- certificateList = Arrays.asList(certificateChain);
- } else {
- certificateList = new ArrayList<>();
- certificateList.add(certificate);
- }
- return new JcaCertStore(certificateList);
- }
-
- /**
- * Signs a MIME message and yields a new S/MIME signed MIME message.
- *
- * @param session The {@link Session} that is used in conjunction with the original {@link MimeMessage}.
- * @param messageId Optional MessageID that should be preserved on the signed MimeMessage.
- * @param mimeMessage The original {@link MimeMessage} or {@link SMTPMessage} to be signed.
- * @param smimeKey The {@link SmimeKey} used to obtain the {@link PrivateKey} to sign the original message with.
- * @return The new S/MIME signed {@link MimeMessage} or {@link SMTPMessage}.
- */
- public static T sign(Session session, @Nullable String messageId, T mimeMessage, SmimeKey smimeKey) {
- return sign(session, messageId, mimeMessage, smimeKey, DEFAULT_SIGNATURE_ALGORITHM_NAME);
- }
-
- /**
- * Signs a MIME message and yields a new S/MIME signed MIME message.
- *
- * @param session The {@link Session} that is used in conjunction with the original {@link MimeMessage}.
- * @param messageId Optional MessageID that should be preserved on the signed MimeMessage.
- * @param mimeMessage The original {@link MimeMessage} or {@link SMTPMessage} to be signed.
- * @param smimeKey The {@link SmimeKey} used to obtain the {@link PrivateKey} to sign the original message with.
- * @param algorithmName The name of the signature algorithm to use. Must be an algorithm supported by the Bouncy Castle security provider.
- * @return The new S/MIME signed {@link MimeMessage} or {@link SMTPMessage}.
- */
- public static T sign(Session session, @Nullable String messageId, T mimeMessage, SmimeKey smimeKey, String algorithmName) {
- //noinspection unchecked
- return (mimeMessage instanceof SMTPMessage)
- ? sign(mimeMessage, (T) new SmimeMessageIdFixingSMTPMessage(session, messageId), smimeKey, algorithmName)
- : sign(mimeMessage, (T) new SmimeMessageIdFixingMimeMessage(session, messageId), smimeKey, algorithmName);
- }
-
- private static T sign(T mimeMessage, T signedMessage, SmimeKey smimeKey, String algorithmName) {
- try {
- copyHeaderLines(mimeMessage, signedMessage);
- copyContent(sign(extractMimeBodyPart(mimeMessage), smimeKey, algorithmName), signedMessage);
- return signedMessage;
- } catch (Exception e) {
- throw handledException(e);
- }
- }
-
- private static MimeBodyPart extractMimeBodyPart(MimeMessage mimeMessage) throws IOException, MessagingException {
- Object content = mimeMessage.getContent();
- UpdatableMimeBodyPart updateableMimeBodyPart = new UpdatableMimeBodyPart();
- if (content instanceof Multipart) {
- updateableMimeBodyPart.setContent((Multipart) content);
- } else {
- updateableMimeBodyPart.setContent(content, mimeMessage.getDataHandler().getContentType());
- }
- updateableMimeBodyPart.updateHeaders();
- return updateableMimeBodyPart;
- }
-
- /**
- * Checks the signature on an S/MIME signed MIME multipart.
- *
- * @param mimeMultipart The {@link MimeMultipart} to be checked.
- * @return {@code true} if the multipart is correctly signed, {@code false}
- * otherwise.
- */
- public static boolean checkSignature(MimeMultipart mimeMultipart) {
- try {
- return checkSignature(new SMIMESigned(mimeMultipart));
- } catch (Exception e) {
- throw handledException(e);
- }
- }
-
- /**
- * Checks the signature on an S/MIME signed MIME part (i.e. MIME message).
- *
- * @param mimePart The {@link MimePart} to be checked.
- * @return {@code true} if the part is correctly signed, {@code false}
- * otherwise.
- */
- public static boolean checkSignature(MimePart mimePart) {
- try {
- if (mimePart.isMimeType("multipart/signed")) {
- return checkSignature(new SMIMESigned((MimeMultipart) mimePart.getContent()));
- } else if (mimePart.isMimeType("application/pkcs7-mime") || mimePart.isMimeType("application/x-pkcs7-mime")) {
- return checkSignature(new SMIMESigned(mimePart));
- } else {
- throw new SmimeException("Message not signed");
- }
- } catch (Exception e) {
- throw handledException(e);
- }
- }
-
- /**
- * Checks a SMIMESigned to make sure that the signature matches.
- */
- private static boolean checkSignature(SMIMESigned smimeSigned) {
- try {
- boolean returnValue = true;
-
- @SuppressWarnings("rawtypes")
- Store certificates = smimeSigned.getCertificates();
- Iterator signerInformations = smimeSigned.getSignerInfos().getSigners().iterator();
-
- while (returnValue && signerInformations.hasNext()) {
- SignerInformation signerInformation = signerInformations.next();
- X509Certificate certificate = getCertificate(certificates, signerInformation.getSID());
- SignerInformationVerifier verifier = getVerifier(certificate);
- if (!signerInformation.verify(verifier)) {
- returnValue = false;
- }
- }
- return returnValue;
-
- } catch (Exception e) {
- throw handledException(e);
- }
- }
-
- /**
- * @param mimeMultipart The {@link MimeMultipart} to be checked.
- * @return The subject / address to which the certificate was issued to. Email clients may use this to show
- * {@code "Signed by: "}
- */
- public static String getSignedByAddress(MimeMultipart mimeMultipart) {
- try {
- return getSignedByAddress(new SMIMESigned(mimeMultipart));
- } catch (Exception e) {
- throw handledException(e);
- }
- }
-
- /**
- * @param mimePart The {@link MimePart} to be checked.
- * @return The subject / address to which the certificate was issued to. Email clients may use this to show
- * {@code "Signed by: "}
- */
- public static String getSignedByAddress(MimePart mimePart) {
- try {
- if (mimePart.isMimeType("multipart/signed")) {
- return getSignedByAddress(new SMIMESigned((MimeMultipart) mimePart.getContent()));
- } else if (mimePart.isMimeType("application/pkcs7-mime") || mimePart.isMimeType("application/x-pkcs7-mime")) {
- return getSignedByAddress(new SMIMESigned(mimePart));
- } else {
- throw new SmimeException("Message not signed");
- }
- } catch (Exception e) {
- throw handledException(e);
- }
- }
-
- /**
- * Returns the subject / address to which the certificate was issued to. Email clients may use this to show
- * {@code "Signed by: "}
- */
- private static String getSignedByAddress(SMIMESigned smimeSigned) {
- try {
- @SuppressWarnings("rawtypes")
- Store certificates = smimeSigned.getCertificates();
-
- SignerInformation signerInformation = smimeSigned.getSignerInfos().getSigners().iterator().next();
- X509Certificate certificate = getCertificate(certificates, signerInformation.getSID());
- SignerInformationVerifier verifier = getVerifier(certificate);
- X500Name x500name = verifier.getAssociatedCertificate().getSubject();
- RDN cn = x500name.getRDNs(BCStyle.CN)[0];
- return IETFUtils.valueToString(cn.getFirst().getValue());
-
- } catch (Exception e) {
- throw handledException(e);
- }
- }
-
- private static X509Certificate getCertificate(@SuppressWarnings("rawtypes") Store certificates,
- SignerId signerId) throws CertificateException {
- @SuppressWarnings({"unchecked"})
- X509CertificateHolder certificateHolder = (X509CertificateHolder) certificates.getMatches(signerId).iterator().next();
- JcaX509CertificateConverter certificateConverter = new JcaX509CertificateConverter();
- certificateConverter.setProvider(BouncyCastleProvider.PROVIDER_NAME);
- return certificateConverter.getCertificate(certificateHolder);
- }
-
- private static SignerInformationVerifier getVerifier(X509Certificate certificate) throws OperatorCreationException {
- JcaSimpleSignerInfoVerifierBuilder builder = new JcaSimpleSignerInfoVerifierBuilder();
- builder.setProvider(BouncyCastleProvider.PROVIDER_NAME);
- return builder.build(certificate);
- }
-
- /**
- * Returns the signed MIME body part of an S/MIME signed MIME multipart.
- *
- * @param mimeMultipart The {@link MimeMultipart} to be stripped off.
- * @return The signed {@link MimeBodyPart} contained in the
- * {@link MimeMultipart}.
- */
- public static MimeBodyPart getSignedContent(MimeMultipart mimeMultipart) {
- try {
- return new SMIMESigned(mimeMultipart).getContent();
- } catch (Exception e) {
- throw handledException(e);
- }
- }
-
- /**
- * Returns the signed MIME body part of an S/MIME signed MIME part (i.e. MIME
- * message).
- *
- * @param mimePart The {@link MimePart} to be stripped off.
- * @return The signed {@link MimeBodyPart} contained in the {@link MimePart}
- * .
- */
- public static MimeBodyPart getSignedContent(MimePart mimePart) {
- try {
- if (mimePart.isMimeType("multipart/signed")) {
- return new SMIMESigned((MimeMultipart) mimePart.getContent()).getContent();
- } else if (mimePart.isMimeType("application/pkcs7-mime") || mimePart.isMimeType("application/x-pkcs7-mime")) {
- return new SMIMESigned(mimePart).getContent();
- } else {
- throw new SmimeException("Message not signed");
- }
- } catch (Exception e) {
- throw handledException(e);
- }
- }
-
- /**
- * Returns the S/MIME state of a MIME multipart.
- *
- * @param mimeMultipart The {@link MimeMultipart} to be checked.
- * @return the {@link SmimeState} of the {@link MimeMultipart}.
- */
- public static SmimeState getStatus(MimeMultipart mimeMultipart) {
- try {
- return getStatus(new ContentType(mimeMultipart.getContentType()));
- } catch (Exception e) {
- throw handledException(e);
- }
- }
-
- /**
- * Returns the S/MIME state of a MIME part (i.e. MIME message).
- *
- * @param mimePart The {@link MimePart} to be checked.
- * @return the {@link SmimeState} of the {@link MimePart}.
- */
- public static SmimeState getStatus(MimePart mimePart) {
- try {
- return getStatus(new ContentType(mimePart.getContentType()));
- } catch (Exception e) {
- throw handledException(e);
- }
- }
-
- private static SmimeState getStatus(ContentType contentType) {
- if (isSmimeSignatureContentType(contentType)) {
- return SmimeState.SIGNED;
- } if (isProbablySmimeSignatureContentType(contentType)) {
- return SmimeState.PROBABLY_SIGNED;
- } else if (isSignatureSmimeType(contentType)) {
- return SmimeState.SIGNED_ENVELOPED;
- } else if (isSmimeEncryptionContenttype(contentType)) {
- return SmimeState.ENCRYPTED;
- } else {
- return SmimeState.NEITHER;
- }
- }
-
- private static boolean isSmimeEncryptionContenttype(ContentType contentType) {
- String baseContentType = contentType.getBaseType();
- return baseContentType.equalsIgnoreCase("application/pkcs7-mime")
- || baseContentType.equalsIgnoreCase("application/x-pkcs7-mime");
- }
-
- private static boolean isSmimeSignatureContentType(ContentType contentType) {
- String protocol = contentType.getParameter("protocol");
- return contentType.getBaseType().equalsIgnoreCase("multipart/signed")
- && protocol != null && isSmimeSignatureProtocoll(protocol);
- }
-
- private static boolean isProbablySmimeSignatureContentType(ContentType contentType) {
- String protocol = contentType.getParameter("protocol");
- return contentType.getBaseType().equalsIgnoreCase("multipart/signed") && protocol == null;
- }
-
- private static boolean isSignatureSmimeType(ContentType contentType) {
- String baseContentType = contentType.getBaseType();
- return baseContentType.equalsIgnoreCase("application/x-pkcs7-mime")
- && "signed-data".equals(contentType.getParameter("smime-type"));
- }
-
- private static boolean isSmimeSignatureProtocoll(String protocol) {
- return protocol.equalsIgnoreCase("application/pkcs7-signature")
- || protocol.equalsIgnoreCase("application/x-pkcs7-signature");
- }
-
- private static SmimeException handledException(Exception e) {
- if (e instanceof SmimeException) {
- return (SmimeException) e;
- }
- return new SmimeException(e.getMessage(), e);
- }
-
-}
diff --git a/src/main/java/org/simplejavamail/utils/mail/smime/UpdatableMimeBodyPart.java b/src/main/java/org/simplejavamail/utils/mail/smime/UpdatableMimeBodyPart.java
deleted file mode 100644
index b119bbc..0000000
--- a/src/main/java/org/simplejavamail/utils/mail/smime/UpdatableMimeBodyPart.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.simplejavamail.utils.mail.smime;
-
-import jakarta.mail.MessagingException;
-import jakarta.mail.internet.MimeBodyPart;
-
-/**
- * A {@link MimeBodyPart} that exposes the method {@code updateHeaders()} with
- * {@code public} visibility.
- *
- * @author Allen Petersen (akp at sourceforge dot net)
- * @author Torsten Krause (tk at markenwerk dot net)
- * @since 1.0.0
- */
-class UpdatableMimeBodyPart extends MimeBodyPart {
-
- /**
- * Calls updateHeaders().
- */
- public void updateHeaders() throws MessagingException {
- super.updateHeaders();
- }
-
-}
diff --git a/src/test/java/org/simplejavamail/utils/mail/smime/SmimeUtilTest.java b/src/test/java/org/simplejavamail/utils/mail/smime/SmimeUtilTest.java
deleted file mode 100644
index 3a1e81c..0000000
--- a/src/test/java/org/simplejavamail/utils/mail/smime/SmimeUtilTest.java
+++ /dev/null
@@ -1,116 +0,0 @@
-package org.simplejavamail.utils.mail.smime;
-
-import jakarta.mail.MessagingException;
-import jakarta.mail.Session;
-import jakarta.mail.internet.InternetAddress;
-import jakarta.mail.internet.MimeMessage;
-import jakarta.mail.internet.MimeMultipart;
-import org.bouncycastle.cms.CMSAlgorithm;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.Security;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-import java.util.Properties;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class SmimeUtilTest {
-
- private static final String SignatureAlgorithmRsaPss = "SHA256WITHRSAANDMGF1";
- private SmimeKeyStore alicesKeyStore;
- private SmimeKeyStore bobsKeyStore;
- private Session mailSession;
-
- @BeforeEach
- public void setup() throws MessagingException, KeyStoreException, NoSuchProviderException, CertificateException, IOException, NoSuchAlgorithmException {
- Security.addProvider(new BouncyCastleProvider());
- InputStream alicesKeystoreStream = this.getClass().getClassLoader().getResourceAsStream("alice.p12");
- this.alicesKeyStore = new SmimeKeyStore(alicesKeystoreStream, "alice".toCharArray());
- InputStream bobsKeystoreStream = this.getClass().getClassLoader().getResourceAsStream("bob.p12");
- this.bobsKeyStore = new SmimeKeyStore(bobsKeystoreStream, "bob".toCharArray());
-
- Properties sessionProps = System.getProperties(); // new Properties(); // Fake properties for a fake session
- this.mailSession = Session.getDefaultInstance(sessionProps);
- }
-
- private MimeMessage createTestMessage(String from, String to) throws MessagingException {
- MimeMessage testMessage = new MimeMessage(this.mailSession);
- testMessage.setFrom(new InternetAddress(from));
- testMessage.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(to));
- testMessage.setSubject("This is a test email");
- testMessage.setContent("This is some test content for the test email's body", "text/plain; charset=utf-8");
- return testMessage;
- }
-
- @Test
- public void SuccessfullySignAndValidate() throws MessagingException, IOException {
- MimeMessage testMessage = createTestMessage("alice@testcorp.com", "alice@testcorp.com");
- SmimeKey alicesKey = this.alicesKeyStore.getPrivateKey("alice", "alice".toCharArray());
- MimeMessage signedMessage = SmimeUtil.sign(this.mailSession, null, testMessage, alicesKey);
- MimeMultipart multipartContent = (MimeMultipart) signedMessage.getContent();
- assertThat(SmimeUtil.getStatus(multipartContent)).isEqualTo(SmimeState.SIGNED);
- assertThat(SmimeUtil.checkSignature(multipartContent)).isTrue();
- }
-
- @Test
- public void SuccessfullyEnvelopeAndDecryptDefault() throws MessagingException {
- MimeMessage testMessage = createTestMessage("alice@testcorp.com", "alice@testcorp.com");
- SmimeKey alicesKey = this.alicesKeyStore.getPrivateKey("alice", "alice".toCharArray());
- X509Certificate alicesCert = alicesKey.getCertificate();
- MimeMessage encryptedMessage = SmimeUtil.encrypt(this.mailSession, null,
- SmimeUtil.sign(this.mailSession, null, testMessage, alicesKey),
- alicesCert);
- assertThat(SmimeUtil.getStatus((encryptedMessage))).isEqualTo(SmimeState.ENCRYPTED);
- MimeMessage decryptedMessage = SmimeUtil.decrypt(this.mailSession, encryptedMessage, alicesKey);
- assertThat(SmimeUtil.checkSignature(decryptedMessage)).isTrue();
- }
-
- @Test
- public void SuccessfullyEnvelopeAndDecrypt() throws MessagingException {
- MimeMessage testMessage = createTestMessage("alice@testcorp.com", "alice@testcorp.com");
- SmimeKey alicesKey = this.alicesKeyStore.getPrivateKey("alice", "alice".toCharArray());
- X509Certificate alicesCert = alicesKey.getCertificate();
- MimeMessage encryptedMessage = SmimeUtil.encrypt(this.mailSession,
- SmimeUtil.sign(this.mailSession, null, testMessage, alicesKey, SignatureAlgorithmRsaPss),
- null, alicesCert, KeyEncapsulationAlgorithm.RSA_OAEP_SHA256, CMSAlgorithm.AES256_CBC);
- assertThat(SmimeUtil.getStatus((encryptedMessage))).isEqualTo(SmimeState.ENCRYPTED);
- MimeMessage decryptedMessage = SmimeUtil.decrypt(this.mailSession, encryptedMessage, alicesKey);
- assertThat(SmimeUtil.checkSignature(decryptedMessage)).isTrue();
- }
-
- @Test
- public void AliceToBoEnvelopeAndDecrypt() throws MessagingException {
- MimeMessage testMessage = createTestMessage("alice@testcorp.com", "bob@testcorp.com");
- SmimeKey alicesKey = this.alicesKeyStore.getPrivateKey("alice", "alice".toCharArray());
- SmimeKey bobsKey = this.bobsKeyStore.getPrivateKey("bob", "bob".toCharArray());
- X509Certificate bobsCert = bobsKey.getCertificate();
- MimeMessage encryptedMessage = SmimeUtil.encrypt(this.mailSession,
- SmimeUtil.sign(this.mailSession, null, testMessage, alicesKey, SignatureAlgorithmRsaPss),
- null, bobsCert, KeyEncapsulationAlgorithm.RSA_OAEP_SHA512, CMSAlgorithm.AES256_GCM);
- assertThat(SmimeUtil.getStatus((encryptedMessage))).isEqualTo(SmimeState.ENCRYPTED);
- MimeMessage decryptedMessage = SmimeUtil.decrypt(this.mailSession, encryptedMessage, bobsKey);
- assertThat(SmimeUtil.checkSignature(decryptedMessage)).isTrue();
- }
-
- @Test
- public void BobToAliceEnvelopeAndDecrypt() throws MessagingException {
- MimeMessage testMessage = createTestMessage("bob@testcorp.com", "alice@testcorp.com");
- SmimeKey bobsKey = this.bobsKeyStore.getPrivateKey("bob", "bob".toCharArray());
- SmimeKey alicesKey = this.alicesKeyStore.getPrivateKey("alice", "alice".toCharArray());
- X509Certificate alicesCert = alicesKey.getCertificate();
- MimeMessage encryptedMessage = SmimeUtil.encrypt(this.mailSession,
- SmimeUtil.sign(this.mailSession, null, testMessage, bobsKey, SignatureAlgorithmRsaPss),
- null, alicesCert, KeyEncapsulationAlgorithm.RSA_OAEP_SHA384, CMSAlgorithm.AES192_CCM);
- assertThat(SmimeUtil.getStatus((encryptedMessage))).isEqualTo(SmimeState.ENCRYPTED);
- MimeMessage decryptedMessage = SmimeUtil.decrypt(this.mailSession, encryptedMessage, alicesKey);
- assertThat(SmimeUtil.checkSignature(decryptedMessage)).isTrue();
- }
-}
\ No newline at end of file
diff --git a/src/test/resources/alice-certgen-rsa.sh b/src/test/resources/alice-certgen-rsa.sh
deleted file mode 100755
index b7a2063..0000000
--- a/src/test/resources/alice-certgen-rsa.sh
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/bash
-
-# This script can be used to generate a self-signed test-certificate for the fictional principal "Alice".
-# The certificate is issued on the basis of a standard RSA key-pair.
-
-### Set the openssl version to use.
-openssl_bin="/usr/local/opt/openssl@1.1/bin/openssl"
-account_name="alice"
-priv_key_name="${account_name}.priv"
-certificate_config_filename="${account_name}.cnf"
-validity_days=1825 # Five years, so the tests won't fail too soon.
-
-echo "Generating private RSA key"
-$openssl_bin genpkey -algorithm rsa -pkeyopt rsa_keygen_bits:4096 -pkeyopt rsa_keygen_pubexp:65537 -out ${priv_key_name}.rsakey
-### Save the private key without password protection
-$openssl_bin rsa -in ${priv_key_name}.rsakey -out ${priv_key_name}.nopass.rsakey
-
-echo "Generating self-signed certificate..."
-$openssl_bin req -outform PEM -out ${account_name}.pem -key ${priv_key_name}.nopass.rsakey -keyform PEM -x509 -nodes -batch -days $validity_days -config $certificate_config_filename -pkeyopt rsa_keygen_bits:2048 -sha256
-
-echo "Generating .p12 file with certificate and private key..."
-$openssl_bin pkcs12 -export -in ${account_name}.pem -inkey ${priv_key_name}.nopass.rsakey -out ${account_name}.p12
diff --git a/src/test/resources/alice.cnf b/src/test/resources/alice.cnf
deleted file mode 100644
index e7ba56a..0000000
--- a/src/test/resources/alice.cnf
+++ /dev/null
@@ -1,34 +0,0 @@
-[ req ]
-default_bits = 4096
-distinguished_name = req_distinguished_name
-x509_extensions = x509_ext
-string_mask = utf8only
-
-[ req_distinguished_name ]
-countryName = Country Name (2 letter code)
-countryName_default = AA
-countryName_min = 2
-countryName_max = 2
-stateOrProvinceName = State or Province Name (full name)
-stateOrProvinceName_default = Testprovince
-localityName = Locality Name (eg, city)
-localityName_default = Testtown
-0.organizationName = Organization Name (eg, company)
-0.organizationName_default = Testcorp
-commonName = Common Name
-commonName_default = Alice
-commonName_max = 64
-emailAddress = Email Address
-emailAddress_default = alice@testcorp.com
-emailAddress_max = 64
-
-# Section x509_ext is used when generating a self-signed certificate. I.e., openssl req -x509 ...
-[ x509_ext ]
-
-subjectKeyIdentifier = hash
-authorityKeyIdentifier = keyid,issuer
-
-basicConstraints = CA:FALSE
-keyUsage = critical, digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
-extendedKeyUsage = clientAuth, emailProtection
-#subjectAltName = email:copy
\ No newline at end of file
diff --git a/src/test/resources/alice.p12 b/src/test/resources/alice.p12
deleted file mode 100644
index e0e73b7..0000000
Binary files a/src/test/resources/alice.p12 and /dev/null differ
diff --git a/src/test/resources/bob-certgen-rsa.sh b/src/test/resources/bob-certgen-rsa.sh
deleted file mode 100755
index 91cbb49..0000000
--- a/src/test/resources/bob-certgen-rsa.sh
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/bash
-
-# This script can be used to generate a self-signed test-certificate for the fictional principal "Bob".
-# The certificate is issued on the basis of a RSASSA-PSS key-pair.
-
-### Set the openssl version to use. Must be OpenSSL 1.1 for RSASSA-PSS support
-openssl_bin="/usr/local/opt/openssl@1.1/bin/openssl"
-account_name="bob"
-priv_key_name="${account_name}.priv"
-certificate_config_filename="${account_name}.cnf"
-validity_days=1825 # Five years, so the tests won't fail too soon.
-
-echo "Generating private RSASSA-PSS key"
-$openssl_bin genpkey -algorithm rsa-pss -pkeyopt rsa_keygen_bits:4096 -pkeyopt rsa_keygen_pubexp:65537 -pkeyopt rsa_pss_keygen_md:sha256 -pkeyopt rsa_pss_keygen_mgf1_md:sha256 -pkeyopt rsa_pss_keygen_saltlen:32 -out ${priv_key_name}.rsapsskey
-### Save the private key without password protection
-$openssl_bin rsa -in ${priv_key_name}.rsapsskey -out ${priv_key_name}.nopass.rsapsskey
-
-echo "Generating self-signed certificate..."
-$openssl_bin req -outform PEM -out ${account_name}.pem -key ${priv_key_name}.nopass.rsapsskey -keyform PEM -x509 -nodes -batch -days $validity_days -config $certificate_config_filename -pkeyopt rsa_keygen_bits:4096 -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:32 -sigopt rsa_mgf1_md:sha256 -sha256
-
-echo "Generating .p12 file with certificate and private key..."
-$openssl_bin pkcs12 -export -in ${account_name}.pem -inkey ${priv_key_name}.nopass.rsapsskey -out ${account_name}.p12
diff --git a/src/test/resources/bob.cnf b/src/test/resources/bob.cnf
deleted file mode 100644
index 9a7fd64..0000000
--- a/src/test/resources/bob.cnf
+++ /dev/null
@@ -1,34 +0,0 @@
-[ req ]
-default_bits = 4096
-distinguished_name = req_distinguished_name
-x509_extensions = x509_ext
-string_mask = utf8only
-
-[ req_distinguished_name ]
-countryName = Country Name (2 letter code)
-countryName_default = BB
-countryName_min = 2
-countryName_max = 2
-stateOrProvinceName = State or Province Name (full name)
-stateOrProvinceName_default = Testprovince
-localityName = Locality Name (eg, city)
-localityName_default = Testtown
-0.organizationName = Organization Name (eg, company)
-0.organizationName_default = Testcorp
-commonName = Common Name
-commonName_default = Bob
-commonName_max = 64
-emailAddress = Email Address
-emailAddress_default = bob@testcorp.com
-emailAddress_max = 64
-
-# Section x509_ext is used when generating a self-signed certificate. I.e., openssl req -x509 ...
-[ x509_ext ]
-
-subjectKeyIdentifier = hash
-authorityKeyIdentifier = keyid,issuer
-
-basicConstraints = CA:FALSE
-keyUsage = critical, digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
-extendedKeyUsage = clientAuth, emailProtection
-#subjectAltName = email:copy
\ No newline at end of file
diff --git a/src/test/resources/bob.p12 b/src/test/resources/bob.p12
deleted file mode 100644
index 030791a..0000000
Binary files a/src/test/resources/bob.p12 and /dev/null differ