I was going through the following tutorial https://www.youtube.com/watch?v=8ptiZlO7ROs to set up an HTTPS connection, and noticed that it seems the code only makes use of server.crt
and server.key
(I'm not sure if server.key
is the public or private key in the RSA key pair). But shouldn't two keys be needed for HTTPS? (both public
and private
keys?).
Altogether, the tutorial covers generation of the following files:
ca.crt
ca.key
ca.srl
client.crt
client.csr
client.key
server.crt
server.csr
server.key
But the node.js code only seems to make use of server.crt
and server.key
:
const express = require('express')
const fs = require('fs')
const https = require('https')
const path = require('path')
const app = express()
const directoryToServe = 'client'
const port = 3443
app.use('/', express.static(path.join(__dirname,'..',directoryToServe)))
const httpsOptions = {
cert: fs.readFileSync(path.join(__dirname,'ssl','server.crt')),
key: fs.readFileSync(path.join(__dirname,'ssl','server.key'))
}
https.createServer(httpsOptions,app)
.listen(port, function() {
console.log(`Serving the '${directoryToServe}' directory at localhost:${port}`)
})
My understanding of HTTPS is that:
- The server sends the client a public key
- The client returns a symmetric key encrypted with the public key
- the server decrypts the symmetric key using the private key
- the client and server communicate using the symmetric key
But as the code above uses only one key server.key
(which I assume is the public key?), how does the HTTPS communication work since I assume both assymetric keys should be needed (public and private) to negotiate the symmetric key exchange?
Here is the code to generate the keys/certificates:
#!/bin/bash
# set values for certificate DNs
# note: CN is set to different values in the sections below
ORG="000_Test_Certificates"
# set values that the commands will share
VALID_DAYS=360
CA_KEY=ca.key
CA_CERT=ca.crt
CLIENT_KEY=client.key
CLIENT_CERT=client.crt
CLIENT_CSR=client.csr
CLIENT_P12=client.p12
SERVER_KEY=server.key
SERVER_CERT=server.crt
SERVER_CSR=server.csr
KEY_BITS=2048
echo
echo "Create CA certificate..."
CN="Test CA"
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:$KEY_BITS -out $CA_KEY
openssl req -new -x509 -days $VALID_DAYS -key $CA_KEY -subj "//CN=$CN\O=$ORG" -out $CA_CERT
echo "Done."
echo
echo "Creating Server certificate..."
CN="localhost"
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:$KEY_BITS -out $SERVER_KEY
openssl req -new -key $SERVER_KEY -subj "//CN=$CN\O=$ORG" -out $SERVER_CSR
openssl x509 -days $VALID_DAYS -req -in $SERVER_CSR -CAcreateserial -CA $CA_CERT -CAkey $CA_KEY -out $SERVER_CERT
echo "Done."
echo
echo "Creating Client certificate..."
CN="Test User 1"
USER_ID="testuser1"
P12_PASSWORD=
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:$KEY_BITS -out $CLIENT_KEY
openssl req -new -key $CLIENT_KEY -subj "//CN=$CN\O=$ORG\UID=$USER_ID" -out $CLIENT_CSR
openssl x509 -days $VALID_DAYS -req -in $CLIENT_CSR -CAcreateserial -CA $CA_CERT -CAkey $CA_KEY -out $CLIENT_CERT
openssl pkcs12 -in $CLIENT_CERT -inkey $CLIENT_KEY -export -password pass:$P12_PASSWORD -out $CLIENT_P12
echo "Done."
echo
echo "----- Don't forget to open your browser and install your $CA_CERT and $CLIENT_P12 certificates -----"
echo
Thank you in advance!
server.key
contains the private key? I've appended the key generation code above in the OP.server.key
is the private key, and the public key is contained inserver.crt
). Alternatively, if that's not the case, how would the server know where to fetch its private key? (which is really my original question)options
parameter for thehttps.createServer()
method. That says it accepts any options fromtls.createServer()
,tls.createSecureContext()
andhttp.createServer()
. Digging a bit more, it'stls.createSecureContext()
that asks for thekey
andcert
parameters: nodejs.org/api/tls.html#tls_tls_createsecurecontext_options . This will answer your question definitively.