Guides / The ask, not the certificate

Certificate signing request

A CSR is a public request: bind these names to this public key. The private key never leaves the machine that made it. The CA answers with a certificate.

Certificate signing requestA private key stays on the machine. From it a CSR carries the public key, subject and SAN names to a CA. The CA returns a certificate that sits under its signature.EMITSENDSIGNKEYPrivate keysite.keyASKCSRpubkey / CN / SANCACAissuerCERTCertificatesigned PEMA CSR IS THE ASK. THE PRIVATE KEY NEVER TRAVELS.The CSR asks the CA to bind this public key to these names (subject / SAN).Send the CSR. Never the key. The certificate comes back under the CA.

The CSR is the ask: take this public key and bind it to this subject and these SAN names. The private key never travels. The CA answers with a certificate that sits under its signature — same public key, same names, now signed. Clients trust that certificate because they already trust the CA. They never see the request.

First principles

A certificate signing request is not a certificate. Generate the private key on the machine that will terminate TLS, or in the HSM or load-balancer that will hold it. Emit the CSR from that key. If the private key travels with the request, the key is burned and you start again.

Three files, three jobs. The key is the secret. The CSR is the request. The certificate is the answer. Browsers and clients never see the CSR. They see the certificate. Read TLS certificates on this desk for what the client actually checks.

Names live in SAN

Modern clients match the host you typed against subjectAltName, not against CN. A CSR whose only name is in CN will get you a certificate that browsers refuse. List every name you need: the apex, www, the API host. A certificate for site.example is not a certificate for www.site.example unless you asked for both.

Make a key, then a CSR

Same OpenSSL path on macOS Terminal, Linux, and Windows if openssl is on the PATH (Git for Windows includes it). Stock macOS ships LibreSSL, which is why the SAN names go in a config file rather than a one-liner flag.

Write a config. Replace the names with yours.

[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no

[req_distinguished_name]
CN = site.example

[v3_req]
subjectAltName = @alt_names

[alt_names]
DNS.1 = site.example
DNS.2 = www.site.example

Then the key, then the request. Mode 600 on the key. Do not overwrite a live key to issue a CSR.

openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out site.key
chmod 600 site.key
openssl req -new -key site.key -out site.csr -config site.cnf

Some CAs still demand RSA. Same loop, different key:

openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out site.key

Inspect before you send

Read the CSR. Confirm the names. Confirm it is a request, not a private key.

openssl req -in site.csr -noout -text

You should see Subject, a public key, and X509v3 Subject Alternative Name with every host you listed. You should not see BEGIN PRIVATE KEY. The file you paste into the CA portal, attach to a ticket, or hand a vendor is site.csr only.

What an admin actually does

  • Generate the key on the machine that will terminate TLS, or in the HSM / load-balancer that will hold it. Do not generate it on a laptop and email it in.
  • Send the CSR. Never the key. Never a file that begins with BEGIN PRIVATE KEY or BEGIN OPENSSH PRIVATE KEY.
  • When the certificate comes back, install it next to the same private key. A cert for a different key is a mismatch. The listener will fail.
  • ACME tools (Caddy, certbot, win-acme) mint the CSR for you. You still need this loop for an internal CA, a commercial CA portal, or a vendor that asks you to paste a CSR.
  • If the key leaked, stop using it. New key, new CSR, new certificate. Revoke the old one with the CA if they issued it.

Informed by openssl-req(1). Wording is ours.