2014-10-28 90 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