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:
Public-key cryptography is also called asymmetric cryptography since its mechanisms use two keys with different confidentiality requirements and different purposes:
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 https://webapibook.blob.core.windows.net/.
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 certificate also contains a signature produced by its issuer, so that it can be stored and distributed via unsafe channels.
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 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:
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.
In the figure:
server-keyand also the legal owner of the
server-keyto encrypt a secret seed that can be decrypted only by the example.net 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.
Figure G-3 shows this extended model, where:
server-keyand also the legal owner of the example.net 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 *.blob.core.windows.net 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.
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:
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.
One way of accomplishing this is by using certificate revocation lists (CRL) containing invalidated (revoked) certificates. For instance, in the previous example the *.blob.core.windows.net certificate contains a CRL distribution point field with a CRL URI (http://mscrl.microsoft.com/pki/mscorp/crl/Microsoft%20Secure%20Server%20Authority(8).crl). 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.
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 -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
-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
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 www.example.net.
We also accomplish this via the
makecert.exe -iv webapibook-ca.pvk -ic webapibook-ca.cer -n "CN=www.example.net" ^ -sv example.pvk -len 2048 -e 01/01/2020 ^ -sky exchange example.cer -eku 184.108.40.206.220.127.116.11.1 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).
-eku 18.104.22.168.22.214.171.124.1 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 126.96.36.199.188.8.131.52.2 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 184.108.40.206.220.127.116.11.2 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
18.104.22.168.22.214.171.124.2 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 (www.example.net, Alice and Bob) and should be installed in the Personal certificate store of each party.
 Available in the .NET Framework tools.