Part III: Certificates · Chapter 10

Asking for a certificate: key generation and the CSR

In one sentence

You generate a key pair, keep the private key, and send the CA a certificate signing request (CSR) carrying only your public key and the names you want.

Who is this for

Level: Practitioner

On this page
  1. The idea
  2. How it really works
  3. At work
  4. Common mistakes
  5. Why it matters to the business
  6. Check yourself
  7. Go deeper

The idea

  • Beginner

You want a certificate for your website. The certificate will hold your public key, so the first step happens at home, on your own server: you create a key pair. The private key stays on that server. Nobody else ever needs it, not even the certificate authority.

Next you fill in a request form. It says, in effect: “Please certify that this public key belongs to www.example.com and example.com.” This form is a certificate signing request (CSR). You sign it with your private key, and send it to the CA.

The whole journey has five steps:

  1. Generate a key pair on the machine that will use it.
  2. Write the request: the names you want and your public key.
  3. Sign the request with your private key.
  4. Send the CSR to the CA. The CA checks that you really control the names (chapter 11) and then issues a certificate.
  5. Install the certificate next to the private key that never moved.

Why sign the request at all? The signature proves that whoever sent the CSR holds the private key that matches the public key inside it. Without it, Mallory could take Rosa’s public key, put it in a request for a name Mallory controls, and get a certificate that wrongly links the two.

A CSR is not secret: it holds only public information. It is also not a certificate. Nobody trusts a CSR, because only you have signed it. It becomes useful only after a CA has checked it and issued a certificate.

How it really works

  • Developer
  • Expert

What is inside a CSR?

The format is PKCS #10, published as RFC 2986 (PKCS #10). In the words of its introduction, “A certification request consists of a distinguished name, a public key, and optionally a set of attributes”, signed by the entity asking for the certificate. The structure (section 4) has two layers:

  • CertificationRequestInfo, the signed part:
    • version: always 0, which openssl prints as “1 (0x0)”;
    • subject: a distinguished name, for example CN=www.example.com;
    • subjectPKInfo: the algorithm and the public key;
    • attributes: optional extras.
  • signatureAlgorithm and signature: the requester’s signature over the signed part.

Names for websites belong in the SAN extension (chapter 9). A CSR asks for extensions through an attribute called extensionRequest, defined in PKCS #9 (RFC 2985, section 5.4.2). openssl shows it as “Requested Extensions”. Windows calls it “Certificate Extensions”, with the identifier 1.2.840.113549.1.9.14.

How a certificate signing request travels: only the public key and the names leave your server Your server Private key ✓ stays here Public key goes into the CSR CSR names (SAN) public key your signature Certificate authority Checks 1. the CSR signature 2. that you control the names Certificate names + public key + the CA's signature Install certificate beside private key certificate comes back ✗ The private key is never sent to anyone, not even the CA.
Only the public key and the names travel. The private key never leaves your server.

Why does the signature matter?

RFC 2986 section 3 gives the reason in one line: “The signature on the certification request prevents an entity from requesting a certificate with another party’s public key.” This is called proof of possession. The CA verifies the CSR’s signature with the public key inside it. If the signature does not verify, the requester does not hold the matching private key, and the CA rejects the request.

This signature is a self-signature. It is not a vote of trust: it says nothing about who you are.

What does the CA do with your CSR?

The CA does not copy your CSR into a certificate. It builds a new certificate from three sources:

  • Your public key, taken from the CSR unchanged.
  • The names you asked for, but only those you prove you control (chapter 11). Public CAs put them in the SAN and treat the CN as optional.
  • Its own profile for everything else: the validity period, key usage, extended key usage, policies and its own extensions. Public CAs must follow the Baseline Requirements, so a request for a ten-year validity or an extra purpose is simply ignored or refused.

Organisation details, such as O=Example Shop, appear in a public certificate only if the CA validated them (OV or EV). A domain-validated certificate leaves them out, whatever the CSR says.

Where do CSRs show up in practice?

  • Manual ordering: you paste a PEM CSR into a CA’s web portal.
  • ACME (RFC 8555): your ACME client, such as certbot, creates a key and CSR for you and sends the CSR in the “finalize” step. The RFC sends it as “the base64url-encoded version of the DER format” (section 7.4). The CSR must list the same names as the order. See chapter 20.
  • Windows and Active Directory Certificate Services: certreq and auto-enrolment create the key in the Windows key store and send a PKCS #10 request to the CA.
  • Private CAs and devices: the same pattern, often automated (chapter 22, chapter 25).

