1

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

prayagupa
  • 30,204
  • 14
  • 155
  • 192
  • The use of `-XGET` there makes my eyes bleed... – Daniel Stenberg Aug 24 '17 at 08:45
  • whats the matter with `-X`. you want `--request` instead? I'm just habituated `-X`ing on anything btw. – prayagupa Aug 24 '17 at 08:50
  • I want `-XGET` removed completely since curl picks the method to use based on the options you pass it. Which makes it use GET here... – Daniel Stenberg Aug 24 '17 at 08:52
  • Is this A) an attempt to use a client certificate or B) an attempt to verify the server's certificate or both? – Daniel Stenberg Aug 24 '17 at 08:53
  • This is an attempt to use a client cert. But I'm not sure the way I created it is correct. – prayagupa Aug 24 '17 at 08:56
  • The version of curl itself doesn't matter for TLS, but different _builds_ of curl use different libraries with different capabilities for the cert file, in particular whether PKCS12 works. Look at the _whole first line_ from `curl -V`. Client auth will actually be done only if the server is configured to request (or demand) it, which yours as shown isn't. – dave_thompson_085 Aug 24 '17 at 11:08
  • Hi. How to send request? Please,Load certificate files to Postman or SOAPUI and send request again and share result with us. – MehmanBashirov Aug 24 '17 at 13:42
  • What version of Tomcat are you using? Recent versions can use OpenSSL-style PEM-encoded certificate and key files instead of having to convert them into a JSSE-friendly keystore format. – Christopher Schultz Aug 28 '17 at 13:09
  • @ChristopherSchultz I'm using `tomcat 8.0.42`. Checked tomcat8 has documentation that states - "Tomcat currently operates only on JKS, PKCS11 or PKCS12 format keystores." So I will give `.p12` a try as well. - https://tomcat.apache.org/tomcat-8.0-doc/ssl-howto.html#SSL_and_Tomcat – prayagupa Aug 28 '17 at 16:32
  • @ChristopherSchultz It might be completely new thread or question but tomcat is working fine with `.pkcs12`. but my client can't connect to tls server. Error is `curl: (60) SSL certificate problem: self signed certificate More details here: https://curl.haxx.se/docs/sslcerts.html`. I'm simply using the same `cert` I used for server `curl --cert client.pem https://localhost:8443/restapi/health` – prayagupa Aug 28 '17 at 23:36

1 Answers1

1
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.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • Thx @EJP. After re-reading your answer couple of times I created jks from PKCS#12 (followed [this answer](https://stackoverflow.com/a/17710626/432903)) `keytool -importkeystore -destkeystore restapi.jks -srckeystore restapi.p12 -srcstoretype pkcs12 -alias restapi`. But cURL gives me same error. I went with `openssl` as only my server is java based not the clients. – prayagupa Aug 24 '17 at 08:42
  • You don't state how you created the .p12 in the first place. What your clients are based on is 100% irrelevant to how you should create and configure your server certificate. You should use whatever technology is appropriate to the server. In this case, `keytool`, Exporting a certificate from `keytool` for use by the clients is trivial. – user207421 Aug 24 '17 at 10:02
  • I created `.p12` with `openssl pkcs12 -export -name restapi -in restapi.cert -inkey restapi.key -out restapi.p12` then imported into jks `keytool -importkeystore -destkeystore restapi.jks -srckeystore restapi.p12 -srcstoretype pkcs12 -alias restapi`. I got your point, I could have used `keytool` as well. – prayagupa Aug 24 '17 at 16:49