October 2020 – written by dogoncouch and edited by leaena.
Concept
Public Key Infrastructure (PKI) is an essential part of the internet. It enables identities to be verified in a way that can’t be forged; without it, you could never be sure that the web site you were looking at was really… the web site you were looking at.
The foundations of PKI are the certificate and private key. These can take many forms: they can be stored in separate files, or together in container files; they can be stored as text that looks like random characters, or as binary data; in some cases, they are stored inside of weird proprietary file formats that not even the software vendor really understands anymore. We’ll cover formats in more depth later on.
The way public key cryptography works is defined by the X.509 standard, which is an open standard, allowing interoperability between different systems and vendors. It defines the attributes that certificates should contain, (some of which are mentioned in the next paragraph), and the system for certificate signing.
Certificates
Let’s start with the certificate; a certificate starts out as a certificate signing request (CSR). A CSR is the public half of a public/private key pair (more on that in a minute) with a set of attributes attached about who it is issued to, such as a Common Name (CN; netlab.dogoncouch.net, for example), Subject Alternate Names (SANs; other names the system can use), and the name of the Organization (O) and Organizational Unit (OU) that it belongs to.
It is then signed by a Certificate Authority (CA) certificate, which is really just another certificate. In order for a certificate to be “signed”, a range of dates is added defining when it is valid, along with some information about the CA certificate that is used to sign, and then a hash of the information contained in the certificate is encrypted using the CA certificate’s private key. This can be done manually by a person (such as with the openssl command from the command line), or through an automated process (such as when buying a certificate from a commercial CA; more on those later).
Private Keys
That brings us to private keys. A certificate is really a pair of things, a certificate and private key. They are similar to the public and private key pairs used by SSH; the certificate is like a public key. If you encrypt data using the private key, it can only be decrypted using the public key, and vice versa. When a signature (which is an encrypted hash of information in the certificate) is decrypted using the CA certificate and compared to a hash of the same information calculated by the client, a match verifies that the signature is not forged. Clients like web browsers come pre-installed with commercial CA certificates, so web sites can be recognized automatically (more on that later on).
Certificate Chains
Certificate authority (CA) certificates are often signed by other CA certificates; these are called intermediate certificate authorities, and they’re part of what are known as certificate chains. One CA certificate can be signed by another CA certificate, which can then be signed by yet another CA certificate, and so on. This chain will eventually lead to the root CA certificate, which is usually what is trusted by the client. The client can verify this chain all the way up to the root CA certificate, which it trusts, and know that the server is legitimate.
Intermediate certificate authorities distribute some of the risk involved in PKI. Root CA certificates typically have more than one intermediate CA certificate signing certificates for them. If an intermediate CA is compromised and needs to be revoked, certificates signed by that CA become invalid, but certificates signed by other intermediate CAs under the same root CA are not affected. Using intermediate CA certificates also means that the root CA certificate’s private key can be kept in a more secure place, and only used when new intermediate CA certificates need to be signed.
Commercial vs Internal
Several commercial public CA companies have their root and/or intermediate certificates trusted by popular web browsers, which is what allows us to trust web sites without having to add configuration to our web browser. Getting certificates from these CA companies typically costs money, and that is how they operate. These are needed for any public-facing system that clients need to recognize by default (for example, this web site).
Most large enterprises have their own internal public key infrastructure, which saves money and keeps more of the risk in-house. They don’t need to worry about how a commercial CA secures their CA certificates, they do it internally and can audit the process themselves. When a new computer is set up in one of these enterprises, the IT organization will install their internal CA certificate on the system before giving it to the user, so internal web sites are trusted automatically and the user doesn’t need to have an understanding of how certificates work.
Formats
Certificates come in a wide variety of different formats, and understanding them all can seem like a daunting task. When broken down, however, there are basically only two important things to understand. First, individual certificates and private keys can either be encoded as random-looking text, or as binary data. Second, these individual certificates can either be stored on their own, or in a container with copies of their certificate chain and/or private key. The word container is just a fancy way of saying some file format.
The popular formats for individual X.509 certificates are PEM (privacy enhanced mail) for text certificates, and DER (distinguished encoding rules) for binary certificates. PKCS #12 (public key cryptography standard #12) is a container format for certificates and private keys; it can store a certificate, full chain, and private key in one file. Java key stores are another storage format, but they are best avoided; they are deprecated, and proprietary, and have been largely replaced with PKCS #12.
File extensions for certificate formats vary widely. Extensions are not always tied to a specific format; certificates with an extension of .cer or .crt could be any format. These are often used interchangeably for all three of the formats mentioned above. They do have format-specific file extensions, however; .pem for PEM, .der for DER, and .p12 for PKCS #12. Using format-specific file extensions makes troubleshooting easier; if someone needs to verify the certificate or check its contents from the command line, they don’t have to first determine what format it is.
Certificate Revocation Lists
When certificates are issued, they have a date range that defines when they are valid. However, if a certificate is stolen or otherwise compromised, it’s important for clients to be able to figure out that they should no longer trust that certificate. For this reason, certificates contain a link to a certificate revocation list (CRL), which is a list of certificates signed by a CA that have been revoked. Clients will verify the certificate’s signature, and then check this list to make sure the CA hasn’t revoked the certificate. In most cases, such as modern web browsers, all of this happens automatically in a way that the user doesn’t need to be aware of (unless the certificate is invalid, in which case they will get a security warning).
Self Signed Certificates
A self signed certificate is not signed by a real CA; the certificate is signed using its own private key. These certificates will cause most clients that verify connections to abort the connection with an error or warning; in a web browser, the user will typically get warned that the connection is not trusted, and given the option to trust the site anyway. Trusting the site adds the certificate to the list of CAs that the client trusts, but only for that particular site. This is often done in development environments where security is less of a concern, or as part of initial configuration of some systems, or sometimes just by people who should know better but are in a hurry.
Blindly telling the browser to trust the certificate gets people around the certificate warning, but is a dangerous thing to do. The client could be connecting to a malicious third party, who could decrypt all of the data going across the connection before forwarding it between the client and server. Fortunately, if you have access to the server, there are ways to verify even self-signed certificates. Certificates have a fingerprint, which is a hash of the entire certificate. By looking at this fingerprint on the server (using openssl from the command line on a Linux server, for example) and comparing it to the fingerprint your browser sees, you can still verify that you are looking at the correct server without a certificate chain. This is a good habit to be in, even if you’re working in a development environment.
I think it builds character.