Appendix G. Public-Key Cryptography and Certificates

The introduction in 1976 of public-key cryptography by Whitfield Diffie and Martin Hellman represented a major breakthrough in the design of large-scale, secure communication systems. The main idea behind their proposal is the generation and usage of one or more key pairs by each entity, each composed of a private key and a public key. The private keys must remain confidential and never have to be sent to other parties. On the other hand, the public keys can be openly distributed without any confidentiality requirements. These distributed public keys can then be used by third parties to:

  • Send encrypted messages that can be decrypted only by the private key holder.
  • Validate signatures that can only have been produced by the private key holder.

Public-key cryptography is also called asymmetric cryptography since its mechanisms use two keys with different confidentiality requirements and different purposes:

  • Private keys must remain confidential and are used to decrypt messages or to produce digital signatures.
  • Public keys can be openly distributed without any confidentiality requirements and are used to encrypt messages or to validate signatures.

This contrasts with classical cryptography, also called symmetric cryptography, where the same key, which must remain secret, is used for all operations (e.g., encrypt and decrypt). Since the currently known asymmetric mechanisms have lower performance than their symmetric counterparts, it is common to use hybrid techniques. For instance, in TLS the asymmetric mechanism is used by the handshake protocol to establish a set of confidential symmetric session keys, which are then used by the record protocol to protect the bulk of the exchanged messages using a symmetric mechanism.

However, public-key cryptography introduces a new problem: public key authentication. Even if public keys can be openly distributed, the receiving parties must have some secure way of knowing to whom they belong (i.e., who is the holder of the associated private keys). Failure to correctly authenticate public keys makes them vulnerable to man-in-the-middle (MITM) attacks, where an attacker replaces an entity public key with its own. This allows the attacker to decrypt every message sent to that entity, since it is in possession of the private key associated with the used public key.

A common way of authenticating public keys is by using public key certificates, which are statements binding a public key to a subject, issued and signed by certification authorities (CA). These CAs are third parties on which a set of entities recognizes authority and competence to verify this binding; that is, they check whether the holder of the private key associated with a public key is also the owner of a name (e.g., DNS name).

To make things a little more concrete, let’s consider the example where a client performs an HTTP request to the resource identified by Since the URI has the https scheme, the HTTP request message must be sent on a TLS- or SSL-protected connection. The secure connection is established by the handshake protocol, which starts with the client sending a client hello message to the server, including the client-supported cryptographic mechanisms. The server responds with a server hello message with the chosen cryptographic mechanisms and also with a certificate message containing the server’s certificate, represented in Figure G-1.

This certificate follows the X.509 specification and is composed of several fields, such as:

  • The public key field, containing the server’s public key
  • The subject field with the server’s name, which in this case is the * wildcard
  • The issuer field containing the issuing entities’ name (the CA name), which is Microsoft Secure Server Authority

The certificate also contains a signature produced by its issuer, so that it can be stored and distributed via unsafe channels.

The * certificate
Figure G-1. The * certificate

Upon receiving this certificate, the client can then use the contained public key to encrypt a secret random seed value and send it to the server. This random seed is a secret value that will be used by both the client and the server to deterministically derive the set of session keys used to protect the exchanged byte stream. However, first the client must ensure that (among other things):

  • The certificate’s subject matches the https URI hostname.
  • The certificate was not tampered with while in transit from the server to the client (the handshake protocol is done over an unprotected connection).
  • The issuing CA (Microsoft Secure Server Authority, in the previous example) is trusted, in this context, to perform the binding between public keys and entity names.

The last verification is usually accomplished through a comparison of the certificate issuer’s field against a trust store containing the trusted issuer’s names and their public keys. The second task involves validating the certificate’s signature using the issuer’s public key, also present in this store.

Trust stores are typically composed of self-issued certificates, each one holding a trusted CA name and its public key. These self-issued certificates are created by CAs and distributed out-of-band, via an authenticated mechanism. The decision to add a self-issued certificate to this trust store means that the consuming entity:

  • Has decided to trust the CA identified in the subject’s field—that is, assumes that every certificate issued by the CA will contain a true public key binding
  • Has checked that the contained public key does indeed belong to the CA

