Certificate private key: how to generate and protect it
A private key is the secret half of the key pair behind an SSL certificate. When you generate a certificate key, you create both halves at once; the certificate is issued later, for the public half. Each of the HTTPS certificates a server presents carries one public key, and the certificate binds that key to your name so that clients can be confident the matching private key is yours [1]. The certificate is public and goes to every client that connects; the private key stays on the server, in a file with restricted access [6].
- What it is
- the secret half of a key pair; the public half is in the certificate [1]
- Generate it
- with
openssl genpkey[5], on the machine that will use it - Access
- a file with restricted access that the server process can still read [6]
- After a leak
- revoke, stop using it, and replace both the key and the certificate [7]
What a private key file contains
RFC 5958, which replaced the PKCS #8 of RFC 5208, defines the syntax for private-key information: a version, an algorithm identifier, the private key, optional attributes and, in its second version, an optional public key [2]. OpenSSL normally writes this PKCS #8 form and uses an older "traditional" format only when asked [5].
An RSA private key as defined in RFC 8017 includes the modulus and the public exponent alongside the private exponent and the primes [3]. For elliptic-curve keys, RFC 5915 makes the public key field optional and says implementations SHOULD always include it [4]. So an RSA key file always carries the public half of the key pair, and an EC key file does whenever it follows that SHOULD. In our run, openssl pkey -text_pub printed Public-Key: (256 bit) for an EC key and Public-Key: (2048 bit) with Exponent: 65537 for an RSA key [8].
That is how a certificate and its key are compared: the public key derived from the key file must equal the one in the certificate, as the certificate and key matcher in the tools section shows. A certificate cannot replace a lost key file, because it carries only the public key [1].
How to generate a certificate key with OpenSSL
On the manual route of generating an SSL certificate, the key comes first: make it on the server that will use it, then build the request from it. openssl genpkey is the command the OpenSSL manual encourages over the algorithm-specific utilities [5]:
$ openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out example.com.key
$ openssl pkey -in example.com.key -noout -check
Key is valid-algorithm ECwithec_paramgen_curve:P-256creates an elliptic-curve key on P-256, the kind an ECDSA certificate uses. For RSA, use-algorithm RSA -pkeyopt rsa_keygen_bits:2048; 2048 bits is also the default size [5].-checkchecks that the private and public components of the key pair are consistent [5].The file is PEM unless you add
-outform DER[5].
In our run the key file came out as -rw-------, readable only by its owner, while a public key and a signing request written from it in the same directory followed the shell's umask as -rw-rw-r-- [8].
Next, openssl req -new -key example.com.key builds the request from this key instead of creating a new one [5]; the fields it needs are in how to create a certificate signing request. In our run the public key in that request was identical to the one derived from the key file [8].
Generating a key and a certificate
An SSL key and certificate are two different things, made in two places. You generate the key on the server that will use it; a certificate authority issues the certificate, for the public half of that key [1] [7]. Creating an SSL key and certificate for a site therefore takes three steps:
Generate the private key with
openssl genpkey, as above.Build the signing request from that key. The key signs the request and the matching public key is placed in it [5]; the fields are in how to create a certificate signing request.
Send the request to the authority. The certificate it issues binds that public key to the subject named in it [1].
The authority cannot do the first step for you: for website certificates the Baseline Requirements forbid it to generate the key pair on your behalf [7]. The request carries the public key, not the key file [5]. The certificate is the public file that goes to every client, and the key file stays on the server [6].
Where the private key lives
Where the key lives depends on who terminates TLS for the site, and so does who generates it.
| Setup | Where the key is | Who generates it |
|---|---|---|
| Your own server | a file named in the server configuration, such as ssl_ in nginx; it may share one file with the certificate [6] | you, with OpenSSL |
| ACME client on your server | a file the client keeps on that server | the client, or you: Certbot, for example, does not reuse the key at renewal unless --reuse-key is set, and with --csr it uses a certificate signing request you created [9] |
| Hosting platform or CDN | with the platform that terminates HTTPS | the platform |
| Online generator | the generator's server, or your browser if it creates the key there | the site that runs it |
The key does not have to be a file: nginx can load it by id through an OpenSSL provider URI scheme such as pkcs11 [6].
A certificate from a free certificate authority arrives through ACME, so on the client route the key stays with the ACME client on your server. SSL certificate authorities are not where the key comes from: for website certificates they may not generate the key pair for you, and may not accept a request for a key they generated [7].
On Bridge CDN the hosting platform row applies: the key pair behind the certificate belongs to the platform, Bridge SSL is its certificate layer, and there is no certificate upload.
How to protect a private key
Protecting a private key means controlling who can read the file, and limiting what a copy is worth, so that a lost file does not turn into a key compromise.
Restrict the file. nginx describes the private key as a secure entity, to be stored in a file with restricted access that its master process can still read; if the key shares a file with the certificate, that file needs the same restriction [6]. Check the file permissions again after you copy or move the key.
Encrypt the copies that travel.
openssl pkey -aes-256-cbcwrites the key encrypted under a passphrase, and the PEM header line then marks the key as encrypted [5][8]. RFC 5958 says the encryption must be as strong as the key it protects [2]. With a wrong passphrase, OpenSSL stopped withCould not read key from example.com.enc.key[8].Decide how the server unlocks it. nginx loads an encrypted key with passphrases from a file named by
ssl_password_file, trying them in turn [6], so the passphrase then sits on the same machine as the key.Treat it as an obligation. With a publicly trusted certificate, the subscriber agreement commits you to take all reasonable measures to keep the private key confidential and under your control [7].
When a key counts as compromised
The Baseline Requirements call a private key compromised when its value has been disclosed to an unauthorized person, or an unauthorized person has had access to it [7]. Access is enough; nobody has to have used the key. RFC 5280 names the stakes: failing to protect a private key lets an attacker masquerade as its owner [1].
A key can also be weak from the start. An authority must reject a request when there is clear evidence that the method used to generate the key was flawed, and when the public key corresponds to a known weak private key, naming the Debian, ROCA and Close Primes vulnerabilities [7].
Once a key may have leaked:
Request revocation of every certificate that uses it, with key compromise as the reason; revoking a certificate explains how to send the request and why revocation comes first here.
Stop using the key and its certificates, as the subscriber agreement requires [7].
Generate a new key, not only a new request. An authority notified of the compromise must reject new requests for that key, and one that learns the key reached an unauthorized person must revoke every certificate that includes its public key [7].
Get a certificate for the new key and check the pair before reloading.
FAQ
What is a private key?
How do I generate a private key for an SSL certificate?
Run openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out example.com.key on the server that will use it, or -algorithm RSA -pkeyopt rsa_keygen_bits:2048 for an RSA key. Then build the signing request from it with openssl req -new -key example.com.key. [5]
Does the certificate authority generate my private key?
No. For website certificates, the Baseline Requirements forbid the authority to generate the key pair for you or to accept a request for a key it generated earlier. [7]
Sources
RFC 5280, Internet X.509 Public Key Infrastructure Certificate and CRL Profile: §3.1, §4.1.2.7, §8.
RFC 5958, Asymmetric Key Packages: §1, §2, §3, §6; obsoletes RFC 5208 (PKCS #8 v1.2).
RFC 8017, PKCS #1: RSA Cryptography Specifications Version 2.2: Appendix A.1.2.
RFC 5915, Elliptic Curve Private Key Structure: §3.
OpenSSL 3.0 manual: openssl-genpkey, openssl-pkey, openssl-req.
nginx documentation: Configuring HTTPS servers; ngx_http_ssl_module, directives
ssl_certificate_keyandssl_password_file.CA/Browser Forum Baseline Requirements, version 2.3.1: §1.6.1, §6.1.1.3, §6.1.2, §9.6.3.
Lab runs for this page: OpenSSL 3.0.13 on Linux Mint 22.1, test name example.com.
Certbot user guide: command-line options
--reuse-key,--no-reuse-key,--csr.