Which key should I generate?

For a website, an elliptic-curve key on the P-256 curve is small, fast and widely supported. RSA keys of 2048 or 3072 bits work everywhere. Public CAs accept only certain algorithms and sizes (Baseline Requirements, section 6.1.5), and they reject weak keys.

Two habits pay off:

  • Generate a fresh key at every renewal, unless you have a reason not to (such as key pinning, chapter 14). A new key limits the damage if an old one leaked unnoticed.
  • Protect the private key file: readable only by the service account, never in email or chat, never in a source repository. For high-value keys, use hardware that will not export them (chapter 21).

At work

  • Developer
  • IT ops

How do I create a key and a CSR?

With OpenSSL 3, one command creates both:

openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:P-256 -noenc -keyout www.key \
  -subj "/C=BE/O=Example Shop/CN=www.example.com" \
  -addext "subjectAltName=DNS:www.example.com,DNS:example.com" \
  -out www.csr
  • -newkey ec -pkeyopt ec_paramgen_curve:P-256 creates a P-256 key. For RSA, use -newkey rsa:3072 instead.
  • -noenc writes the private key without a password (older OpenSSL versions call it -nodes). Servers usually need this to start unattended, so protect the file with permissions instead.
  • -subj sets the subject. -addext adds the SAN, which is what matters for websites.
  • www.key is your private key. Do not open it in a chat window, a ticket or a website.

In Git Bash on Windows, the leading / in -subj can be rewritten as a Windows path. Run the command with MSYS_NO_PATHCONV=1 in front of it to prevent that.

How do I check a CSR before I send it?

openssl req -in www.csr -noout -text -verify
Certificate request self-signature verify OK
Certificate Request:
    Data:
        Version: 1 (0x0)
        Subject: C=BE, O=Example Shop, CN=www.example.com
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:de:97:84:56:68:98:87:ab:13:b6:9e:ec:e1:43:
                    (4 more lines of the public key)
                ASN1 OID: prime256v1
                NIST CURVE: P-256
        Attributes:
            Requested Extensions:
                X509v3 Subject Alternative Name: 
                    DNS:www.example.com, DNS:example.com
    Signature Algorithm: ecdsa-with-SHA256
    Signature Value:
        30:46:02:21:00:c6:be:5f:e2:f1:a8:dd:22:b9:d5:de:85:f1:
        (3 more lines of the signature)

Check three things: the self-signature verifies, every name you need is under Requested Extensions, and the key type and size are what you intended. The file itself starts with -----BEGIN CERTIFICATE REQUEST-----. If it starts with -----BEGIN CERTIFICATE-----, you have a certificate, not a request.

How do I request many names?

For more than a couple of names, a small configuration file is easier to review and to keep in version control. It contains no secrets:

[req]
prompt             = no
distinguished_name = dn
req_extensions     = ext

[dn]
CN = shop.example.com

[ext]
subjectAltName = DNS:shop.example.com, DNS:api.example.com, DNS:example.com
openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:P-256 -noenc \
  -keyout shop.key -config req.cnf -out shop.csr
openssl req -in shop.csr -noout -text | sed -n '/Attributes/,/Signature Algorithm/p'
        Attributes:
            Requested Extensions:
                X509v3 Subject Alternative Name: 
                    DNS:shop.example.com, DNS:api.example.com, DNS:example.com
    Signature Algorithm: ecdsa-with-SHA256

Does this certificate belong to my key?

When the certificate comes back, check that it holds the public key from your key pair. Hash the public key from each file and compare:

openssl pkey -in www.key -pubout | openssl sha256
openssl req  -in www.csr -noout -pubkey | openssl sha256
openssl x509 -in www.crt -noout -pubkey | openssl sha256
openssl x509 -in wild.crt -noout -pubkey | openssl sha256
SHA2-256(stdin)= ffc0c984958821cfeefca9e1706dcb63e79f580063f460030841d6a20717b61c
SHA2-256(stdin)= ffc0c984958821cfeefca9e1706dcb63e79f580063f460030841d6a20717b61c
SHA2-256(stdin)= ffc0c984958821cfeefca9e1706dcb63e79f580063f460030841d6a20717b61c
SHA2-256(stdin)= 5d4c9cd343675b714f0305bedc6cbecb4b436a63b0310c8715895101c1aedd11

