2014-09-19 152 views
1

我正尝试从Java邮件(充气城堡1.51)发送S/MIME签名和加密邮件给我自己,以将其发送给我的Outlook。使用Outlook 2010查看S/MIME邮件

我能够发送正常的邮件,但接收是一个问题,因为Outlook不想打开邮件。以下是我尝试打开时出现的错误:

无法打开此项目。您的数字身份证名称不能被底层安全系统找到。

使用p7m查看器可以看到相同的邮件(保存到本地文件的eml格式),表明P12证书已正确安装在我的笔记本电脑上。我在我的Java邮件代码中安装了与我在Keystore中使用的P12文件相同的文件。

我做错了什么? Outlook的问题是否结束?我正在使用Office 365,并希望添加p7m Viewer也无法打开从Outlook WebMail下载的smime.p7m。我收到的错误是:

该文件已损坏;签名信息可能会丢失。

下面是我用来加密/发送邮件的Java代码。

public class BCTest { 

    public static final String pkcs12Keystore = "C:/Development/Workspace/BouncyCastle_SecureMail/resources/cert/StartCom.p12"; 
    public static final String ksPassword = "ksPassword"; 

    public static final String sendFile = "C:/Development/Workspace/BouncyCastle_SecureMail/resources/hello.txt"; 
    public static final String outputFile = "C:/Development/Workspace/BouncyCastle_SecureMail/output/Encrypted.eml"; 
    public static final String message = "Hi There!!"; 
    public static final String frAddress = "[email protected]"; 
    public static final String toAddress = "[email protected]"; 

    public static final String host = "outlook.office365.com"; 
    public static final int port = 587; 
    public static final String userName = "[email protected]"; 
    public static final String password = "password"; 

    public static void main(String[] args) { 
     send(); 
    } 

    public static void send() { 
     try { 
      System.out.println("Setting Mailcap"); 
      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); 

      /* Add BC */ 
      System.out.println("Setting Bouncy Castle as provider"); 
      Security.addProvider(new BouncyCastleProvider()); 

      /* Open the keystore */ 
      System.out.println("Opening the keystore: " + pkcs12Keystore + " using password " + ksPassword); 
      KeyStore keystore = KeyStore.getInstance("PKCS12", "BC"); 
      keystore.load(new FileInputStream(pkcs12Keystore), ksPassword.toCharArray()); 

      // Find the first legit alias in the keystore and use it 
      System.out.println("Getting the keystore alias"); 
      Enumeration<String> e = keystore.aliases(); 
      String keyAlias = null; 
      while (e.hasMoreElements() && (keyAlias == null)) { 
       String alias = e.nextElement(); 
       keyAlias = keystore.isKeyEntry(alias) ? alias : null; 
      } 
      if (keyAlias == null) { 
       throw new Exception("Can't find a private key!"); 
      } 

      Certificate[] chain = keystore.getCertificateChain(keyAlias); 

      /* Get the private key to sign the message with */ 
      System.out.println("Getting the private key"); 
      PrivateKey privateKey = (PrivateKey) keystore.getKey(keyAlias, ksPassword.toCharArray()); 
      if (privateKey == null) { 
       throw new Exception("No private key for alias: " + keyAlias); 
      } 

      /* Create Email body */ 
      System.out.println("Creating the Email body"); 
      MimeBodyPart messageBodyPart = new MimeBodyPart(); 
      messageBodyPart.setContent(message, "text/html"); 

      /* Attach the file to encrypt */ 
      System.out.println("Creating the attachment"); 
      FileDataSource fds = new FileDataSource(sendFile); 
      MimeBodyPart attachPart = new MimeBodyPart(); 
      attachPart.setDataHandler(new DataHandler(fds)); 
      attachPart.setFileName(fds.getName()); 

      System.out.println("Adding body & attachment to mail"); 
      MimeMultipart bodyMulti = new MimeMultipart(); 
      bodyMulti.addBodyPart(messageBodyPart); 
      bodyMulti.addBodyPart(attachPart); 

      System.out.println("Setting mail properties"); 
      Session session = Session.getDefaultInstance(System.getProperties()); 
      MimeMessage body = new MimeMessage(session); 
      body.setFrom(new InternetAddress(frAddress)); 
      body.setRecipient(Message.RecipientType.TO, new InternetAddress(toAddress)); 
      body.setSentDate(new Date()); 
      body.setSubject("Encrypted Mail"); 
      body.setContent(bodyMulti, bodyMulti.getContentType()); 
      body.saveChanges(); 

      /* Create the SMIMESignedGenerator */ 
      System.out.println("Creating 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); 

      System.out.println("Creating the ASN1EncodableVector"); 
      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)); 

      System.out.println("Adding certificate"); 
      List<X509Certificate> certList = new ArrayList<X509Certificate>(); 
      certList.add((X509Certificate) chain[0]); 

