在 java 8 中验证来自第三方的叶证书

Validating a leaf certificate from a third party in java 8

我正在寻找一种方法来验证从第三方发送的 java.security.cert.X509Certificate 对象。证书提供者正在使用 dns 或 ldap 来获取证书。我在 link 中包含了有关如何检索证书的附加信息。

http://wiki.directproject.org/w/images/2/24/Certificate_Discovery_for_Direct_Project_Implementation_Guide_v4.1.pdf

我还需要知道将在任何验证步骤中使用的协议和默认端口。证书需要满足本文档第 13 页第 4 节中的以下条件:

http://wiki.directproject.org/w/images/e/e6/Applicability_Statement_for_Secure_Health_Transport_v1.2.pdf

  1. 尚未过期。
  2. 具有有效消息摘要的有效签名
  3. 尚未撤销
  4. 绑定到预期的实体
  5. 具有受信任的证书路径

项目 1 直接将证书对象上的 getNotAfter 和 getNotBefore 方法的日期与当前日期进行比较,或者使用抛出检查异常的 checkValidity 方法。

对于第 2 项,我看到了一种获取签名的方法,但我不确定如何生成消息摘要并验证签名和消息摘要是否均有效。

对于第 3 项,通过对证书 getExtensionValue("2.5.29.31") 调用此方法,证书吊销列表似乎与其他一些数据混合在一起。检索证书撤销列表数据似乎可以通过 http 进行,而 ocsp 似乎是基于 http 的。我无法在 java.

中找到如何执行此操作

对于第 4 项,我不确定绑定在证书上下文中意味着什么,或者验证它涉及什么。

对于第 5 项,通过对证书 getExtensionValue("1.3.6.1.5.5.7.1.1") 调用此方法,中间证书的数据似乎与其他一些数据混合在一起。一旦通过 http 检索到证书数据,CertPathValidator 看起来可能能够帮助验证此信息。

我会把答案分成 3 份。第一个是背景,第二个是库的选择,实现代码(我在实现中使用的参考文献)

过去我实现了一个非常相似的用例。我让一家供应商完成了物联网制造,为了让他们上船,我实施了与您提到的相同的 X509 验证过程。

实施: 对于我的实施,我参考了以下内容。您可以将 BC 作为您的 defaultProvider (Security.setProvider) 并使用以下代码。代码直接求解1,3,5。代码在这里:https://nakov.com/blog/2009/12/01/x509-certificate-validation-in-java-build-and-verify-chain-and-verify-clr-with-bouncy-castle/

现在来到 2,答案取决于您将如何从客户端获取证书以及应用程序将提供哪些额外数据。 其高层流程如下 a) 客户端出示证书 b) 客户端使用某种可接受的算法进行摘要。 SHA256 很流行,你可以根据需要和你有多少计算来增加强度。客户端创建摘要后,为了证明他是证书的所有者,您可以使用设备的私钥对摘要进行签名。然后可以将其传输到验证者应用程序 c) 获得证书和签名后,您可以使用证书和与之关联的 Public 密钥来验证应用相同摘要的签名,然后在此处验证 signature.A 好的参考:http://www.java2s.com/Code/Java/Security/SignatureSignAndVerify.htm

我不是 100% 确定 4 是什么意思。但如果这意味着身份证明(谁出示证书就必然是他们是谁,签名和验证将提供相同的)

虽然您可以使用 java 安全性 API 实现用例,但我使用 bouncycastle 核心 API 来实现用例。 Bouncycastle API 更加丰富并且经过了实战测试,特别是对于我们不得不使用的奇怪的 EC 曲线算法,你会发现很多人都对 BouncyCastle 发誓。

希望对您有所帮助!

证书验证是一项复杂的任务。您可以使用 native Java 8 support 或 Bouncycastle 手动执行您需要的所有验证(过期、撤销、证书链)。但是我推荐的选项是使用已经考虑了所有可能性的特定库。

看看DSS documentation and Certificate Verification example

    // Trusted certificates sources, root and intermediates (#5 )
    CertificateSource trustedCertSource = null;
    CertificateSource adjunctCertSource = null;


    // The certificate to be validated
    CertificateToken token = DSSUtils.loadCertificate(new File("src/main/resources/keystore/ec.europa.eu.1.cer"));

    // Creates a CertificateVerifier using Online sources. It checks the revocation status with the CRL lists URLs or OCSP server extracted from the certificate #3
    CertificateVerifier cv = new CommonCertificateVerifier();
    cv.setAdjunctCertSource(adjunctCertSource);     
    cv.setTrustedCertSource(trustedCertSource);

    // Creates an instance of the CertificateValidator with the certificate
    CertificateValidator validator = CertificateValidator.fromCertificate(token);
    validator.setCertificateVerifier(cv);

    // We execute the validation (#1, #2, #3, #5)
    CertificateReports certificateReports = validator.validate();

    //The final result. You have also a detailedReport and DiagnosticData
    SimpleCertificateReport simpleReport = certificateReports.getSimpleReport();

验证将执行您指定的所有步骤,包括过期、证书签名、吊销和检查信任链(包括中间证书的下载)。

步骤 # 4 我不太明白你的意思。我想验证证书对应于受信任列表的证书实体之一

要加载受信任的证书来源,请参阅this

CertificatePool certPool = new CertificatePool();
CommonCertificateSource ccc = new CommonCertificateSource(certPool);
CertificateToken cert = DSSUtils.loadCertificate(new File("root_ca.cer"));
CertificateToken adddedCert = ccc.addCertificate(cert);