The key, the CSR and www.crt match. wild.crt belongs to a different key, so it will not work with www.key. The first command reads the private key file but prints only the public key’s hash. The private key itself is never shown.

A mismatch is a common reason for a server that refuses to start. nginx, for example, reports key values mismatch (nginx documentation). The same message appears when a certificate file starts with an intermediate instead of the server certificate (chapter 13).

How do I do it on Windows?

certreq builds the key inside the Windows key store, so the private key never exists as a loose file. You describe the request in an INF file, following Microsoft’s certreq reference:

[Version]
Signature=$Windows NT$

[NewRequest]
Subject = "CN=www.example.com, O=Example Shop, C=BE"
KeyAlgorithm = RSA
KeyLength = 3072
Exportable = FALSE
MachineKeySet = TRUE
RequestType = PKCS10
HashAlgorithm = sha256

[Extensions]
2.5.29.17 = "{text}"
_continue_ = "DNS=www.example.com&"
_continue_ = "DNS=example.com"
# in an elevated prompt, because MachineKeySet = TRUE creates a computer key
certreq -new request.inf request.csr
# send request.csr to the CA, receive the certificate as issued.cer
certreq -accept issued.cer
  • MachineKeySet = TRUE stores the key for the computer, so services such as IIS can use it.
  • Exportable = FALSE stops anyone from exporting the private key later.
  • certreq -accept links the issued certificate to the waiting private key and installs it.

To read any CSR on Windows, use certutil -dump. Here it decodes the CSR made with openssl above:

PKCS10 Certificate Request:
Version: 1
Subject:
    CN=www.example.com
    O=Example Shop
    C=BE
...
  Attribute[0]: 1.2.840.113549.1.9.14 (Certificate Extensions)
...
    Subject Alternative Name
        DNS Name=www.example.com
        DNS Name=example.com

Check yours

Paste a CSR into the decoder below to see its subject, its requested names and whether its self-signature verifies. It runs in your browser. A CSR is public information, but never paste a private key into any website.

Try it: CSR decoderOpen the full tool

Runs in your browser. Nothing you paste is sent anywhere. A CSR is public; never paste the private key that goes with it.

PEM text, or a .csr file dropped on the box.

Common mistakes

  • “The CA creates my private key.” In the normal flow, you create it. A key that someone else generated is a key that someone else may have kept. If a portal offers to generate your key, prefer creating it on your own server.
  • “The CSR contains my private key.” It contains only the public key, the names and a signature. You can share a CSR safely.
  • “A CSR is a certificate, so I can install it.” Nobody trusts a CSR. Only the certificate the CA issues can be installed.
  • “Everything in my CSR ends up in the certificate.” The CA decides. It uses your public key and the names you prove, and its own profile for the rest.
  • “Only the CN matters.” Browsers use the SAN. Put every name in the requested SAN extension.
  • “I can reuse last year’s CSR.” That reuses last year’s key. Generate a new key and CSR at renewal, or let your ACME client do it.

Why it matters to the business

  • Leader

Check yourself

Check yourself

Your hosting provider asks you to email them your website's private key so they can order the certificate. What should you do?

  1. Email it inside a password-protected zip file
  2. Refuse, and create the key and CSR on the server yourself, or let the provider generate the key on the server that uses it
  3. Email the certificate instead, because it contains the key
Show answer

Answer B Refuse, and create the key and CSR on the server yourself, or let the provider generate the key on the server that uses it

Check yourself

What does the signature on a CSR prove?

  1. That the CA has approved the request
  2. That the sender holds the private key matching the public key in the CSR
  3. That the sender owns the domain names listed in the CSR
Show answer

Answer B That the sender holds the private key matching the public key in the CSR

Check yourself

You write a validity of five years into your CSR for a public TLS certificate. What happens?

  1. The certificate is valid for five years
  2. The CA sets its own validity, within the public limits
  3. The CA must ask a browser vendor for permission
Show answer

Answer B The CA sets its own validity, within the public limits

Go deeper

In the gameLevel 10: Asking for a certificatePetition Office, Keystone. In development

The crash course covers the CSR in lesson 5, Names, jobs and asking for a certificate.

Early edition. Checked against the standards; an independent expert review is in progress. Found a mistake? Tell us.

Last reviewed Edition 0.9