      SMIMESignedGenerator gen = new SMIMESignedGenerator("binary"); 
      gen.addSignerInfoGenerator(new JcaSimpleSignerInfoGeneratorBuilder().setProvider("BC").build("SHA1withRSA", privateKey, 
        (X509Certificate) chain[0])); 
      gen.addCertificates(new JcaCertStore(certList)); 

      MimeMultipart multiPart = gen.generate(body); 

      MimeMessage signedMessage = new MimeMessage(session); 
      System.out.println("Creating Mime Message"); 

      @SuppressWarnings("unchecked") 
      Enumeration<String> headers = body.getAllHeaderLines(); 
      while (headers.hasMoreElements()) { 
       signedMessage.addHeaderLine(headers.nextElement()); 
      } 
      signedMessage.setContent(multiPart); 
      signedMessage.saveChanges(); 

      /* Create the encrypter and encrypt the message */ 
      System.out.println("Encrypting Mime Message"); 
      SMIMEEnvelopedGenerator fact = new SMIMEEnvelopedGenerator(); 
      fact.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator((X509Certificate) chain[0]).setProvider("BC")); 

      MimeBodyPart encryptedPart = fact.generate(signedMessage, new JceCMSContentEncryptorBuilder(CMSAlgorithm.RC2_CBC, 40) 
        .setProvider("BC").build()); 
      encryptedPart.setHeader("Content-Transfer-Encoding", "binary"); 

      ByteArrayOutputStream out = new ByteArrayOutputStream(); 
      encryptedPart.writeTo(out); 

      /* Create a new MimeMessage for the encrypted and signed content */ 
      System.out.println("Setting mail server properties"); 
      Properties props = new Properties(); 
      props.put("mail.smtp.host", host); 
      props.put("mail.smtp.port", port); 
      props.put("mail.smtp.auth", "true"); 
      props.put("mail.smtp.starttls.enable", "true"); 

      Session smtpSession = Session.getInstance(props, new Authenticator() { 
       @Override 
       protected PasswordAuthentication getPasswordAuthentication() { 
        return new PasswordAuthentication(userName, password); 
       } 
      }); 

      MimeMessage smtpMessage = new MimeMessage(smtpSession, new ByteArrayInputStream(out.toByteArray())); 
      smtpMessage.saveChanges(); 

      /* Set all original MIME headers in the encrypted message */ 
      @SuppressWarnings("unchecked") 
      Enumeration<String> orgHeaders = body.getAllHeaderLines(); 
      while (orgHeaders.hasMoreElements()) { 
       String headerLine = (String) orgHeaders.nextElement(); 
       /* Do not override content-* headers from the original message */ 
       if (!Strings.toLowerCase(headerLine).startsWith("content-")) { 
        smtpMessage.addHeaderLine(headerLine); 
       } 
      } 

      System.out.println("Creating eml file as location: " + outputFile); 
      smtpMessage.writeTo(new FileOutputStream(outputFile)); 

      System.out.println("Sending Mail"); 
      Transport.send(smtpMessage); 
      System.out.println("Mail Sent"); 

     } catch (SMIMEException ex) { 
      ex.getUnderlyingException().printStackTrace(System.err); 
      ex.printStackTrace(System.err); 
     } catch (Exception ex) { 
      ex.printStackTrace(System.err); 
     } 
    } 
} 

PLZ帮助!

问候

回答

0

这听起来像你需要导入您的私钥(在的.p12格式)到Outlook中的个人信任存储区。这里是如何做到这一点:

导入您的个人证书:

从工具菜单,选择Internet选项。打开内容选项卡, 并单击证书。在“证书”窗口中,选择您的 证书并单击导入。通过证书导入 向导导入您的证书文件。浏览正确的 文件时,请将“文件类型”字段从* .cer,* .crt更改为* .pfx, * .p12。当证书最初导出时,系统会提示您输入用于加密私钥的密码。输入它。您将 想要选择启用强大的私钥保护,并将此密钥标记为可导出单选按钮。你可以选择你想要的任何存储 。将所有证书放入Personal 商店是最容易的。点击完成退出向导。执行导入操作需要花费一些时间到 。弹出一个窗口说应用程序是 创建一个受保护的项目,并为您选择安全级别。 把它留在中等(默认)是好的。点击确定。弹出一个窗口 表示导入成功。点击确定。

来源:https://fermi.service-now.com/kb_view.do?sysparm_article=KB0010813

+0

另外,您也可以直接双击.p12文件开始导入过程 – Jeff 2014-11-13 18:09:49

+0

感谢杰夫。是的,试过但没有工作!我收到了同样的错误。 – Sumit 2014-11-17 07:47:49

+0

我在Outlook中遇到了一个问题,在其中一个电子邮件标题中出现了无意中的换行符。删除换行突然让Outlook开心,我可以再次查看消息。其他客户更容忍畸形标题。难道你的电子邮件在某个地方有一个不好的标题? – Jeff 2014-12-02 16:53:43

相关问题