在 Java 中验证 PKCS#7 证书
需要一些有关 Java 加密例程的帮助。
给定 PKCS#7 签名,我想根据受信任的存储验证它包含的所有证书。我假设签名中包含的所有证书都按正确的顺序形成有效的证书路径(或链,等等),因此
- 最上面的(#0)是签名证书;
- 下一个(#1)是中间证书,用于签署#0;
- 下一个 (#2) 是另一个中间证书,用于签署 #1;
- 等等。
最后一个证书 (#N) 由 CA 签名。
这就是我到目前为止所成功破解的:
// Exception handling skipped for readability
//byte[] signature = ...
pkcs7 = new PKCS7(signature); // `sun.security.pkcs.PKCS7;`
// *** Checking some PKCS#7 parameters here
X509Certificate prevCert = null; // Previous certificate we've found
X509Certificate[] certs = pkcs7.getCertificates(); // `java.security.cert.X509Certificate`
for (int i = 0; i < certs.length; i++) {
// *** Checking certificate validity period here
if (cert != null) {
// Verify previous certificate in chain against this one
prevCert.verify(certs[i].getPublicKey());
}
prevCert = certs[i];
}
//String keyStorePath = ...
KeyStore keyStore = KeyStore.getInstance("JKS"); // `java.security.KeyStore`
keyStore.load(new FileInputStream(keyStorePath), null);
// Get trusted VeriSign class 1 certificate
Certificate caCert = keyStore.getCertificate("verisignclass1ca"); // `java.security.cert.Certificate`
// Verify last certificate against trusted certificate
cert.verify(caCert.getPublicKey());
所以问题是——如何使用标准 Java 类(如 CertPath
等)来完成此操作?我有一种强烈的感觉,我正在重新发明自行车。或者,如果有人有 BouncyCastle 库的示例,那也可以。
额外问题:如何根据受信任的存储验证证书,以便自动选择根证书?
Need some help with crypto routines in Java.
Given a PKCS#7 signature, I want to verify all certificates it contains against a trusted store. I assume that all certificates contained in signature are in the correct order to form a valid certificate path (or chain, whatever), so that
- topmost (#0) is a signing certificate;
- next one (#1) is an intermediate certificate, used to sign #0;
- next one (#2) is another intermediate certificate, used to sign #1;
- and so on.
The last certificate (#N) is signed by CA.
That's what I've managed to hack so far:
// Exception handling skipped for readability
//byte[] signature = ...
pkcs7 = new PKCS7(signature); // `sun.security.pkcs.PKCS7;`
// *** Checking some PKCS#7 parameters here
X509Certificate prevCert = null; // Previous certificate we've found
X509Certificate[] certs = pkcs7.getCertificates(); // `java.security.cert.X509Certificate`
for (int i = 0; i < certs.length; i++) {
// *** Checking certificate validity period here
if (cert != null) {
// Verify previous certificate in chain against this one
prevCert.verify(certs[i].getPublicKey());
}
prevCert = certs[i];
}
//String keyStorePath = ...
KeyStore keyStore = KeyStore.getInstance("JKS"); // `java.security.KeyStore`
keyStore.load(new FileInputStream(keyStorePath), null);
// Get trusted VeriSign class 1 certificate
Certificate caCert = keyStore.getCertificate("verisignclass1ca"); // `java.security.cert.Certificate`
// Verify last certificate against trusted certificate
cert.verify(caCert.getPublicKey());
So the question is -- how can this be done using standard Java classes like CertPath
and friends? I have a strong feeling I'm re-inventing a bicycle. Or, if someone has an example with BouncyCastle library, that would also be fine.
Bonus question: how to verify a certificate against a trusted store so that root certificate is selected automatically?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我自己找到了解决方案。因此,以下是如何根据可信存储提取和验证证书链(为了可读性而跳过异常处理):
如果验证失败,
validate()
将引发异常。文档:
ASN1Set
,ContentInfo
,SignedData
。所有其他外来名称和相关文档都可以在 java.security.cert 中找到。这里没有 SUN 依赖项,只需要 BouncyCastle 提供程序库。
这个问题(尤其是答案)可能会有所帮助也。
Found the solution myself. So, here's how one can extract and validate a certificate chain against the trusted store (exception handling skipped for readability):
validate()
will throw an exception if validation fails.Docs:
ASN1Set
,ContentInfo
,SignedData
. All other exotic names and related docs can be found injava.security.cert
.No SUN-dependencies here, only BouncyCastle provider library is needed.
This question (and especially an answer) may help too.
您需要 CertificateFactory。 javadoc 中的最后一个示例正是您想要的。
You want CertificateFactory. The last example in the javadocs do exactly what you want.