We stress this last requirement, since a self-signed certificate is not sufficient to bind a public key to a name: this verification must be done by alternative means.

Figure G-2 represents an example for the model we just described.

Certificate issued directly by a trusted CA
Figure G-2. Certificate issued directly by a trusted CA

In the figure:

  • CA0 issues the CS certificate after checking that the entity running the server is the holder of the private key associated with server-key and also the legal owner of the domain name.
  • The client trusts CA0 for certificate purposes and so installs the CA0 self-issued certificate in its trust store, after checking the correctness of the certificate information, namely its public key.
  • During the TLS handshake protocol, the client receives the CS certificate and validates it by checking that (1) it was issued by a trusted CA and (2) its signature is successfully validated through the CA’s public key. After this, the client uses server-key to encrypt a secret seed that can be decrypted only by the name (according to CA0).

Certificate issuance by a CA should be preceded by a secure verification of the certified information, particularly the binding of the public key to a name. Typically, CAs describe this secure verification procedures in a document called Certification Practice Statements. Depending on the name scope (DNS name, email, citizen’s identifier), the verification can be expensive (e.g., verifying official records to ensure that an entity is the owner of a registered name) or difficult to perform (the CA does not have any relation to the naming authority). Hence, CAs can delegate their certification capability to other CAs, called intermediate CAs or subordinate CAs. They do so by issuing a certificate, where the issuer is the directly trusted CA and the subject is the intermediate CA. This certificate serves two purposes: in addition to binding the intermediate CA name to its public key, it also states that a subset of the issuer’s certification capabilities are delegated to the intermediate CA.

Intermediate certification authorities and certification paths
Figure G-3. Intermediate certification authorities and certification paths

Figure G-3 shows this extended model, where:

  • CA0, usually called the root CA because it is directly trusted by the client, delegates its certification capability to CA1 by issuing the intermediate C1 certificate.
  • It is CA1, not CA0, that checks if the entity running the server is the holder of the private key associated with server-key and also the legal owner of the domain name.

In this model, the server certificate validation requires building a certificate chain—composed of all the certificates from the directly trusted C0 certificate (present in the trust store)—to the server’s certificate, via the intermediate certificate C1.

Returning to our concrete scenario, Figure G-4 shows the * certification path, composed of two intermediate CAs. Only the root CA (GTE CyberTrust Global Root) is directly trusted by the client. However, this CA has delegated its certification authority to Microsoft Internet Authority, which in turn redelegated it to Microsoft Secure Server Authority. It is this last CA that issues the server certificate.

The server’s certificate path
Figure G-4. The server’s certificate path

On Windows systems, certificates are managed via stores, such as the ones represented in Figure G-5. These stores are grouped by store location (current user, local computer) and have specific semantics. For instance:

  • The Personal store contains the certificates for which the private key associated with the public key is also stored.
  • The Trusted Root Certification Authorities store contains the trusted certificates that can be used as roots for the certification paths.
  • The Intermediate Certification Authorities store contains CA certificates that are not directly trusted but that can be used to build a certification path.
Windows certificate stores
Figure G-5. Windows certificate stores

When the Windows certificate management system has to validate a certificate, it considers a certification path valid only if the root is in the Trusted Root Certification Authorities store. You must take great care before adding certificates to this store, since its contents define who is allowed to issue valid certificates. As an example, by adding a certificate to this trust store, the Fiddler tool is able to dynamically issue valid certificates for any server name. This allows Fiddler to intercept the HTTPS traffic by impersonating the remote server. This is an example of a MITM attack, used in this case for benign development and debugging purposes.


The validity of the certificate information can change over time. Namely, if an attacker is able to obtain an entity’s private key, then the associated public key should not be used anymore.

