Creating a private Root CA and signing a server certificate (with SAN)

 Notes for the reader

  • Run all commands from a single working folder.

  • Protect rootCA.key (this is the CA signing key). Do not share it.

  • Clients must trust the Root CA certificate (rootCA.pem) or they will still see certificate warnings.

Creating Root CA key and certificate

1. Create your own Root CA private key (rootCA.key)

Recommended: encrypt the Root CA key with a passphrase.

openssl genrsa -aes256 -out rootCA.key 4096

If you do not want a passphrase (not recommended), use:

openssl genrsa -out rootCA.key 4096

2. Create openssl.cfg (Root CA certificate config)

Create a file called openssl.cfg using Notepad and paste the following.
Update C, ST, L, O, OU, CN as needed.

Important: The Root CA CN should be a CA name (example: “Company Root CA”), not a device hostname.

[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_ca
prompt = no
default_md = sha256

[req_distinguished_name]
C = CA
ST = ON
L = Toronto
O = Company
OU = IT
CN = Company Root CA

[v3_ca]
# Extensions for a typical Root CA certificate
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

Save this openssl.cfg in the same directory as rootCA.key.

3. Create the Root CA certificate and self-sign it (rootCA.pem)

openssl req -x509 -new -key rootCA.key -config openssl.cfg -days 3650 -sha256 -out rootCA.pem

Output files created so far:

  • rootCA.key = Root CA private key (keep secure)

  • rootCA.pem = Root CA public certificate (this is what you distribute/trust)

Creating server key and certificate with Subject Alternative Name (SAN)

4. Create the server private key (device.key)

openssl genrsa -out device.key 2048

5. Create openssl2.cfg (CSR + SAN config)

Create another config file called openssl2.cfg using Notepad.
Update the identity fields and set DNS/IP SANs based on how you will access the device.

Why SAN matters: Modern TLS clients use SAN, not CN, for hostname/IP matching. TLS clients/browsers ignore CN for name matching now and rely on SAN. If you connect by hostname, you need a DNS SAN. If you connect by IP, you need an IP SAN.

[req]
distinguished_name = req_distinguished_name
prompt = no
default_md = sha256
req_extensions = req_ext

[req_distinguished_name]
C = CA
ST = ON
L = Markham
O = Company
OU = IT
CN = device1.company.com

[req_ext]
basicConstraints = CA:FALSE
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
DNS.1 = device1.company.com
IP.1 = 192.168.0.10

If you ONLY connect by IP, you can omit the DNS line.
If you ONLY connect by hostname, you can omit the IP line.

6. Create the CSR file (device.csr)

openssl req -new -key device.key -out device.csr -config openssl2.cfg

7. Create the server certificate (device.crt) signed by your Root CA

openssl x509 -req -in device.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out device.crt -days 3650 -sha256 -extfile openssl2.cfg -extensions req_ext

This also creates a serial file like rootCA.srl (normal/expected).

Verification

8. Verify the certificate chains to your Root CA

openssl verify -CAfile rootCA.pem device.crt

9. Confirm SAN is present

openssl x509 -in device.crt -noout -ext subjectAltName

10. View full certificate details

openssl x509 -in device.crt -noout -text

Installing / Trusting 

  • Install device.key + device.crt on the server/device.

  • Import/trust rootCA.pem on client machines/applications (OS trust store, browser trust store, Java trust store, etc.).
    Otherwise, clients will still show “untrusted certificate”.

Comments