I needed to test the data transfer involved in TLS and Mutual TLS handshake. I found bits of information on different sites. I thought it will be good to put all the information in one place and show the E2E flow.
There are 3 steps:
- Prepare the client and server certificates
- Configure NGINX
- Test the handshake
Prepare the client and the server certificates
Generate client key pair and self-signed certificate
$/rnd/TLS/rsaclient: keytool -genkey -keyalg RSA -alias test -keystore clientselfsignedrsa.jks -validity 30 -keysize 2048
You will be prompted to enter password and few other details when generating certificates.
Generate server key pair and self-signed certificate
$/rnd/TLS/rsaserver: keytool -genkey -keyalg RSA -alias test -keystore serverselfsignedrsa.jks -validity 30 -keysize 2048
You will be prompted to enter password and few other details when generating certificates.
Extract client certificate and private key
$/rnd/TLS/rsaclient: keytool -importkeystore -srckeystore clientselfsignedrsa.jks -destkeystore pkcs12-keystore.p12 -deststoretype PKCS12
$/rnd/TLS/rsaclient: openssl pkcs12 -nokeys -in pkcs12-keystore.p12 -out rsaclientcert.pem
$/rnd/TLS/rsaclient: openssl pkcs12 -nocerts -nodes -in pkcs12-keystore.p12 -out rcsclientkey.key
Extract server certificate and private key
$/rnd/TLS/rsaserver: keytool -importkeystore -srckeystore serverselfsignedrsa.jks -destkeystore pkcs12-keystore.p12 -deststoretype PKCS12
$/rnd/TLS/rsaserver: openssl pkcs12 -nokeys -in pkcs12-keystore.p12 -out rsaservercert.pem
$/rnd/TLS/rsaserver: openssl pkcs12 -nocerts -nodes -in pkcs12-keystore.p12 -out rsaserverkey.key
Configure NGINX
The config file on mac is under /usr/local/etc/nginx
Edit the HTTPS server section and reload nginx (nginx -s reload)
# HTTPS server
#
server {
listen 8443 ssl;
server_name localhost;
ssl_certificate /rnd/TLS/rsaserver/rsaservercert.pem;
ssl_certificate_key /rnd/TLS/rsaserver/rsaserverkey.key;
ssl_client_certificate /rnd/TLS/rsaclient/rsaclientcert.pem;
# Comment/Uncomment following line based on whether you want Mutual TLS or not.
ssl_verify_client on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
location / {
root html;
index index.html index.htm;
}
}
Start wireshark capture with filter as "port 8443"
Test TLS Handshake
I have stripped some of the details from below trace to keep the size in check.
Mutual TLS (ssl_verify_client on;)
$ openssl s_client -connect localhost:8443 -cert /rnd/TLS/rsaclient/rsaclientcert.pem -key /rnd/TLS/rsaclient/rcsclientkey.key -CAfile /rnd/TLS/rsaserver/rsaservercert.pem -state -debug
CONNECTED(00000003)
SSL_connect:before/connect initialization
....
SSL_connect:SSLv2/v3 write client hello A
...
SSL_connect:SSLv3 read server hello A
...
SSL_connect:SSLv3 read server certificate A
...
SSL_connect:SSLv3 read server key exchange A
...
SSL_connect:SSLv3 read server certificate request A
SSL_connect:SSLv3 read server done A
...
SSL_connect:SSLv3 write client certificate A
...
SSL_connect:SSLv3 write client key exchange A
...
SSL_connect:SSLv3 write certificate verify A
...
SSL_connect:SSLv3 write change cipher spec A
...
SSL_connect:SSLv3 write finished A
SSL_connect:SSLv3 flush data
...
SSL_connect:SSLv3 read server session ticket A
...
SSL_connect:SSLv3 read finished A
---
Certificate chain
...
---
Server certificate
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
---
---
SSL handshake has read 2619 bytes and written 1621 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES256-GCM-SHA384
Session-ID:
Session-ID-ctx:
Master-Key:
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
TLS session ticket lifetime hint: 300 (seconds)
TLS session ticket:
Start Time: 1515538253
Timeout : 300 (sec)
Verify return code: 0 (ok)
Without Mutual TLS (comment ssl_verify_client on; in NGINX conf)
$ openssl s_client -connect localhost:8443 -cert /rnd/TLS/rsaclient/rsaclientcert.pem -key /rnd/TLS/rsaclient/rcsclientkey.key -CAfile /rnd/TLS/rsaserver/rsaservercert.pem -state -debug
CONNECTED(00000003)
SSL_connect:before/connect initialization
...
SSL_connect:SSLv2/v3 write client hello A
...
SSL_connect:SSLv3 read server hello A
...
SSL_connect:SSLv3 read server certificate A
...
SSL_connect:SSLv3 read server key exchange A
...
SSL_connect:SSLv3 read server done A
...
SSL_connect:SSLv3 write client key exchange A
...
SSL_connect:SSLv3 write change cipher spec A
...
SSL_connect:SSLv3 write finished A
SSL_connect:SSLv3 flush data
...
SSL_connect:SSLv3 read server session ticket A
...
SSL_connect:SSLv3 read finished A
---
Certificate chain
...
---
Server certificate
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
---
No client certificate CA names sent
Peer signing digest: SHA512
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 1568 bytes and written 444 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES256-GCM-SHA384
Session-ID:
Session-ID-ctx:
Master-Key:
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
TLS session ticket lifetime hint: 300 (seconds)
TLS session ticket:
Start Time: 1515538406
Timeout : 300 (sec)
Verify return code: 0 (ok)
Finally some numbers
Following is the summary of amount of data transferred during TLS handshake. This is relevant and may be a concern for OTA interfaces like cellular interfaces due to cost of data. These can be optimized with various TLS configuration on the server side. The objective of this exercise was to understand the data overhead in general.
- TLS with RSA 2048 bit key - 2932 bytes
- Mutual TLS with RSA 2048 bit key - 5384 bytes
- TLS with ECC 256 bit key - 2356 bytes
- Mutual TLS with ECC 256 bit key - 3847 bytes