— notes, nodejs, security — 1 min read
In Mutual TLS both Client and Server have a certificate and both sides authenticate using their public/private key pair. Below are the handshake steps in simplistic way.
Below are the steps and commands
Server Details
1openssl req -new -x509 -days 365 -keyout server-ca-key.pem -out server-ca-crt.pem2
3# Output4Generating a RSA private key5....+++++6.............................................+++++7writing new private key to 'server-ca-key.pem' 8Enter PEM pass phrase:9Verifying - Enter PEM pass phrase:10-----11You are about to be asked to enter information that will be incorporated12into your certificate request.13What you are about to enter is what is called a Distinguished Name or a DN.14There are quite a few fields but you can leave some blank15For some fields there will be a default value,16If you enter '.', the field will be left blank.17-----18Country Name (2 letter code) [AU]:IN19State or Province Name (full name) [Some-State]:TN20Locality Name (eg, city) []:Chennai21Organization Name (eg, company) [Internet Widgits Pty Ltd]:Bobby Dreamer Inc., 22Organizational Unit Name (eg, section) []:Crypto23Common Name (e.g. server FQDN or YOUR name) []:localhost24Email Address []:
1openssl genrsa -out server-key.pem 40962
3# Output4Generating RSA private key, 4096 bit long modulus (2 primes)5.............................++++6..............................++++7e is 65537 (0x010001)
1openssl req -new -sha256 -key server-key.pem -out server-csr.pem2
3# Output4You are about to be asked to enter information that will be incorporated5into your certificate request.6What you are about to enter is what is called a Distinguished Name or a DN.7There are quite a few fields but you can leave some blank8For some fields there will be a default value,9If you enter '.', the field will be left blank.10-----11Country Name (2 letter code) [AU]:IN12State or Province Name (full name) [Some-State]:TN13Locality Name (eg, city) []:Chennai14Organization Name (eg, company) [Internet Widgits Pty Ltd]:Bobby Dreamer Inc., 15Organizational Unit Name (eg, section) []:Crypto16Common Name (e.g. server FQDN or YOUR name) []:server.localhost17Email Address []:18
19Please enter the following 'extra' attributes20to be sent with your certificate request21A challenge password []:22An optional company name []:
1openssl x509 -req -days 365 -in server-csr.pem -CA server-ca-crt.pem -CAkey server-ca-key.pem -CAcreateserial -out server-crt.pem2
3# Output4Signature ok5subject=C = IN, ST = TN, L = Chennai, O = "Bobby Dreamer Inc., ", OU = Crypto, CN = server.localhost6Getting CA Private Key7Enter pass phrase for server-ca-key.pem:
Using the below command you can verify the certificate signature against the CA
1openssl verify -CAfile server-ca-crt.pem server-crt.pem2
3# Output4server-crt.pem: OK
Client details
1openssl req -new -x509 -days 365 -keyout client-ca-key.pem -out client-ca-crt.pem2
3# Output4Generating a RSA private key5......+++++6............+++++7writing new private key to 'client-ca-key.pem'8Enter PEM pass phrase:9Verifying - Enter PEM pass phrase:10-----11You are about to be asked to enter information that will be incorporated12into your certificate request.13What you are about to enter is what is called a Distinguished Name or a DN.14There are quite a few fields but you can leave some blank15For some fields there will be a default value,16If you enter '.', the field will be left blank.17-----18Country Name (2 letter code) [AU]:IN19State or Province Name (full name) [Some-State]:TN20Locality Name (eg, city) []:Chennai21Organization Name (eg, company) [Internet Widgits Pty Ltd]:Browsers Inc.,22Organizational Unit Name (eg, section) []:Security23Common Name (e.g. server FQDN or YOUR name) []:browser.com24Email Address []:
1openssl genrsa -out client-key.pem 40962
3# Output4Generating RSA private key, 4096 bit long modulus (2 primes)5...............................................................................................................................++++6..............................++++7e is 65537 (0x010001)
1openssl req -new -sha256 -key client-key.pem -out client-csr.pem2
3# Output4You are about to be asked to enter information that will be incorporated5into your certificate request.6What you are about to enter is what is called a Distinguished Name or a DN.7There are quite a few fields but you can leave some blank8For some fields there will be a default value,9If you enter '.', the field will be left blank.10-----11Country Name (2 letter code) [AU]:IN12State or Province Name (full name) [Some-State]:TN13Locality Name (eg, city) []:Chennai14Organization Name (eg, company) [Internet Widgits Pty Ltd]:Browsers Inc.,15Organizational Unit Name (eg, section) []:Security16Common Name (e.g. server FQDN or YOUR name) []:client.browser.com17Email Address []:18
19Please enter the following 'extra' attributes20to be sent with your certificate request21A challenge password []:22An optional company name []:
1openssl x509 -req -days 365 -in client-csr.pem -CA client-ca-crt.pem -CAkey client-ca-key.pem -CAcreateserial -out client-crt.pem2
3# Output4Signature ok5subject=C = IN, ST = TN, L = Chennai, O = "Browsers Inc.,", OU = Security, CN = client.browser.com6Getting CA Private Key7Enter pass phrase for client-ca-key.pem:
1openssl verify -CAfile client-ca-crt.pem client-crt.pem2
3# Output 4client-crt.pem: OK
Code is available here in Github
node server.js
node client.js
1D:\BigData\14.Nodejs\17.Certificates\b.client-server_certificate2>node client.js2TLS Socket ERROR (Error: getaddrinfo ENOTFOUND server.localhost)
In Windows, go to C:\Windows\System32\drivers\etc
hosts
file1127.0.0.1 server.localhost2127.0.0.1 client.browser.com
It should look like below
Rerun the client script node client.js
1D:\BigData\14.Nodejs\17.Certificates\b.client-server_certificate2>node client.js2TLS Connection established successfully!3Response statusCode: 2004Response headers: {5 date: 'Mon, 30 Aug 2021 15:25:24 GMT',6 connection: 'close',7 'transfer-encoding': 'chunked'8}9Server Host Name: server.localhost10Received message: OK!11
12TLS Connection closed!
In the server side, you will get response like below,
1D:\BigData\14.Nodejs\17.Certificates\b.client-server_certificate2>node server.js2Mon Aug 30 2021 20:55:23 GMT+0530 (India Standard Time) ::ffff:127.0.0.1 GET /
Tried to connect to server using CURL it did not work. Did not attempt to do any further investigating as it looks like another whole subject to learn.
1curl -k https://127.0.0.1:8888 -v --cacert ./certs/server-ca-crt.pem --key ./certs/client-key.pem --cert ./certs/client-crt.pem2
3# Output 4* Rebuilt URL to: https://127.0.0.1:8888/5* Trying 127.0.0.1...6* TCP_NODELAY set7* Connected to 127.0.0.1 (127.0.0.1) port 8888 (#0)8* schannel: SSL/TLS connection with 127.0.0.1 port 8888 (step 1/3)9* schannel: disabled server certificate revocation checks10* schannel: verifyhost setting prevents Schannel from comparing the supplied target name with the subject names in server certificates.11* schannel: using IP address, SNI is not supported by OS.12* schannel: sending initial handshake data: sending 153 bytes...13* schannel: sent initial handshake data: sent 153 bytes14* schannel: SSL/TLS connection with 127.0.0.1 port 8888 (step 2/3)15* schannel: failed to receive handshake, need more data16* schannel: SSL/TLS connection with 127.0.0.1 port 8888 (step 2/3)17* schannel: encrypted data got 197018* schannel: encrypted data buffer: offset 1970 length 409619* schannel: a client certificate has been requested20* schannel: SSL/TLS connection with 127.0.0.1 port 8888 (step 2/3)21* schannel: encrypted data buffer: offset 1970 length 409622* schannel: sending next handshake data: sending 100 bytes...23* schannel: SSL/TLS connection with 127.0.0.1 port 8888 (step 2/3)24* schannel: encrypted data got 725* schannel: encrypted data buffer: offset 7 length 409626* schannel: next InitializeSecurityContext failed: SEC_E_ILLEGAL_MESSAGE (0x80090326) - This error usually occurs when a fatal SSL/TLS alert is received (e.g. handshake failed). More detail may be available in the Windows System event log.27* Closing connection 028* schannel: shutting down SSL/TLS connection with 127.0.0.1 port 888829* schannel: clear security context handle30curl: (35) schannel: next InitializeSecurityContext failed: SEC_E_ILLEGAL_MESSAGE (0x80090326) - This error usually occurs when a fatal SSL/TLS alert is received (e.g. handshake failed). More detail may be available in the Windows System event log.