Sending Complete Chain from Common Access Card (CAC)?
I'm attempting to enable SSL communication from a web service client (Axis2) using the certificate on the user's CAC card. Works like a 开发者_JAVA技巧charm....UNTIL the web server is CAC enabled. At that point the SSL connection is rejected with the error message that the other certificates in the chain were not included.
I have ensured that the provider is available, either by adding it to the security.properties file or creating it programatically.
My current approach is to simply set the system properties: System.setProperty("javax.net.ssl.keyStore", "NONE"); System.setProperty("javax.net.ssl.keyStoreType", "PKCS11");
I understand from this question/answer that this approach only sends the "end entity" certificate. Apparently I need to implement my own X509KeyManager. This is new ground for me, can anyone suggest a good reference or provide samples of how to do so?
Appreciate the assistance.
The best key manager implementation depends on the issuer of the certificates you expect to be using.
If the certificate on the user's CAC will always be issued by a specific CA, simply store that issuer's certificate and any intermediate certificates further up the chain in a PKCS #7 file. In the getCertificateChain()
method, this collection can be appended blindly to the user's certificate and returned.
If things aren't quite that simple, but a complete list of possible issuers can be enumerated, obtain all of their certificates, and their issuer's certificates, and so on, up to the root certificates.
Add all of the root certificates to a key store as trusted entries. Bundle the intermediate certificates in a PKCS-#7–format file.
Implement X509KeyManager
(or extend X509ExtendedKeyManager
if you're working with SSLEngine
). Specifically, in the getCertificateChain()
method, you'll use a CertPathBuilder
to create a valid chain from the user's certificate to a trusted root. The target is the certificate that you load from the user's CAC with the alias
parameter. The trusted roots are the certificates in trust store that you created; the intermediate certificates can be loaded from the PKCS #7 file and added to the builder parameters. Once the chain is built, get the certificate path and convert it to an array. This is the result of the getCertificateChain()
method.
If you can't predict who will be issuing the user's certificate, you might be able to obtain the intermediate certificates at runtime from an LDAP directory or other repository. That's a whole new level of difficulty.
精彩评论