2014-10-28 91 views
0

我的應用程序使用java安全API簽名文件並進行驗證。 簽名時,我使用PFX文件和密碼作爲輸入,簽名後我使用字節生成簽名文件。 驗證過程中,我使用簽名文件,證書文件和簽名文件作爲輸入。 請找我正在使用的驗證代碼如下:我的代碼可以驗證自簽名證書,但在使用威瑞信頒發證書時失敗

// KeyFilePath= path of certificate file 
// fileToVerify = path of signed file 
// signatureFilePath = path of signature file 



InputStream inputStream = new FileInputStream(KeyFilePath); 
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); 
X509Certificate x509Certificate = (X509Certificate) certificateFactory.generateCertificate(inputStream); 

// input the signature bytes 
String sigFile = signatureFilePath; 

FileInputStream sigFileInputStream = new FileInputStream(sigFile); 
byte[] sigToVerify = new byte[sigFileInputStream.available()]; 
sigFileInputStream.read(sigToVerify); 
sigFileInputStream.close(); 

PublicKey pubKey = x509Certificate.getPublicKey(); 
Signature signature = Signature.getInstance(signAlgorithm); 

signature.initVerify(pubKey); 

// Update and verify the data 
try { 
    FileInputStream dataFileInputStream = new FileInputStream(fileToVerify); 
    BufferedInputStream bufferedInputStream = new BufferedInputStream(dataFileInputStream); 

    byte[] buffer = new byte[IVerifyDigitalSignature.BYTE_SIZE]; 
    int bufferedInputStreamLength; 

    while (bufferedInputStream.available() != IVerifyDigitalSignature.ZERO_LENGTH) { 
     bufferedInputStreamLength = bufferedInputStream.read(buffer); 
     signature.update(buffer, IVerifyDigitalSignature.ZERO_LENGTH, bufferedInputStreamLength); 
    } 

    bufferedInputStream.close(); 

    // Verify the Signature 
    x509Certificate.verify(pubKey); 
    verifyDigitalSignature = signature.verify(sigToVerify); 

請幫我解決同樣的,因爲它尚未關閉。

+0

'byte [] sigToVerify = new byte [sigFileInputStream.available()];'記錄爲'InputStream.available()'的不正確使用,所以將它與0比較以作爲流結束的測試。 – EJP 2014-11-05 09:24:15

+1

自簽名證書是由其「自己的」密鑰簽署的,或者更確切地說是由其公共一半在證書中的私鑰的一半簽名的。因此'x509certificate.verify(pubkey)'成功了,但基本上沒用,因爲任何攻擊者都可以自簽署欺詐證書。 CA簽名的證書由CA(私人)密鑰簽名,因此,通過查找* parent *(CA)證書並使用*那個pubkey,子證書可以並且通常必須被驗證,迭代直到您到達根CA是自簽名的,並且只能因爲它是手動信任的(通常位於信任庫文件中)而可以信任。 ... – 2014-11-05 12:27:01

+1

...除了有效的簽名外,還有其他一些需要驗證的證書鏈是有效的(不僞造或被破壞的)。這通常稱爲PKI驗證,或者更具體地說PKIX驗證,因爲該格式(X.509證書等)爲因特網分析)是最常見的。對於Java,http://docs.oracle.com/javase/7/docs/technotes/guides/security/certpath/CertPathProgGuide.html是一個相當不錯的開始。 – 2014-11-05 12:29:45

回答

1

如果您想在此做自己,是你必須多麼漫長,它遍歷從信任錨鏈中的證書到您想要的證書, (它可以爲不同的CA,類有所不同,在不同的時間)。 使用來自「父級」(更高級別)證書的公鑰驗證每個「子級」證書(較低級別)證書上的簽名僅爲 的一小部分;有很多需要其他步驟。 通常只有找到正確的證書可能是一個問題;如果你已經有一個正確的鏈條,你有一個開始。 但你確定你有「正確的」鏈嗎?對於給定的證書,通常有幾個可能的鏈條, ,有時其中一些是有效的,但另一些已經過期或變得不可驗證。 Verisign特別頒發我相信所有最近的證書都在他們的G5根目錄下,但爲不正確的更新者提供了一個替代路徑 (有效)G1,並且有時不能更新。

大多數情況下的算法在「PKIX」RFC5280, 中定義,除了OCSP RFC6960而不是CRL用於撤銷更加普遍。 您可能會忽略省略的跨層次結構和NameConstraints,其中AFAIK實際上不是由Verisign等公共CA使用的 ,以及CA使用的策略,但用戶/員工不關心。 https://security.stackexchange.com/questions/37409/certificate-chain-checking有一個很好但不完整的介紹。

但你使用Java的(真的JCE的)的CertPathValidator爲「PKIX」可能會更好過 - 如果需要的CertPathBuilder - 而我已經提到你。這已經由專家撰寫和測試。只是調用它 仍然有點複雜,但沒有像重寫所有事情那麼複雜。

+0

非常感謝@ dave_thompson_085您的詳細expalnation。 我嘗試了您提到的步驟,並能夠使用其頒發者證書驗證服務器證書。 – 2014-11-11 08:40:15

+0

但我還需要驗證簽名過程中生成的「簽名」文件的證書。爲此,我在https://www.flexiprovider.de/examples/ExampleSMIMEverify.html上找到了一個解決我的問題的示例,但它規定「由於樣本證書是自簽名的,因此可能需要驗證CA證書。在現實生活中,您應該檢查證書鏈,直至可信CA,以確保擁有有效的證書。」 – 2014-11-11 08:55:29

+0

所以,youplease可以幫助我用java代碼來解決如何解決「檢查這個證書鏈到可靠的CA,以確保有有效的證書」 在此先感謝 – 2014-11-11 08:56:14