在Java中需要一些加密例程的帮助。
鉴于PKCS#7签名,我想验证它对可信商店包含的所有证书。我假设签名中包含的所有证书都以正确的顺序形成有效的证书路径(或链,无论如何),以便
最后一个证书(#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());
所以问题是 - 如何使用CertPath
和朋友等标准Java类来完成?我有一种强烈的感觉,我正在重新发明一辆自行车。或者,如果某人有BouncyCastle库的示例,那也没关系。
加分问题:如何针对受信任的商店验证证书,以便自动选择根证书?
答案 0 :(得分:12)
自己找到解决方案。因此,以下是如何针对可信商店提取和验证证书链的方法(为了便于阅读而跳过异常处理):
CertificateFactory cf = CertificateFactory.getInstance("X.509");
// Get ContentInfo
//byte[] signature = ... // PKCS#7 signature bytes
InputStream signatureIn = new ByteArrayInputStream(signature);
DERObject obj = new ASN1InputStream(signatureIn).readObject();
ContentInfo contentInfo = ContentInfo.getInstance(obj);
// Extract certificates
SignedData signedData = SignedData.getInstance(contentInfo.getContent());
Enumeration certificates = signedData.getCertificates().getObjects();
// Build certificate path
List certList = new ArrayList();
while (certificates.hasMoreElements()) {
DERObject certObj = (DERObject) certificates.nextElement();
InputStream in = new ByteArrayInputStream(certObj.getDEREncoded());
certList.add(cf.generateCertificate(in));
}
CertPath certPath = cf.generateCertPath(certList);
// Load key store
//String keyStorePath = ...
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(new FileInputStream(keyStorePath), null);
// Set validation parameters
PKIXParameters params = new PKIXParameters(keyStore);
params.setRevocationEnabled(false); // to avoid exception on empty CRL
// Validate certificate path
CertPathValidator validator = CertPathValidator.getInstance("PKIX");
CertPathValidatorResult result = validator.validate(certPath, params);
如果验证失败, validate()
将抛出异常。
文档:ASN1Set
,ContentInfo
,SignedData
。所有其他外来名称和相关文档都可以在java.security.cert
中找到。
此处没有SUN依赖项,只需要BouncyCastle provider library。
This问题(特别是答案)也可能有所帮助。
答案 1 :(得分:2)
你想要CertificateFactory。 javadocs中的最后一个示例正是您想要的。