1

I tried using bouncy castle but it says digital signature isn't valid/ can't be verified at receiver end.

I don't want to encrypt the email, only add digital signature.

Please see below code snippet where I'm passing MimeMessage and returning signed MimeMessage, which is then send using Java mail sender

        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");

        CommandMap.setDefaultCommandMap(mailcap);

        Security.addProvider(new BouncyCastleProvider());

        KeyStore ks = KeyStore.getInstance("PKCS12");
        File file = ResourceUtils.getFile(certificatePath);
        ks.load(new FileInputStream(file), certificatePassword.toCharArray());

        Enumeration<String> es = ks.aliases();
        String alias = "";
        boolean isAlias = false;
        while (es.hasMoreElements()) {
            alias = es.nextElement();

            if (isAlias = ks.isKeyEntry(alias)) {
                break;
            }
        }
        if (isAlias) {
            KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry) ks.getEntry(alias, new KeyStore.PasswordProtection(certificatePassword.toCharArray()));
            PrivateKey myPrivateKey = pkEntry.getPrivateKey();

            Certificate[] chain = ks.getCertificateChain(alias);
            chain[0].verify(chain[1].getPublicKey());

            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);

            ASN1EncodableVector attributes = new ASN1EncodableVector();
            attributes.add(new SMIMEEncryptionKeyPreferenceAttribute(
                    new IssuerAndSerialNumber(
                            new X500Name(((X509Certificate) chain[0])
                                    .getIssuerDN().getName()),
                            ((X509Certificate) chain[0]).getSerialNumber())));
            attributes.add(new SMIMECapabilitiesAttribute(capabilities));

            SMIMESignedGenerator signer = new SMIMESignedGenerator();
            signer.addSigner(
                    myPrivateKey,
                    (X509Certificate) chain[0],
                    "DSA".equals(myPrivateKey.getAlgorithm()) ? SMIMESignedGenerator.DIGEST_SHA1
                            : SMIMESignedGenerator.DIGEST_MD5,
                    new AttributeTable(attributes), null);

            List certList = new ArrayList();
            certList.add(chain[0]);
            CertStore certs = CertStore.getInstance("Collection",
                    new CollectionCertStoreParameters(certList), "BC");
            signer.addCertificatesAndCRLs(certs);

            MimeMultipart mm = signer.generate(mimeMessage, "BC");
            MimeMessage signedMessage = new MimeMessage(mimeMessage);

            signedMessage.setContent(mm);
            signedMessage.saveChanges();
            LOG.info("{EMAIL SIGNING] Successfully signed email");
            return signedMessage;

I'm able to read the mail but the mail client shows error saying certificates isn't valid/verified.

I have followed this example

Gaurav Pingale
  • 424
  • 1
  • 5
  • 11
  • 1
    @GhostCat sorry I posted question from mobile app. I have added the code snippet and reference to example I'm following, hope this helps. Thanks – Gaurav Pingale Jun 27 '19 at 08:47
  • 1
    Why do you consider it necessary to valide your own certificate chain? – user207421 Jun 27 '19 at 10:46
  • @user207421 I read somewhere I need to verify it. Even without chain[0].verify(chain[1].getPublicKey()) I get the same results – Gaurav Pingale Jun 27 '19 at 11:06
  • Maybe you need to add in your mail client configuration the CA certificate that issued the signer certificate and all the certificate chain. Well, at least you should check if it has the certificate root. – Egl Jun 28 '19 at 18:01
  • Did you try installing the certificate in your PC ? Add the CA to the trusted CAs ? – Sree Vishnu May 03 '21 at 04:25

0 Answers0