One way of accomplishing this is by using certificate revocation lists (CRL) containing invalidated (revoked) certificates. For instance, in the previous example the * certificate contains a CRL distribution point field with a CRL URI ( When validating the certificate, this URI can be used to retrieve the CRL and check if the certificate hasn’t been revoked.

An alternative method is to check the certificate’s current validity state by using the Online Certificate Status Protocol (OCSP), where the client directly asks the CA for the current certificate state. The validation of a certification should include one of these forms of revocation checking.

To know more about the use of X.509 certificates in Internet scenarios, including the certification path construction and validation details, we recommend the set of RFCs issued by the PKIX IETF working group, namely RFC 5280.

Creating Test Keys and Certificates

When you are developing clients and servers that use the TLS protocol, it is useful to have a set of keys and certificates for testing purposes. In the following paragraphs we show how to create this infrastructure using a set of Windows command-line tools. However, before we start, there is something we should emphasize: never use these keys and certificates in a production scenario; they are only for testing purposes.

The first step is to create a root certification authority, using the makecert tool:[14]

makecert -r -n "CN=Demo Certification Authority;O=Web API Book" ^
 -sv webapibook-ca.pvk ^
 -len 2048 -e 01/01/2020 -cy authority webapibook-ca.cer

The -r option instructs makecert to generate a self-signed certificate—that is, a certificate signed with the private key associated with the contained public key. This certificate will be used as the certification path root.

The certification authority will have the X.500 name CN=Demo Certification Authority;O=Web API Book, where CN and O are name attributes: CN stands for common name and O stands for organization. The private key will be stored in the webapibook-ca.pvk file, encrypted by a key derived from a given password. This private key will be used to sign each issued certificate.

The second step is to generate an asymmetric key pair and certificate for a fictional server named We also accomplish this via the makecert tool:

makecert.exe -iv webapibook-ca.pvk -ic webapibook-ca.cer -n "" ^
 -sv example.pvk -len 2048 -e 01/01/2020 ^
 -sky exchange example.cer -eku

pvk2pfx.exe -pvk example.pvk -spc example.cer -pfx example.pfx

This certificate is issued by the previously generated CA, so makecert requires both the CA certificate (for naming) and the CA private key (for signing). The -eku option adds an enhanced key usage extension to the generated certificate, indicating that it can be used with TLS server authentication.

The .pvk file contains the server’s private key and the .cer file contains its certificate, including the public key. The last line in the previous example uses the pvk2pfx tool to encapsulate both the private key and the certificate into a single .pfx (personal information exchange) file. This last file uses the PKCS#12 interoperability format for exchanging cryptographic material, such as private keys and certificates, and is the most commonly used format in Windows for this purpose.

The final step is to generate client-side certificates for the two famous cryptography fictional characters, Alice and Bob:

makecert.exe -iv webapibook-ca.pvk -ic webapibook-ca.cer ^
   -n "CN=Alice;O=Web API book fictional characters" ^
   -sv alice.pvk -len 2048 -e 01/01/2020 -sky exchange ^
   alice.cer -eku
pvk2pfx.exe -pvk alice.pvk -spc alice.cer -pfx alice.pfx

makecert.exe -iv webapibook-ca.pvk -ic webapibook-ca.cer ^
   -n "CN=Bob;O=Web API book fictional characters" ^
   -pe -sv bob.pvk -len 2048 -e 01/01/2020 -sky exchange ^
   bob.cer -eku
pvk2pfx.exe -pvk bob.pvk -spc bob.cer -pfx bob.pfx

This process is similar to the one we used to generate the host cryptographic material, with only one exception: the generated certificates will have the extension, which indicates that they can be used for TLS client-side authentication.

After completing this process, we should have generated two types of files. The webapibook-ca.cer file contains the CA certificate and should be used by every party that chooses to trust the certifications performed by this entity. On Windows, this trust decision results in adding the certificate to the Trusted Root Certificate Authorities user’s store. The .pfx files contain both certificates and private keys for each of the parties (, Alice and Bob) and should be installed in the Personal certificate store of each party.

[14] Available in the .NET Framework tools.

Get Designing Evolvable Web APIs with ASP.NET now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.