我尝试在相互TLS连接的客户端启用OCSP检查。如果我只在服务器端启用,那么服务器将正确地验证客户端证书。
当我在客户端使用以下参数启用时:
-Djavax.net.ssl.trustStore="$ROOTDIR/certs/intermediate/certs/local-truststore.jks" -Djavax.net.ssl.trustStorePassword=<some-password> -Djava.security.debug="certpath ocsp" -Djavax.net.debug="all" -Dcom.sun.net.ssl.checkRevocation=true -Docsp.enable=true
则客户端抛出错误:
java.security.cert.CertPathValidatorException: Could not determine revocation status
查看ocsp certpath调试跟踪并通过各种不同的场景,似乎ocsp验证器以某种方式将CA证书视为"坏的"。(参见certpath: RejectKeySelector。
certpath: ForwardBuilder.getMatchingCerts()...
certpath: ForwardBuilder.getMatchingEECerts()...
certpath: X509CertSelector.match(SN: 1000
Issuer: CN=root-ca.acme.com, O="Acme Corp, LLC", ST=New York, C=US
Subject: CN=intermediate-ca.acme.com, O="Acme Corp, LLC", ST=New York, C=US)
certpath: X509CertSelector.match: subject DNs don't match
certpath: X509CertSelector.match(SN: 1003
Issuer: CN=intermediate-ca.acme.com, O="Acme Corp, LLC", ST=New York, C=US
Subject: CN=ledger.acme.com, O="Acme Corp, LLC", ST=New York, C=US)
certpath: X509CertSelector.match: subject DNs don't match
certpath: ForwardBuilder.getMatchingCACerts()...
certpath: ForwardBuilder.getMatchingCACerts(): the target is a CA
certpath: X509CertSelector.match(SN: f9e9243278f85e6a21408510cbedf46d8f0333
Issuer: CN=root-ca.acme.com, O="Acme Corp, LLC", ST=New York, C=US
Subject: CN=root-ca.acme.com, O="Acme Corp, LLC", ST=New York, C=US)
certpath: X509CertSelector.match returning: true
**certpath: RejectKeySelector.match: bad key**
certpath: X509CertSelector.match(SN: 1000
Issuer: CN=root-ca.acme.com, O="Acme Corp, LLC", ST=New York, C=US
Subject: CN=intermediate-ca.acme.com, O="Acme Corp, LLC", ST=New York, C=US)
certpath: X509CertSelector.match: subject DNs don't match
certpath: X509CertSelector.match(SN: 1003
Issuer: CN=intermediate-ca.acme.com, O="Acme Corp, LLC", ST=New York, C=US
Subject: CN=ledger.acme.com, O="Acme Corp, LLC", ST=New York, C=US)
certpath: X509CertSelector.match: subject DNs don't match
certpath: ForwardBuilder.getMatchingCACerts: found 0 CA certs
certpath: SunCertPathBuilder.depthFirstSearchForward(): certs.size=0
12:16:23.215 [main] ERROR app.ClientApp$ - io.grpc.StatusRuntimeException: UNAVAILABLE: io exception
在以下JDK库代码中抛出:
http://cr.openjdk.java.net/~vinnie/8019627/webrev.00/raw_files/new/src/share/classes/sun/security/provider/certpath/RevocationChecker.java
确切的证书根据信任存储库中通过的CA而更改,即在我的测试配置中的两层中,如果只有根CA通过,则在根CA上失败;如果两个CA都通过,则在中间CA上失败。
在更高的跟踪中,我看到这个来自SunCertPathBuilder.engineBuild
Target Cert Constraints: RejectKeySelector: [
X509CertSelector: [
Subject: CN=root-ca.acme.com,O=Acme Corp, LLC,ST=New York,C=US
matchAllSubjectAltNames flag: true
Key Usage: KeyUsage [
Crl_Sign
]
但不清楚为什么(在这种情况下根ca)被添加到RejectKeySelector
从服务器(链或个人)和信任存储(链或根)传递的证书的预期组合是什么?
主要问题是ocsp。enable=true需要在Java安全属性文件中设置,而不是在命令行中。你可以创建一个覆盖文件并使用:-
Djava.security.properties = . ./java.security-client
遗憾的是,OpenJDK11尚未启用OCSP订书机,因此需要进一步的工作。