Java - 电子邮件签名

jul*_*ien 5 java email signing jakarta-mail

我在用 Java 签名电子邮件时遇到了一些问题。

我相信我的代码很好,但是当我在收件箱中收到电子邮件时,它说无法验证签名。

这里的代码 - 非常简单:

  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);
Run Code Online (Sandbox Code Playgroud)

这是我从邮件中得到的:

我使用 .pfx 用该命令生成梯形图:

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

它由权威和一切签署。

所以我相信导入和代码对我来说看起来不错,但它不起作用,我想知道我错过了什么。

谢谢 !!

Tho*_*win 1

据我所知,GoDaddy 不出售电子邮件签名证书。您可能想阅读mozilla 的这篇评论这篇文章,以了解如何获取它。本文解释了几种类型的证书:

  1. Web服务器认证证书
  2. 统一通信 (UC) 证书
  3. 通配符证书
  4. 扩展验证证书
  5. 低保证/域验证证书
  6. 代码签名证书
  7. 电子邮件证书
  8. 根签名证书

了解哪种 SSL 证书类型可以帮助您避免许多问题,例如尝试使用证书执行不该执行的操作。