CSR explained: how to generate a signing request safely
A certificate signing request (CSR) is a file you generate and send to a certificate authority. It carries the names you want covered and your public key, and it is signed with the matching private key. The signature proves you hold that key, so nobody can request a certificate for someone else's public key. The certificate that comes back holds your name and public key, plus the issuer's name and a serial number and validity period that the authority chooses [1]; what an SSL certificate is covers the rest.
The private key itself never goes into the request or to the authority. For website certificates, the Baseline Requirements do not let the authority generate it for you [5].
- Format
- PKCS #10 [1]
- Inside
- subject name, public key, attributes, signature [1]
- Not inside
- private key, issuer, serial number, validity period [1]
- Text form
-----BEGIN CERTIFICATE REQUEST-----[3]- Key sizes
- RSA 2048 bits or more; ECDSA P-256, P-384, P-521 [5]
- Names
- every hostname in the subject alternative name list [5]
What a certificate signing request contains
RFC 2986 defines a certificate signing request as three parts: the request information, a signature algorithm identifier, and a signature over the request information. The request information holds four fields [1]:
Version: 0 in this version of the standard. OpenSSL prints it as
Version: 1 (0x0)[8].Subject: the distinguished name, meaning the common name and, for organisation-validated certificates, the organisation and its location [5].
Subject public key: the key algorithm and the public half of your key pair.
Attributes: optional extra data. The extension request attribute carries extensions you want in the certificate, including the subject alternative name list. The challenge password attribute is a password for requesting revocation, and the issuer decides what it means (RFC 2985) [2].
When you create a CSR, the tool DER-encodes the request information and signs it with your private key. That structure is what the CSR file holds, and OpenSSL can write it as PEM text or as binary DER [6]. The authority checks that signature, authenticates you and builds the certificate; it may use the requested extensions when it does. A request has no field for the issuer, the serial number or the validity period [1].
How to generate a CSR with OpenSSL
To generate a CSR, run one openssl req command. It creates a new private key and the request for it [6]:
$ openssl req -new -newkey rsa:2048 -noenc \
-keyout example.com.key \
-out example.com.csr \
-subj "/CN=example.com" \
-addext "subjectAltName=DNS:example.com,DNS:www.example.com"-newkey rsa:2048generates a 2048-bit RSA key [6], the smallest RSA size an authority may accept [5].-noencwrites the key without a passphrase. It replaces-nodes, deprecated since OpenSSL 3.0 [6].-subjsets the subject, and-addextadds the subject alternative name list as a requested extension [6].
For an organisation-validated certificate, add the verified fields to -subj, for example /C=GB/L=London/O=Example Ltd/CN=example.com.
The key file is your private key; the CSR carries only the public key. On our test machine (OpenSSL 3.0.13, Linux Mint 22.1) it came out as -rw-------, readable only by its owner, while the CSR followed the shell's umask as -rw-rw-r-- [8]. Never copy the key into a repository, a ticket or a chat message.
The request is one step of creating an SSL certificate, alongside proving control of the names and installing what the authority returns.
An ECDSA key instead of RSA
Replace -newkey rsa:2048 with -newkey ec -pkeyopt ec_paramgen_curve:P-256; ec_paramgen_curve picks the curve [6]. P-256, P-384 and P-521 are the curves the Baseline Requirements allow [5]. Decoded, such a request shows NIST CURVE: P-256 and ecdsa-with-SHA256 [8].
A self-signed certificate, or a request on IIS
Adding -x509 to the RSA command makes OpenSSL output a certificate instead of a request [6]. The result is a self-signed certificate, with no authority involved.
On Windows servers with IIS, the request is made in IIS Manager or with certreq; that procedure is in the IIS part of the installation section.
What to put in each field
When you generate a CSR, put every hostname in the subject alternative name list. A publicly trusted certificate must carry that list, and a common name, if present, must repeat one of its entries [5]. Clients must not identify a server by the common name (RFC 9525) [4]. RFC 2986 leaves it to the authority whether it uses the extensions requested in a certificate signing request [1], so listing every name yourself removes the guess. How the list works is covered on SAN certificates.
Subject fields by validation level
The rest of the subject depends on the validation level. The Baseline Requirements fix which attributes each kind of certificate may carry [5]:
| In the certificate | Domain-validated certificate | Organisation-validated certificate |
|---|---|---|
| Subject alternative names | must be present | must be present |
| Common name (CN) | not recommended; if present, one of the SAN entries | the same |
| Organisation (O) | must not appear | must: your organisation's name or trade name |
| Country (C) | may: two-letter code | must: two-letter code |
| State (ST) or locality (L) | must not appear | at least one of the two |
| Organisational unit (OU) | must not appear | must not appear |
| Any other attribute, such as an email address | must not appear | not recommended |
For a domain-validated certificate, the organisation and location you type cannot appear in the certificate [5]. That includes a free SSL certificate from Let's Encrypt, which offers domain-validated certificates and no organisation or extended validation [7]. For organisation validation, the authority verifies each of these fields before it puts them in the certificate [5].
Leave out the challenge password unless your authority asks for one; OpenSSL's own signing tools ignore it [6].
Check the CSR before you submit it
Decode the request and read back what it declares:
$ openssl req -in example.com.csr -noout -text -verify
Certificate request self-signature verify OK
Certificate Request:
Data:
Version: 1 (0x0)
Subject: CN = example.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Attributes:
Requested Extensions:
X509v3 Subject Alternative Name:
DNS:example.com, DNS:www.example.com
Signature Algorithm: sha256WithRSAEncryptionThe modulus, exponent and signature bytes are cut from this output [8]. Check four things:
verify OK, which means the self-signature matches the public key inside [6], so whoever made the request held the private key [1];the subject;
the key size;
every name under Subject Alternative Name.
The file itself starts with -----BEGIN CERTIFICATE REQUEST-----, the label RFC 7468 gives to PKCS #10 requests. Some tools write NEW CERTIFICATE REQUEST, which parsers may treat as the same [3]. Submit the whole text, both lines included.
What a missing name list looks like
The same command on a request made without -addext:
Attributes:
(none)
Requested Extensions:
Signature Algorithm: sha256WithRSAEncryptionThere is no Subject Alternative Name line [8]. Generate the request again before you submit it: once a certificate is issued, adding a name means a new certificate.
A valid signature is not an accepted key
OpenSSL creates and verifies a 1024-bit request without complaint, printing verify OK and Public-Key: (1024 bit) [8]. An authority must reject it: the Baseline Requirements allow RSA keys of at least 2048 bits and ECDSA keys on P-256, P-384 or P-521, and no others. It must also reject a key known to be compromised or weak, such as the Debian weak keys [5].
Does the request match your key
The CSR and the key file must hold the same public key:
$ openssl req -in example.com.csr -noout -pubkey | openssl sha256
SHA2-256(stdin)= 7eb4866ac03c9d6bbfbd5c6edd5fdef0f68bb36e0b82cdc43ff5563edb586a2f
$ openssl pkey -in example.com.key -pubout | openssl sha256
SHA2-256(stdin)= 7eb4866ac03c9d6bbfbd5c6edd5fdef0f68bb36e0b82cdc43ff5563edb586a2fEqual digests mean the two belong together [6][8]. A request generated against the wrong key gives two different digests.
Reusing a CSR at renewal
A request is bound to one key pair [1], so reusing it at renewal reuses the key. In our run, a new request made with -key example.com.key carried the same public key as the first one, down to the same SHA-256 digest [8]. A key kept for years has an exposure history nobody can reconstruct.
Generating a fresh key and request each time costs one command: -newkey instead of -key. With regular renewal, the key is then replaced along with the certificate.
Where the private key should live
You can regenerate a request with one command; you cannot take back a leaked key. If an authority learns that a subscriber's private key was communicated to an unauthorised person or an unaffiliated organisation, it must revoke every certificate with that public key [5].
Generate it where it will be used. A key created on the server that serves the certificate never travels. If it must move, move it once, over a channel you control.
Keep it out of convenient places. Repositories, tickets, chats and shared drives keep copies longer, and show them to more people, than anyone intends.
Decide who can read it. File permissions should allow exactly the account that needs it.
Plan for replacement. A new key at each renewal limits what an old exposure is worth.
If you do not want to use the command line
An online generator builds a request from a form. Ask where it creates the key. A generator that makes the key on its server has held your private key; one that creates the key in your browser keeps it on your device. If a tool does not say which it does, assume the server.
For website certificates, authorities must not generate a key pair for a subscriber, and must not accept a request whose key they generated earlier [5]. A service that offers to create your key is doing what an authority is forbidden to do. A decoder that only reads a request sees nothing secret, because the request carries only the public key [1].
FAQ
What is a CSR file?
A file holding a certificate signing request. In text form it is base64 between -----BEGIN CERTIFICATE REQUEST----- and -----END CERTIFICATE REQUEST----- lines. It carries the subject, the public key and any requested extensions, signed with your private key.
How do I generate a CSR?
Run openssl req -new -newkey rsa:2048 -noenc -keyout example.com.key -out example.com.csr, with your names in -subj and -addext as shown above. It writes a new private key and the request in one step.
Does the private key go to the certificate authority?
No. Only the public key is in the request. For website certificates, an authority must not generate the key pair for you.
Why does my certificate not cover www?
Compare the subject alternative names in the request and in the certificate. Clients identify a server by those names, not by the common name. If a name is missing, generate a new request that lists every name and have the certificate reissued.
Can I reuse an old CSR at renewal?
You can, but it keeps the same key pair.
How do I check a CSR before sending it?
Run openssl req -in example.com.csr -noout -text -verify and read verify OK, the key size and the subject alternative names.
Sources
RFC 2986, PKCS #10: Certification Request Syntax Specification, sections 3, 4.1, 4.2.
RFC 2985, PKCS #9: Selected Object Classes and Attribute Types, sections 5.4.1, 5.4.2.
RFC 7468, Textual Encodings of PKIX, PKCS, and CMS Structures, sections 2, 7.
RFC 9525, Service Identity in TLS, section 2.
CA/Browser Forum Baseline Requirements, version 2.3.1: §3.2.2.1, §3.2.2.2, §6.1.1.3, §6.1.2, §6.1.5, §7.1.2.7.2, §7.1.2.7.4, §7.1.2.7.6, §7.1.4.3.
OpenSSL 3.0 manual: openssl-req, openssl-genpkey, openssl-pkey.
Let's Encrypt, FAQ: certificate types offered.
Lab runs for this page: OpenSSL 3.0.13 on Linux Mint 22.1, test name example.com.