OpenSSL Cheatsheet

CSRs and Certificates

Use this OpenSSL reference while you build software engineering projects, review code, or refresh the syntax you reach for most.

Create a CSR from an existing key

A certificate signing request bundles a public key plus the subject and the extensions you want, signed by the matching private key.

openssl req -new -key key.pem -out req.csr \
  -subj "/C=US/ST=California/L=San Francisco/O=Acme Inc/CN=example.com"

-subj skips the interactive prompts. Without it OpenSSL asks for every field and a bare Enter leaves it empty, which some CAs reject.

Key and CSR in one command

openssl req -new -newkey rsa:2048 -noenc \
  -keyout key.pem -out req.csr \
  -subj "/C=US/O=Acme Inc/CN=example.com"

# EC instead of RSA
openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 \
  -noenc -keyout ec.key -out req.csr -subj "/CN=example.com"

-noenc (formerly -nodes) writes the key unencrypted, which is what a web server needs to start without a prompt.

Subject Alternative Names

Every modern browser ignores CN and reads SAN only. A CSR without a SAN produces a certificate no browser will trust, so always add one.

openssl req -new -key key.pem -out req.csr \
  -subj "/CN=example.com" \
  -addext "subjectAltName=DNS:example.com,DNS:www.example.com"

# Wildcard plus apex
openssl req -new -key key.pem -out req.csr \
  -subj "/CN=example.com" \
  -addext "subjectAltName=DNS:example.com,DNS:*.example.com"

# IPs and emails in the same list
openssl req -new -key key.pem -out req.csr \
  -subj "/CN=box.internal" \
  -addext "subjectAltName=DNS:box.internal,IP:10.0.0.5,IP:127.0.0.1"

-addext may be repeated, once per extension:

openssl req -new -key key.pem -out req.csr -subj "/CN=example.com" \
  -addext "subjectAltName=DNS:example.com" \
  -addext "keyUsage=critical,digitalSignature,keyEncipherment" \
  -addext "extendedKeyUsage=serverAuth,clientAuth"

Subject field reference

The -subj string is slash separated, /Key=Value, and order is conventional rather than enforced.

KeyNameExampleNotes
CCountryUSTwo letters, uppercase, ISO 3166
STState or provinceCaliforniaSpell it out
LLocalitySan FranciscoCity
OOrganizationAcme IncLegal name for OV/EV
OUOrganizational unitITIgnored by public CAs now
CNCommon nameexample.comCosmetic for TLS, SAN wins
emailAddressEmailops@acme.comUsed by S/MIME, not TLS

A value containing a slash needs escaping, or switch to a config file:

openssl req -new -key key.pem -out req.csr \
  -subj "/O=Acme\/Widgets/CN=example.com"

Read a CSR back

Never send a CSR you have not read. This is the single most common source of a rejected order.

openssl req -in req.csr -noout -text            # everything
openssl req -in req.csr -noout -subject         # subject line only
openssl req -in req.csr -noout -verify          # self-signature check
openssl req -in req.csr -noout -pubkey          # embedded public key

Pull just the SANs out:

openssl req -in req.csr -noout -text | grep -A1 "Subject Alternative Name"

Confirm the CSR matches the key you think it does:

openssl req  -in req.csr -noout -pubkey | openssl sha256
openssl pkey -in key.pem -pubout      | openssl sha256

Same digest means same key pair.

Config file instead of flags

For anything repeated, put the extensions in a file. This is the only way to get a SAN into x509 -req on OpenSSL 1.1.x.

# csr.cnf
[req]
default_md         = sha256
prompt             = no
distinguished_name = dn
req_extensions     = v3_req

[dn]
C  = US
O  = Acme Inc
CN = example.com

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

[alt]
DNS.1 = example.com
DNS.2 = www.example.com
IP.1  = 10.0.0.5
openssl req -new -key key.pem -config csr.cnf -out req.csr

Gotchas

- -addext needs OpenSSL 1.1.1 or newer. On older builds use -config with a req_extensions section. - -addext silently loses to -config when the same extension appears in both. Pick one mechanism per CSR. - A CSR carries no validity dates and no serial. Those are chosen by the signer, so -days on req -new is ignored unless -x509 is also present. - Public CAs discard most of your CSR. They keep the public key and often the SANs, then set the subject, dates, and extensions themselves. - Wildcards cover one label only. *.example.com matches www.example.com but not a.b.example.com and not the bare example.com. - -noenc on a CSR command applies to the key written by -keyout, not to the CSR itself. CSRs are never encrypted.