I'm trying to use self signed certificates (ie where the Subject and the Issuer are both the same) with x509 client authentication.
My understanding is that I need to make two sets of key pairs and put them into the appropriate keyStore.jks for the client and the server.
Then I need to make each side "trust" the CA that signed the certificates. Since these are self-signed, that seems to mean I need to put the certificate also into the trustStore.jks for both sides (ie the client's cert should go into the server's trustStore, and opposite for the server's cert).
This is how I did it:
#make selfsigned Tomcat cert
keytool -genkey -keyalg RSA -validity 365 -keysize 2048 -alias tomcat -keystore $TOMCAT_ROOT/conf/keyStore.jks -storepass changeit -dname 'CN=localhost' -keypass changeit
#don't want to import the whole private key... just the certificate part
# we're trying to make the client trust the server's CA
keytool -exportcert -alias tomcat -keystore $TOMCAT_ROOT/conf/keyStore.jks -storepass changeit -file tomcat.crt
keytool -importcert -alias tomcat -keystore clientTrustStore.jks -storepass clientPassword -file tomcat.crt -noprompt
#make the client key pair
keytool -genkey -keyalg RSA -validity 365 -keysize 2048 -alias client -keystore clientKeyStore.jks -storepass clientPassword -dname 'CN=root' -keypass clientPassword
#make sure tomcat can trust the client's CA
keytool -exportcert -alias client -keystore clientKeyStore.jks -storepass clientPassword -file client.crt
keytool -importcert -alias client -keystore $TOMCAT_ROOT/conf/trustStore.jks -storepass changeit -file client.crt -noprompt
Tomcat's Connector is configured like
<Connector port="8443"
protocol="org.apache.coyote.http11.Http11NioProtocol"
SSLEnabled="true"
maxThreads="150"
scheme="https"
secure="true"
keystoreFile="snip/conf/keyStore.jks"
keystorePass="changeit"
truststoreFile="snip/conf/trustStore.jks"
truststorePass="changeit"
enableLookups="true"
clientAuth="true"
sslEnabledProtocols="TLSv1.2,TLSv1.1"
ciphers="TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA256, SSL_RSA_WITH_3DES_EDE_CBC_SHA"
/>
And the client is run like this:
java -Djavax.net.ssl.trustStore=clientTrustStore.jks \
-Djavax.net.ssl.trustStorePassword=clientPassword \
-Djavax.net.ssl.keyStore=clientKeyStore.jks \
-Djavax.net.ssl.keyStorePassword=clientPassword \
-Djavax.net.debug=ssl foo.bar.Main
Ultimately the client spewls a lot of info, but here you can see that the client apparently refuses to send it's client certificate
*** ServerHello, TLSv1.2
--snip--
*** CertificateRequest
Cert Types: RSA, DSS, ECDSA
Supported Signature Algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA256withDSA, SHA224withECDSA, SHA224withRSA, SHA224withDSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA
Cert Authorities:
<CN=root>
*** ServerHelloDone
Warning: no suitable certificate found - continuing without client authentication
*** Certificate chain
<Empty>
***
I read that to mean: "Server is saying hello and asking for a client certificate (because of the tomcat clientAuth=true setting). That certificate must be signed by one of the listed CAs (ie CN=root), but then the client says no suitable certificate is found.