Java - 电子邮件签名

问题描述:

我在使用java签署电子邮件时遇到了一些问题。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生成与该命令的基石:

密钥工具 - importkeystore -srckeystore /Users/sign.pfx -srcstoretype pkcs12 -destkeystore /Users/keystore.jks -deststoretype jks

它从权威和一切签署。

因此,导入和代码看起来不错,我相信但它不工作,我想知道我缺少什么。

谢谢!

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

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

知道哪些SSL证书类型可以帮助您避免许多问题,如要使用的东西,它不是为了做一个证书。

我不得不编辑提供程序来让代码运行,但后来它对我有用。谢谢!

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