前提:我有证书,我想验证系统'信任'此证书(由Java /操作系统由受信任的根CA签名)
我找到了一些不同的解决方案来解决这个问题。
选项1:
使用SSL类来获取信任。
TrustManagerFactory tmfactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmfactory.init((KeyStore) null);
for (TrustManager trustManager : tmfactory.getTrustManagers()) {
if (trustManager instanceof X509TrustManager) {
try {
((X509TrustManager) trustManager).checkClientTrusted(new X509Certificate[] {new JcaX509CertificateConverter().getCertificate(holder)}, "RSA");
System.out.println("This certificate is trusted by a Root CA");
} catch (CertificateException e) {
e.printStackTrace();
}
}
}
由于这种方法很大程度上依赖于SSL类(当前项目不需要),我们正在寻找替代方案。
选项2:
将Java的cacerts
文件加载到密钥库中,并根据我的证书检查每个“最受信任”的证书是否相等。
String filename = System.getProperty("java.home") + "/lib/security/cacerts".replace('/', File.separatorChar);
FileInputStream is = new FileInputStream(filename);
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
String password = "changeit";
keystore.load(is, password.toCharArray());
// This class retrieves the most-trusted CAs from the keystore
PKIXParameters params = new PKIXParameters(keystore);
// Get the set of trust anchors, which contain the most-trusted CA certificates
Set<X509Certificate> rootCertificates = params.getTrustAnchors().parallelStream().map(TrustAnchor::getTrustedCert).collect(Collectors.toSet());
return rootCertificates.contains(holderX509);
这种方法的问题是它需要密码来验证JKS编码文件的完整性。虽然SSL似乎没有(或者更确切地说使用System.getProperty("javax.net.ssl.trustStorePassword")
,但这又与SSL密切相关。
问题:是否存在从文件和纯SSL手动加载证书之间的解决方案?我觉得好像应该有一些课程,我可以打电话来简单地验证系统对证书的信任,而不必跳过几个环节。
答案 0 :(得分:1)
没有下载第三方库,可能没有其他选择。
你为什么要试图避免&#34; SSL&#34;图书馆?它是标准库的一部分,因此不会给您的程序带来负担。
无论如何,证书验证是SSL的重要组成部分。我怀疑是否有人在创建一个没有实现SSL协议的实质性子集的库的情况下遇到了麻烦。没有真正的理由这样做。
答案 1 :(得分:1)
阅读David Hook的Beginning Cryptography With Java之后我已经制作了以下示例来验证证书链(它完成了使用系统信任库来验证根CA的最初目标)
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509", new BouncyCastleProvider());
InputStream is = new ByteArrayInputStream(some bytes in an array);
CertPath certPath = certificateFactory.generateCertPath(is, "PKCS7"); // Throws Certificate Exception when a cert path cannot be generated
CertPathValidator certPathValidator = CertPathValidator.getInstance("PKIX", new BouncyCastleProvider());
PKIXParameters parameters = new PKIXParameters(KeyTool.getCacertsKeyStore());
PKIXCertPathValidatorResult validatorResult = (PKIXCertPathValidatorResult) certPathValidator.validate(certPath, parameters); // This will throw a CertPathValidatorException if validation fails
这也实现了不必使用SSL类的目标 - 而是使用Java安全类/算法。