prayagupadhyay
prayagupadhyay

Reputation: 31232

TLS with self-signed cert with tomcat server - could not load PEM client certificate

I want to use TLS for my REST API for which I'm planning to create self-signed cert and provide public key to the clients of my restapi.

My restapi is deployed on tomcat catalina container (tomcat version 8.0.42).

And my test steps are as below,

Server side

1) I created a self signed cert using openssl

openssl genrsa -out restapi.key 2048                                                                   

openssl req -new -key restapi.key -out restapi.csr                                                     

openssl x509 -req -days 24855 -in restapi.csr -signkey restapi.key -out restapi.cert 

2) created PKCS#12 bundle

openssl pkcs12 -export -in restapi.cert -inkey restapi.key -out restapi.p12 -name restapi

3) Then configured tomcat to have TLS enabled (with keystoreType as "PKCS12"), and started tomcat

<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"                       
        maxThreads="150" 
        SSLEnabled="true" 
        scheme="https" 
        secure="true"                            
        keystoreFile="/Users/prayagupd/restapi.p12" 
        keystoreType="PKCS12"
        keystorePass="prayagupd"                          
        clientAuth="true" 
        sslProtocol="TLS" /> 

Client side

4) sent https request

I have same pkcs#12 file for a client. I saw openssl x509 -pubkey -noout -in restapi.cert > pubkey.pem as well not sure if this one is what i need.

This is what the .p12 permission look like

21765315 -rw-r--r--  1 prayagupd  NORD\Domain Users  2596 Aug 24 01:34 restapi.p12

When I send https request it fails with following error (with curl 7.55.1)

curl -v --cert restapi.p12 https://localhost:8443/restapi/health
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8443 (#0)
* ALPN, offering http/1.1
* could not load PEM client certificate, OpenSSL error error:0906D06C:PEM routines:PEM_read_bio:no start line, (no key found, wrong pass phrase, or wrong file format?)
* Closing connection 0
curl: (58) could not load PEM client certificate, OpenSSL error error:0906D06C:PEM routines:PEM_read_bio:no start line, (no key found, wrong pass phrase, or wrong file format?)

$ curl --cert restapi.p12:restapi https://localhost:8443/restapi/health
curl: (58) could not load PEM client certificate, OpenSSL error error:0906D06C:PEM routines:PEM_read_bio:no start line, (no key found, wrong pass phrase, or wrong file format?)

Its working if I bypass the TLS,

$ curl --insecure https://localhost:8443/restapi/health
{"id":3,"eventId":"config_sucks","status":"Sky is green"}

openssl s_client throws ssl handshake failure,

$ openssl s_client -connect localhost:8443 -showcerts
CONNECTED(00000003)
59281:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:/BuildRoot/Library/Caches/com.apple.xbs/Sources/OpenSSL098/OpenSSL098-59.60.1/src/ssl/s23_lib.c:185:

Note

I found a SO resource - Mutual authentication with Tomcat 7 which explains very well establishing TLS communication. But having the same issue could not load PEM client certificate. Here's my code - Tlsv1.2

Upvotes: 1

Views: 795

Answers (1)

user207421
user207421

Reputation: 310957

keytool -import -alias root -keystore restapi.jks -trustcacerts -file -trustcacerts -file restapi.cert

The problem is here. All this accomplished was importing the signed certificate. You need to import the private key as well. You should really have used nothing but the keytool here:

keytool -genkey ...
keytool -selfcert

using the same alias throughout. You can throw away your existing keystore, it is of no use to man or beast.

This is all documented. See the JSSE Reference Guide.

You could have done it all with openssl as well, but you would have needed to end up with a PKCS#12 keystore file, which you can use directly in Java. No reason for this unless you're also dealing with an OpenSSL-based system, such as Apache HTTPD, MySQL, OpenLDAP, etc.

Upvotes: 1

Related Questions