我正在使用Java BouncyCastle所谓的“轻量级”API来通过TCP套接字建立TLS连接。
我想验证由受信任的CA之一签名的服务器提供的证书链。听起来像是一个相当普遍的任务,默认情况下每个理智的TLS客户端实现都有,所以我希望这应该很简单。
为了简化问题,我不会要求验证除签名/信任链之外的任何内容,例如匹配主机名或检查过期日期。这样的检查似乎微不足道。
如果我正确理解文档,那么用户应该实现TlsAuthentication
接口。唯一提供的实现是LegacyTlsAuthentication
,它适应现在已弃用的CertificateVerifyer
接口,该接口只有AlwaysValidVerifyer
实现(在引擎盖下只是虚拟“return true;
”)。 / p>
所以,这就是我现在所拥有的:
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
是否被另一个{0}正确签名的现有示例。有人可以给我一些指示吗?
我正在使用BounceCastle的专有API,因为需要使用默认Java安装不允许的密码套件,因为受到美国加密政策管辖权的限制。例如,AES256加密需要安装无限强度策略文件,如果可能的话,我真的想避免额外的最终用户安装步骤。
答案 0 :(得分:4)
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”是签名者的公钥。因此,根据证书链的长度,您将重复调用此方法,从最终实体证书开始,然后上线到自签名根证书。
答案 1 :(得分:1)
你需要去的地方
http://www.cs.berkeley.edu/~jonah/bc/org/bouncycastle/asn1/x509/KeyUsage.html#keyCertSign
将为CA颁发证书设置keyCertSign。
您在serverCertificate.getCerts()上面的代码将返回一个X509CertificateStructure对象(您的链)的数组,您可以调用这些对象来获取ASN1Object()以获取接口DerEncodable / KeyUsage
我希望这会有所帮助。