2012-10-16 151 views
2

我使用過期的公用證書在Java中驗證數字簽名(PKCS#7)時遇到問題。 有關更多詳細信息,請在.NET中對數據進行簽名,然後使用Java進行驗證,但在Java中籤名數據時將出現「證書過期」錯誤,並在Java中驗證。在這兩種情況下,我使用了相同的驗證方法,相同的私鑰和公共證書。如何繞過證書驗證數字簽名時驗證已過期

請告訴我爲什麼?如果我想在驗證數字簽名時繞過證書過期驗證,該怎麼辦?

謝謝,在C#.NET

註冊方法

private static string SignData(byte[] data, string pkcs12FileUrl, string pkcs12Password) 
    { 
     X509Certificate2 signerCert = new X509Certificate2(pkcs12FileUrl, pkcs12Password); 
     ContentInfo content = new ContentInfo(data); 
     SignedCms signed = new SignedCms(content, true); 
     CmsSigner signer = new CmsSigner(signerCert); 
     signer.IncludeOption = X509IncludeOption.None; 
     signed.ComputeSignature(signer); 

     return Convert.ToBase64String(signed.Encode()); 
    } 

在Java的註冊方法

public static String SignData(byte[] data, String pkcs12File, String pkcs12Password) 
    throws Exception 
{ 
     if(Security.getProvider("BC")==null) 
     { 
      Security.addProvider(new BouncyCastleProvider()); 
     } 
     KeyStore keyStore = getPkcs12Info(pkcs12File, pkcs12Password); 

     Enumeration<String> aliasesList = keyStore.aliases(); 
     String aliasName = ""; 
     while (aliasesList.hasMoreElements()) 
     { 
      aliasName = aliasesList.nextElement().toString(); 
     } 

     X509Certificate signerCert = (X509Certificate) keyStore.getCertificate(aliasName); 
     PrivateKey privateKey = (PrivateKey) keyStore.getKey(aliasName,pkcs12Password.toCharArray()); 

     CMSSignedDataGenerator Signer = new CMSSignedDataGenerator(); 
     Signer.addSigner(privateKey, signerCert, CMSSignedDataGenerator.DIGEST_SHA1); 

     CMSProcessableByteArray digestContent = new CMSProcessableByteArray(data); 

     CMSSignedData Signed = Signer.generate(digestContent, false, "BC"); 
     return Base64.encode(Signed.getEncoded()); 

} 

private static KeyStore getPkcs12Info(String pkcs12File, String pkcs12Password) throws Exception 
{ 
    //KeyStore keyStore = KeyStore.getInstance("PKCS12", "BC"); 
     KeyStore keyStore = KeyStore.getInstance("PKCS12"); 
     keyStore.load(new FileInputStream(pkcs12File), pkcs12Password.toCharArray()); 
     return keyStore; 
} 

在Java中

public static boolean VerifySignature(byte[] data, String digitalSignature, InputStream publicCertFile) throws Exception 
{ 
    if(Security.getProvider("BC")==null) 
    { 
     Security.addProvider(new BouncyCastleProvider()); 
    } 
    CertificateFactory factory = CertificateFactory.getInstance("X509","BC"); 
    X509Certificate publicCert = (X509Certificate)factory.generateCertificate(publicCertFile); 
    CMSProcessableByteArray digestContent = new CMSProcessableByteArray(data); 
    CMSSignedData Signed = new CMSSignedData(digestContent,Base64.decode(digitalSignature)); 
    SignerInformation Signer=(SignerInformation)Signed.getSignerInfos().getSigners().iterator().next(); 
    return Signer.verify(publicCert, "BC"); 
} 
+1

我更新的代碼你能提供(鏈接),具有涉及這一問題,並在公共證書樣本的簽名? – mkl

+1

謝謝你考慮我的話題。我的答案已經解決了問題。 – anhtuangv

回答

1

驗證方法,如果你簽署一份文件與已經過期的證書,已經沒有意義了。證書已經過期,不應該被用於新的用途。驗證簽名證書已過期的文檔是有意義的,因爲至少您知道簽名文檔時證書是有效的。除非它明顯是由.NET簽署的。聽起來像.NET中的一個bug給我。

+1

我不確定它是否是一個.NET錯誤,但我發現這個鏈接http://comments.gmane.org/gmane.comp.encryption.bouncy-castle.devel/768與我的問題相關。但是我仍然不知道如何解決這個問題。 – anhtuangv

+1

@anhtuangv如果通過'修復'你的意思是'使用Java和過期的證書籤名文檔',你*不能*修復它,而你*不想*修復它。這是一種不安全的做法。解決它的方法是更新證書。 – EJP

+1

是的,最好像你說的那樣更新證書。但是,就我而言,我不想在證書過期時續訂證書。因爲我只是使用數字簽名來驗證Web服務之間的請求和響應消息。如果我續約,我必須將新證書發送給我的所有合作伙伴,我的所有合作伙伴也必須將新證書(如果證書已過期)發送給我。而且,如果我忘記這樣做,系統將會出錯。 – anhtuangv

1

我發現了這個話題Java implementation of C# SignedCms,並試圖改變我的Sign方法在Java中的代碼。最後,它工作得很好。在這裏,在Java的

public static String SignData(byte[] data, String pkcs12File, String pkcs12Password) 
    throws Exception 
{ 
     ByteArrayOutputStream byteArrOut = new ByteArrayOutputStream(); 
     DEROutputStream derOut = new DEROutputStream(byteArrOut); 
     try 
     { 
      if(Security.getProvider("BC")==null) 
      { 
       Security.addProvider(new BouncyCastleProvider()); 
      } 
      KeyStore keyStore = getPkcs12Info(pkcs12File, pkcs12Password); 

      Enumeration<String> aliasesList = keyStore.aliases(); 
      String aliasName = ""; 
      while (aliasesList.hasMoreElements()) 
      { 
       aliasName = aliasesList.nextElement().toString(); 
      } 

      X509Certificate signerCert = (X509Certificate) keyStore.getCertificate(aliasName); 
      PrivateKey privateKey = (PrivateKey) keyStore.getKey(aliasName, pkcs12Password.toCharArray()); 

      List certList = new ArrayList(); 
      Store certs = new JcaCertStore(certList); 

      JcaSimpleSignerInfoGeneratorBuilder builder = new JcaSimpleSignerInfoGeneratorBuilder().setProvider("BC").setDirectSignature(true); 


      CMSSignedDataGenerator signer = new CMSSignedDataGenerator(); 
      signer.addSignerInfoGenerator(builder.build("SHA1withRSA", privateKey, signerCert)); 
      signer.addCertificates(certs); 

      CMSTypedData msg = new CMSProcessableByteArray(data); 
      CMSSignedData signed = signer.generate(msg, false); 

      derOut.writeObject(signed.toASN1Structure().toASN1Primitive()); 
      return Base64.encode(byteArrOut.toByteArray()); 
     } 
     catch(Exception ex) 
     { 
      throw ex; 
     } 
     finally 
     { 
      derOut.close(); 
      byteArrOut.close(); 
     } 

}