java – 使用BouncyCastle的“轻量级”API验证TLS服务器证书

我正在使用Java BouncyCastle所谓的“轻量级”API来通过TCP套接字建立TLS连接.

我想验证由受信任的CA之一签名的服务器提供的证书链.听起来像一个相当普遍的任务,默认情况下每个理智的TLS客户端实现,所以我希望这应该是简单的.

为了简化问题,我不会要求验证除签名/信任链之外的任何内容,例如匹配主机名或检查到期日期.实施这些检查似乎微不足道.

如果我正确理解文档,那么用户应该实现一个TlsAuthentication接口.唯一提供的实现是LegacyTlsAuthentication,它适应现在已弃用的CertificateVerifyer接口,该接口只有AlwaysValidVerifyer实现(这只是虚拟“返回true;”在引擎盖下).

所以,这就是我现在所拥有的:

DefaultTlsClient tlsClient = new DefaultTlsClient() {
    @Override
    public TlsAuthentication getAuthentication() throws IOException {
        TlsAuthentication auth = new TlsAuthentication() {
            @Override
            public void notifyServerCertificate(Certificate serverCertificate) {
                // Here I should validate certificate chain, but this far
                // I only managed to print subjects for debugging purposes.
                for (org.bouncycastle.asn1.x509.Certificate c : serverCertificate.getCerts()) {
                    System.out.println("Certificate: " + c.getSubject().toString());
                }
            }

            @Override
            public TlsCredentials getClientCredentials(CertificateRequest cr) throws IOException {
                return null;
            }
        };
        return auth;
    }
};

socket = new Socket(hostname, port);
tlsHandler = new TlsProtocolHandler(socket.getInputStream(), socket.getOutputStream());
tlsHandler.connect(tlsClient);

但是,我无法理解或找到任何现有的示例,它会检查一个org.bouncycastle.asn1.x509.Certificate是否被另一个正确签名.有人可以给我一些指示吗?

我正在使用BounceCastle的专有API,因为需要使用默认Java安装不允许的密码套件,因为它受到美国加密政策管辖权限制的约束.例如,AES256加密需要安装无限强度策略文件,如果可能的话,我真的想避免额外的最终用户安装步骤.

解决方法:

X509CertificateHolder类的isSignatureValid方法应该适合您.此方法接受1个参数,即ContentVerifierProvider.您可以通过将证书传递给构造函数来创建X509CertificateHolder.

以下代码取自BC的version 2 API page,并且应该为您提供如何在解决方案中实现此功能的好主意.

ContentVerifierProvider contentVerifierProvider =
   new BcRSAContentVerifierProviderBuilder(
      new DefaultDigestAlgorithmIdentifierFinder()).build(lwPubKey);

if (!certHolder.isSignatureValid(contentVerifierProvider))
{
    System.err.println("signature invalid");
}

“lwPubKey”是签名者的公钥.因此,根据证书链的长度,您将重复调用此方法,从最终实体证书开始,然后上线到自签名根证书.

上一篇:一种基于状态机的 DOM 树生成技术(1)


下一篇:python读取csv、xlsx文件