Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java - Email Signing

I have some issues with signing emails in java.

I believe my code is good but when I receive the email in my inbox, it says that it is unable to verify the signature.

Here the code - Pretty straightforward :

  boolean isAlias = false;

        // Add BouncyCastle content handlers to command map
        MailcapCommandMap mailcap = (MailcapCommandMap) CommandMap.getDefaultCommandMap();

        mailcap.addMailcap("application/pkcs7-signature;; x-java-content-handler=org.bouncycastle.superman.mail.smime.handlers.pkcs7_signature");
        mailcap.addMailcap("application/pkcs7-mime;; x-java-content-handler=org.bouncycastle.superman.mail.smime.handlers.pkcs7_mime");
        mailcap.addMailcap("application/x-pkcs7-signature;; x-java-content-handler=org.bouncycastle.superman.mail.smime.handlers.x_pkcs7_signature");
        mailcap.addMailcap("application/x-pkcs7-mime;; x-java-content-handler=org.bouncycastle.superman.mail.smime.handlers.x_pkcs7_mime");
        mailcap.addMailcap("multipart/signed;; x-java-content-handler=org.bouncycastle.superman.mail.smime.handlers.multipart_signed");

        CommandMap.setDefaultCommandMap(mailcap);

        Security.addProvider(new BouncyCastleProvider());

        KeyStore keyStore = KeyStore.getInstance("JKS");

        InputStream ins = SigningEmail.class.getResourceAsStream("/keystore.jks");

        // Provide location of Java Keystore and password for access
        keyStore.load(ins,"changeit".toCharArray());

        // Find the first legit alias in the keystore and use it
        Enumeration<String> es = keyStore.aliases();
        String alias = "";
        while (es.hasMoreElements()) {
            alias = es.nextElement();

            // Does alias refer to a private key? Assign true/false to isAlias & evaluate
            if (isAlias = keyStore.isKeyEntry(alias)) {
                break;
            }
        }
        if (isAlias) {
            KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(alias, new KeyStore.PasswordProtection("***".toCharArray()));
            PrivateKey myPrivateKey = pkEntry.getPrivateKey();

            // Load certificate chain
            Certificate[] chain = keyStore.getCertificateChain(alias);

            // Create the SMIMESignedGenerator
            SMIMECapabilityVector capabilities = new SMIMECapabilityVector();
            capabilities.addCapability(SMIMECapability.dES_EDE3_CBC);
            capabilities.addCapability(SMIMECapability.rC2_CBC, 128);
            capabilities.addCapability(SMIMECapability.dES_CBC);
            capabilities.addCapability(SMIMECapability.aES256_CBC);
            capabilities.addCapability(SMIMECapability.aES128_CBC);
            capabilities.addCapability(SMIMECapability.aES192_CBC);

            //Cert info
            X500Name x500 = new X500Name(((X509Certificate) chain[0]).getIssuerDN().getName());
            IssuerAndSerialNumber serialNumber = new IssuerAndSerialNumber(x500 ,  ((X509Certificate) chain[0]).getSerialNumber()) ;

            ASN1EncodableVector signedAttrs = new ASN1EncodableVector();
            signedAttrs.add(new SMIMEEncryptionKeyPreferenceAttribute(serialNumber));
            signedAttrs.add(new SMIMECapabilitiesAttribute(capabilities));

            //Set X509
            X509Certificate cert = (X509Certificate) keyStore.getCertificate(alias);
            List<X509Certificate> certList = new ArrayList<X509Certificate>();
            certList.add(cert);
            Store certs = new JcaCertStore(certList);


            //Signing generator
            SMIMESignedGenerator gen = new SMIMESignedGenerator();
            gen.addSignerInfoGenerator(
                      new JcaSimpleSignerInfoGeneratorBuilder()
                           .setProvider("BC")
                           .setSignedAttributeGenerator(new AttributeTable(signedAttrs))
                           .build("SHA1withRSA", myPrivateKey, cert));
            gen.addCertificates(certs);

            MimeMessage cloneOriginal = new MimeMessage(body);

            //Sign
            MimeMultipart mainPart = gen.generate(body , "BC");

            // Set the content of the signed message
            cloneOriginal.setContent(mainPart, mainPart.getContentType());  
            cloneOriginal.saveChanges();

            // Send the message
            sender.send(cloneOriginal);

Here what I get from mail :

I used the .pfx to generate the keystone with that command :

keytool -importkeystore -srckeystore /Users/sign.pfx -srcstoretype pkcs12 -destkeystore /Users/keystore.jks -deststoretype jks

It signed from an authority and everything.

So the import and the code looks good to me I believe but it does not work, and I am wondering what I am missing.

Thanks !!

like image 914
julien Avatar asked Oct 31 '22 20:10

julien


2 Answers

As far as I know, GoDaddy does not sell email signing certificate. You may want to read this review by mozilla and this to know how to obtain one. This article explain several types of certificate:

  1. web server authentication certificate
  2. Unified Communications (UC) certificate
  3. wildcard certificate
  4. Extended Validation certificate
  5. low assurance/domain-validated certificate
  6. code signing certificate
  7. e-mail certificate
  8. root signing certificate

Knowing which SSL certificate type can help you avoid many problems such as trying to use a certificate for something that it isn't meant to do.

like image 173
ThomasEdwin Avatar answered Nov 12 '22 16:11

ThomasEdwin


I had to edit the providers to get your code run but then it worked for me. Thanks!

MailcapCommandMap mailcap = (MailcapCommandMap) CommandMap.getDefaultCommandMap();

mailcap.addMailcap("application/pkcs7-signature;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_signature");
mailcap.addMailcap("application/pkcs7-mime;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_mime");
mailcap.addMailcap("application/x-pkcs7-signature;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.x_pkcs7_signature");
mailcap.addMailcap("application/x-pkcs7-mime;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.x_pkcs7_mime");
mailcap.addMailcap("multipart/signed;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.multipart_signed");
mailcap.addMailcap("multipart/signed;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.multipart_signed");
like image 24
Jérôme Avatar answered Nov 12 '22 15:11

Jérôme