1

probably a silly question but i'm starting using certificates and I still have a lot of stuff to learn.

I'm trying to make an authenticated connection to an API using a client certificate. The idea is that the server recognised the certificate and do personalised stuff according the user.

I created a simple app in jakarta which returns the user. There is an endpoint in the api which works well if i disabled the client authentication but when i enabled the client authentication in the server.xml of the tomcat server the connection to the server works but there is an error "certificate unknown" when tries to reach it.

I will try to explain step by step what i do.

First i created a self-signed certificate:

keytool -genkey -keyalg RSA -alias tomcat \
-keystore conf/keyStore \
-storepass changeit \
-validity 360 -keysize 2048

Then i exported it:

keytool -exportcert -alias tomcat \
-keystore conf/keyStore \
-file tomcatTestCertificate.cer

I found that i need to import the certificate to the java truststore but i don't have access to sudo so i copy the java truststore and i import the certificate to it.

cp $JAVA_HOME/lib/security/cacerts conf/cacerts

keytool -importcert -alias tomcat \
-keystore conf/cacerts \
-file tomcatTestCertificate.cer

I repeat the process to create another java keystore for the client, i exported the certificate and added to the cacerts.

I ask tomcat to start using my new cacerts file writing it in the setenv.sh file.

Using CATALINA_OPTS:    -Djavax.net.ssl.trustStore=/Users/samuel.gongoragarcia/Documents/Tomcat/apache-tomcat-10.1.5/conf/cacerts -Djavax.net.ssl.trustStorePassword=changeit

And I created a connector in the server.xml file:

<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
           maxThreads="150" SSLEnabled="true" scheme="https" secure="true">
    <SSLHostConfig certificateVerification="required">
        <Certificate certificateKeystoreFile="/Users/samuel.gongoragarcia/Documents/Tomcat/apache-tomcat-10.1.5-testing/conf/keyStoreTomcat"
                     certificateKeystorePassword="changeit"
                     type="RSA" />
        <CertificateVerification certificateKeystoreFile="/Users/samuel.gongoragarcia/Documents/Tomcat/apache-tomcat-10.1.5-testing/conf/keyStoreClient"
                                certificateKeystorePassword="changeit" />   
    </SSLHostConfig>
</Connector>

Then i exported the certificate and key from the keystore of the client:

keytool -importkeystore -srckeystore keyStoreClient -destkeystore keyStoreClient.p12 -srcstoretype JKS -deststoretype PKCS12 -deststorepass changeit
openssl pkcs12 -in keyStoreClient.p12 -out cert.key.pem -nocerts -nodes
openssl pkcs12 -in keyStoreClient.p12 -out cert.crt.pem -clcerts -nokeys

And i made the call:

curl -vv -k -E cert.crt.pem --key cert.key.pem https://localhost:8443/JakartaApp/api/checkuser
*   Trying 127.0.0.1:8443...
* Connected to localhost (127.0.0.1) port 8443 (#0)
* ALPN: offers h2
* ALPN: offers http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Request CERT (13):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Certificate (11):
* TLSv1.3 (OUT), TLS handshake, CERT verify (15):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN: server did not agree on a protocol. Uses default.
* Server certificate:
*  subject: C=Unknown; ST=Unknown; L=Unknown; O=Unknown; OU=Unknown; CN=localhost
*  start date: Aug  9 10:12:02 2023 GMT
*  expire date: Aug  8 10:12:02 2024 GMT
*  issuer: C=Unknown; ST=Unknown; L=Unknown; O=Unknown; OU=Unknown; CN=localhost
*  SSL certificate verify result: self signed certificate (18), continuing anyway.
> GET /JakartaApp/api/checkuser HTTP/1.1
> Host: localhost:8443
> User-Agent: curl/7.84.0
> Accept: */*
> 
* TLSv1.3 (IN), TLS alert, certificate unknown (558):
* OpenSSL SSL_read: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown, errno 0
* Closing connection 0
curl: (56) OpenSSL SSL_read: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown, errno 0

As i understand curl recognised the server, the certificate is self-signed but it is okay (-k flag) but then...why doesn't accept the client certificate? It is already imported in the cacerts trustore and tomcat is validating the certificates against the same cacerts.

Could somebody give me an advise?

best regards!

dave_thompson_085
  • 34,712
  • 6
  • 50
  • 70
Samuel Góngora
  • 141
  • 1
  • 11
  • 1
    No, you didn't import the client cert into cacerts, you imported tomcat's _own_ cert, which is unnecessary and useless there. Import cert.crt.pem instead. Also there is no ` ... >` _element_ in tomcat config, only the camelcase _attribute_ on ``. – dave_thompson_085 Aug 09 '23 at 20:59
  • hello! if a try a keytool -importcert -alias tomcat \ -keystore conf/cacerts \ -file cert.key.pem i get an "keytool error: java.lang.Exception: Input not an X.509 certificate" what could be? thank you so much! – Samuel Góngora Aug 11 '23 at 08:57
  • 1
    Your client cert file is cert.crt.pem as I said, not cert.key.pem which is the _key_ file. I didn't tell you to import the key, you don't need to import the key, and keytool _can't_ import a bare key including (but not limited to) OpenSSL formats. – dave_thompson_085 Aug 11 '23 at 21:10

0 Answers0