Basis Lab

Answers · Keeping it safe

Is a TLS certificate itself a secret?

In shortNo. The certificate is public and is sent to every client that connects. The private key kept beside it is the secret, and it is one of the highest value credentials you hold.

No. A TLS certificate is a public document: it is the half of the key pair designed to be handed to strangers, and every client that connects receives a copy before it trusts anything at all. The secret is the private key that sits beside it and never leaves the server.

Every field in a certificate is meant to be read by people who have no relationship with you. It carries the hostname, the dates it is valid between, the name of the issuer, and a public key. During a handshake the server sends the whole thing in the clear, then signs a value with the private key to prove that the public key it just handed over really belongs to it. Anybody can check that signature using the public key inside the certificate. Nobody can produce it without the private key. That is the entire security argument, and it works precisely because the certificate is not secret.

server→client:cert  and  σ=Signkpriv(T)\text{server} \to \text{client}: \quad \mathrm{cert} \;\text{and}\; \sigma = \mathrm{Sign}_{k_{\mathrm{priv}}}(T)

The client then checks that Verifykpub(T,σ)=1\mathrm{Verify}_{k_{\mathrm{pub}}}(T, \sigma) = 1, where kpubk_{\mathrm{pub}} is the key printed in the certificate. If the certificate had to be kept secret, no client could ever learn kpubk_{\mathrm{pub}}, and the check could not happen. Secrecy would defeat the mechanism.

The natural guess fails for that reason. A certificate is a file, it sits on disk under a path like /etc/ssl, and it is occasionally referred to as a security artefact, so it feels like a credential. But a value that is broadcast to every connecting client on every connection cannot be protected, and does not need to be. The thing whose exposure ruins you is the key file next to it, which is often in the same directory and therefore gets the same treatment: copied into a container image, pasted into a chat message to unblock a colleague, and left in a backup. The certificate is signed by a certificate authority and is worthless to an attacker who already has it. The private key is signed by nobody and is worth everything to them.

Counting the copies

A moderate service holds around thirty distinct credentials and each one lives in roughly six places, so the number of copies in existence is 30×6=18030 \times 6 = 180. The private key is one of the thirty. Follow where its copies sit and the count that matters is not six but the subset that survives a rotation, because a copy that stops working when you rotate is an inconvenience and a copy that keeps working is the exposure.

FIG 1
where the copy iswho can read itsurvives a rotation
the secret storetwo people and four servicesno
the process environmentanybody who can run a command in the containerno
a laptop configuration filewhoever has the laptopyes
a chat message to a colleaguethe whole channel, foreveryes
a database backupwhoever can read the backup bucketyes

Three of those five keep working after the key is replaced, and not one of them is recorded anywhere. The secret store is the best protected place on the list and the one people spend their effort hardening, which is wasted work: it was already the tightest of the five.

Where the split moves

The same division holds for client certificates, where the certificate identifies the client and the client's private key is the credential, and for internal certificates that are never published anywhere. An internal certificate does disclose hostnames and internal names if it escapes, and that is a real leak of information, but leaking information is not the same as leaking a credential and should not be ranked as one. The interesting case is the private key held in a hardware module: the key file disappears and the question becomes who can call the module, so the secret has not gone away, it has changed shape from a file you can copy into a permission you can inherit. That moves the copy count without moving the ranking, and it is the same problem as a cloud role, which is a credential that is granted by position rather than by knowledge.

So rank the two halves separately, with the single question the inventory is built on: if somebody outside the company had this value and nothing else, what could they do by tomorrow morning. Holding the certificate, they can do nothing, because they already had it. Holding the private key, they can stand in front of every client that trusts that name and answer as the server, read anything that client sends, and, if the name is shared with an internal service, mint a session for whatever sits behind it. That puts the private key in the top band of the inventory by consequence, not by how secret it feels, and it belongs there even though the certificate printed beside it belongs in no band at all.

Worth keeping

  • A TLS certificate is public by design: it is sent in the clear to every client that connects, and its contents are worthless to an attacker who already has them.
  • The private key beside the certificate is the credential, and anybody holding it can impersonate the server to every client that trusts that name.
  • Rotating a private key without finding every copy leaves the copies that still work, which are usually the ones nobody audited.
  • Rank credentials by what they unlock by tomorrow morning and by how many copies exist, not by how secret they feel.

Where this goes next

This question is one step of Keeping a Secret in Production, a course that works through its subject from the beginning. The page that teaches this part of it is What Counts as a Secret, and it reads the whole way through whether or not you have an account.

What an account changes is the practice: problems standing under every idea, marked with a reason rather than a tick, in a copy of the course that is yours.

Read that pageThe whole course

Other questions people ask about this

  1. How do I stop one service from reading another service's password?Give every service its own identity, grant only the credentials it uses, and test that it cannot read another service's password.
  2. Are environment variables safe for storing passwords?No: environment variables are convenient, but they are inherited by child processes, visible to process inspection and crash reports, and no record is kept when a password is read from them.
  3. How does text I saved in a comment end up running as JavaScript in someone else's browser?The comment stayed text in storage; a page that later pasted it into its own markup made the browser read it as code.
  4. Why does escaping the quotes in user input not stop SQL injection?Escaping quotes only cleans one context; SQL injection stops only when query text and values travel separately, so the value is never parsed as code.
  5. Why isn't encrypting the password enough to keep it safe if the database leaks?Because encryption can be undone by your own login code, so the key that lets you check a password usually sits near the database, and anyone who copies both can read every password.
  6. Is it actually OK to look at a risk and decide not to fix it?Yes, if the decision not to fix it is written down with a reason, a named owner and a date or trigger for looking again; otherwise it is just an oversight.

Read alongside