Java - 电子邮件签名

时间:2014-07-14 14:17:18

标签: java email javamail signing

我在使用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);

这是我从邮件中得到的:

我使用.pfx用该命令生成keystone:

  

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

它从权威和所有事情签署。

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

谢谢!

2 个答案:

答案 0 :(得分:1)

据我所知,GoDaddy不出售电子邮件签名证书。您可能需要阅读this review by mozillathis以了解如何获取一个。 This article解释了几种类型的证书:

  1. Web服务器身份验证证书
  2. 统一通信(UC)证书
  3. 通配符证书
  4. 扩展验证证书
  5. 低保证/域验证证书
  6. 代码签名证书
  7. 电子邮件证书
  8. root签名证书
  9. 了解哪种SSL证书类型可以帮助您避免许多问题,例如尝试将证书用于其不应该做的事情。

答案 1 :(得分:0)

我必须编辑提供程序才能运行代码,但这对我有用。谢谢!

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