# Certificates Distributing public keys is a way to enable authentication of machines. Machine A sends a message to machine B, claiming the identity K_A, by signing with k_A. B verifies that signature, hence the identity. But this protocol requires B to know or to ascertain K_A. Until now, we've just assumed there's a way for B to do that. Let's actually solve the problem now. ### Digital Certificates A *digital certificate* (henceforth, *certificate*) is a signature Sign(id_S, K_S; k_I) on the pair of an identity id_S and public key K_S of a subject S. A certificate is created by an *issuer* I, whose signing key is k_I. The certificate binds id_S to K_S according to I. As a simpler notation for this idea, let Cert(S; I) be a certificate issued by I for S. Hence Cert(S; I) = Sign(id_S, K_S; k_I). If machine A has acquired a certificate Cert(S; I), and if A trusts I to issue that certificate, then A has a basis to verify S's identity. **Authentication with Certificates**  1. S: Let m = "I'm id_S". Compute s = Sign(m; k_S). 2. S -> A: m, s 3. A: Find a certificate Cert(S; I) from a trusted issuer I. Verify the signature of I on the certificate. Verify that the identifier in the certificate is id_S. Retrieve K_S from the certificate. Accept if Ver(m; s; K_S).  In step 1, m could contain additional information to be authenticated beyond the identity of S. In step 3, one common implementation error is to forget to verify id_S. Indeed, sometimes crypto libraries will not do this for you by default. The most common format for certificates is X.509, an international standard. Beyond id_S, K_S, and the signature, an X.509 signature also contains a serial number, a validity interval, and several other data. ### Public Key Infrastructure The final step above requires verifying a signature on a certificate. If A already knows I's public key, that's not a problem. But if not, it seems like all we've done is to make a recursive call: to verify S's key, A needs to verify I's key. And that might involve finding and verifying even more certificates. Where does the recursion end? At some point, A needs to reach a certificate issued by a principal that A is willing to trust. To solve this problem, we need a system to help mangage the distribution of certificates. Such systems are called *public key infrastructures* (PKIs). There are two philosophies for building PKIs: - **Decentralized:** anarchy, no publicly recognized leaders, e.g., PGP - **Centralized:** oligarchy, leadership of a few elite, e.g., CAs ### PGP: Pretty Good Privacy PGP, a program implementing encryption and digital signature schemes, was invented by Phil Zimmerman in 1991. He made it and source code publicly available. This was notable as the first time there had been popular open source for public-key cryptography. The US Customs Service launched a criminal investigation for violation of export laws. High-strength cryptography was classified as a munition, so there was some question that Zimmerman might have been guilty of arms trafficking. After three years, the investigation was dropped. The philosophy of PGP is decentralized. Management of certificates devolves to users; anyone can certify anyone else and distribute that certificate as they wish. With PGP, a user A accumulate certificates that she trusts on a *keyring*. The user's own key is on that keyring as a *self-signed* certificate Cert(A; A). From time to time, A might synchronize with another user B, importing keys from B's keyring. When a user acquires a certificate, she records how much trust to place in the issuer, hence in the certificate. The result is a *web of trust*: a user can have multiple certificates for a given key from multiple issuers. There's no central repository of certificates that has to be trusted. So there's also no central service that could be taken down, DOS'd, coerced, seized by law enforcement, etc. Nonetheless, it's convenient to have such servers, and they do exist. [MIT runs one](https://pgp.mit.edu/), for example. **Example.** *Suppose Bob sends Alice a message that he signs. Alice now needs to verify the signature, and to do that, she needs a certificate for Bob. She searches for certificates for Bob, and manages to find Cert(Bob;Dave), Cert(Bob;Bob), and Cert(Bob;Carol). Alice doesn't happen to know Dave, Bob, or Carol. So she searches around for certificates for them. She manages to find a certificate Cert(Carol; Ellen), and realizes that Ellen is a friend of her that she trusts, and that Ellen's public key is already in her (Alice's) keyring, as Cert(Ellen;Alice). So Alice has Cert(Alice; Alice), Cert(Ellen; Alice), Cert(Carol; Ellen), Cert(Bob; Carol). After verifying all those certificates, Alice can create a new certificate Cert(Bob; Alice), put it in her keyring, and later distribute it to others. And, of course, she can verify Bob's signature on the message.* In the example above, Alice ends up with a list of certificates: Cert(Alice; Alice), Cert(Ellen; Alice), Cert(Carol; Ellen), Cert(Bob; Carol). This list forms a *certificate chain*, starting with a certificate for Alice and ending with a certificate for Bob. At the *root* is a key that Alice trusts (her own), called the *root of trust*. In this case, Alice was able to find a chain, but in general it might not be possible to find a path through the web of trust that enables creation of a certificate chain with a trusted root. PGP was designed to help humans manage their security, so the discussion above is phrased in terms of humans. But it applies equally well to machines, and could be used for authentication of machines. More common for that task, however, is the use of certificate authorities.