2011-12-21 81 views
1

我在使用x509證書驗證S/Mime簽名消息時遇到了一些問題。這是我的代碼:使用x509證書進行S/MIME驗證

public class verifyMsg { 

private static void verify(SMIMESignedParser s) throws Exception { 

    Security.addProvider(new BouncyCastleProvider()); 
    System.out.println("wbilem"); 
    CertStore certs = s.getCertificatesAndCRLs("Collection", "BC"); 

    SignerInformationStore signers = s.getSignerInfos(); 
    Collection c = signers.getSigners(); 
    Iterator it = c.iterator(); 

    while (it.hasNext()) { 
     File f = new File("signature.crt"); 
     FileInputStream fis = new FileInputStream(f); 
     DataInputStream dis = new DataInputStream(fis); 
     byte[] keyBytes = new byte[(int) f.length()]; 
     dis.readFully(keyBytes); 
     dis.close(); 
     fis.close(); 
     SignerInformation signer = (SignerInformation) it.next(); 
     Collection certCollection = certs.getCertificates(signer.getSID()); 
     Iterator certIt = certCollection.iterator(); 
     FileInputStream fr = new FileInputStream("signature.crt"); 
     CertificateFactory cf = CertificateFactory.getInstance("X509"); 
     X509Certificate cert = (X509Certificate) cf.generateCertificate(fr); 


     if (signer.verify(cert, "BC")) { //problem is there... 
      System.out.println("signature verified"); 
     } else { 
      System.out.println("signature failed!"); 
     } 

    } 
} 

public static void main(String[] args) throws Exception { 
    Properties props = System.getProperties(); 
    Session session = Session.getDefaultInstance(props, null); 

    try { 
     FileInputStream fr = new FileInputStream("signature.crt"); 
     CertificateFactory cf = CertificateFactory.getInstance("X509"); 
     X509Certificate c = (X509Certificate) cf.generateCertificate(fr); 
     System.out.println("Read in the following certificate:"); 
     System.out.println("\tCertificate for: " + c.getSubjectDN()); 
     System.out.println("\tCertificate issued by: " + c.getIssuerDN()); 
     System.out.println("\tThe certificate is valid from " + c.getNotBefore() + " to " + c.getNotAfter()); 
     System.out.println("\tCertificate SN# " + c.getSerialNumber()); 
     System.out.println("\tGenerated with " + c.getSigAlgName()); 
     System.out.println(c.getPublicKey()); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 

    try { 
     MimeMessage msg = new MimeMessage(session, new SharedFileInputStream("G:\\MIME.txt")); 
     if (msg.isMimeType("multipart/signed")) { 

      SMIMESignedParser s = new SMIMESignedParser((MimeMultipart) msg.getContent()); 
      System.out.println("Status:"); 
      verify(s); 
     } else if (msg.isMimeType("application/pkcs7-mime")) { 

      // in this case the content is wrapped in the signature block. 
      // 
      SMIMESignedParser s = new SMIMESignedParser(msg); 
      System.out.println("Status1:"); 
      verify(s); 
     } else { 
      System.err.println("Not a signed message!"); 
     } 

    } catch (MessagingException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (CMSException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
} 

}

,我有與此異常的問題:

CMSSignerDigestMismatchException:消息摘要屬性值不匹配的計算值。我不知道我做錯了什麼。我使用jdk 1.4.2。

回答

1

我只是發現問題與消息。我將字節數組轉換爲字符串,然後將此字符串轉換爲輸入流。現在我給輸入流字節數組沒有轉換,一切都OK :)

+0

你在代碼中做了什麼確切的改變,我面臨同樣的問題可以請幫助代碼片段,你在你的代碼中改變了什麼。 – Swapnil 2013-11-19 15:45:27

0

我解決了這個問題。如果您使用S/MIME簽名數據,然後根據S/MIME標準,我們應該有MIME版本,內容類型。 ..etc和標題與要用空行標記的消息分開。當消息的類型爲「text/plain」時,我們不會向消息添加標題,這很明顯。但是如果使用S/MIME來簽名數據時,它會查找S/MIME標準頭文件,並在摘要中出現類似錯誤的問題。

在簽名前將以下標題添加到郵件 MIME版本:1.0 Content-Type:text/plain;

或者只是在消息前添加一個空白行。

上面的方法對我來說工作得很好。