4

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

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

为了简化问题,我不询问验证签名/信任链以外的任何内容,例如匹配主机名或检查到期日期。这样的检查实施起来似乎微不足道。

如果我正确理解了文档,则有一个TlsAuthentication用户应该实现的界面。唯一提供的实现是LegacyTlsAuthentication,它适应现在已弃用的CertificateVerifyer接口,它只有实现(这只是引擎盖下的AlwaysValidVerifyer虚拟“ ”)。return 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 加密需要安装无限强度的策略文件,如果可能的话,我真的很想避免额外的最终用户安装步骤。

4

2 回答 2

5

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

以下代码取自 BC 的第 2 版 API 页面,应该可以让您很好地了解如何在您的解决方案中实现这一点。

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

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

“lwPubKey”是签名者的公钥。因此,根据您的证书链的长度,您将反复调用此方法,从最终实体证书开始,一直到自签名根证书。

于 2013-05-15T23:45:53.823 回答
1

哇,一堆弃用的课程。我对你有感觉。

你需要去的地方是

http://www.cs.berkeley.edu/~jonah/bc/org/bouncycastle/asn1/x509/KeyUsage.html#keyCertSign

将为 CA 颁发证书设置 keyCertSign。

您上面的代码 serverCertificate.getCerts() 将返回一个 X509CertificateStructure 对象数组(您的链),您可以调用 toASN1Object() 来获取接口 DerEncodable / KeyUsage

我希望这有帮助。

于 2013-05-14T02:28:30.243 回答