From dde9d815631647efea23a97cf89dfde7989d452e Mon Sep 17 00:00:00 2001 From: bbottema Date: Sat, 13 Apr 2019 22:30:39 +0200 Subject: [PATCH 1/2] Ignore IntelliJ project files --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 91a5ca7..9818eb8 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ .project .classpath .checkstyle +/.idea +/*.iml From 97a76ab0a5359645435788c807416ff3cb78b5a8 Mon Sep 17 00:00:00 2001 From: bbottema Date: Sat, 13 Apr 2019 22:37:12 +0200 Subject: [PATCH 2/2] #5: Implement API to return the (CN) subject of the first certificate on a MimePart. This subject is actually the email address of the person to which the certificate was issued to, a value often used by email clients to display "Signed by: ". --- .../utils/mail/smime/SmimeUtil.java | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/src/main/java/net/markenwerk/utils/mail/smime/SmimeUtil.java b/src/main/java/net/markenwerk/utils/mail/smime/SmimeUtil.java index 60b6e46..0456d04 100644 --- a/src/main/java/net/markenwerk/utils/mail/smime/SmimeUtil.java +++ b/src/main/java/net/markenwerk/utils/mail/smime/SmimeUtil.java @@ -60,7 +60,10 @@ 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.cert.X509CertificateHolder; import org.bouncycastle.cert.jcajce.JcaCertStore; import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; @@ -491,6 +494,61 @@ private static boolean checkSignature(SMIMESigned smimeSigned) throws MessagingE 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 {