Certificate Authorities (CAs) Demystified

Kjell Wooding | 2003-01-11

There seems to be a great deal of unnecessary mystery about SSL, IPsec, and public-key certificates in general. This mystery often leads people to self-sign their entire public key infrastructure (or simply use pre-shared keys), without realizing what they are doing, or why they are doing it. This document aims to clear up that mystery.

This document talks about OpenSSL, as it is one of the most popular toolsets for generating and managing keys, and (as usual) assumes everyone is running OpenBSD.

Contents

Terminology and Concepts

In order to talk about Certificate Authorities (CAs), and Public-Key Infrastructures (PKIs), we will require some terminology:

Public Key
The public component of an RSA key pair. This may be extracted from an RSA private key, such as those generated using the openssl genrsa command. These keys are usually stored in PEM format.
Private Key
The private component of an RSA key pair. These are generated using the openssl genrsa command, and contain all the information required to generate an associated public key. These keys are usually stored in PEM format.
PEM format

The most common file format for RSA key files. Ths format consists of a base64-encoded ASN.1 DER-encoded format offset by

-----BEGIN RSA PRIVATE KEY-----
-----END RSA PRIVATE KEY-----

lines.

x509 Certificate
Essentially, a signed public key.
Certificate Authority (CA)
A trusted entity responsible for signing public keys (and hence, creating certificates).
Public Key Infrastructure (PKI)
A hierarchy of certificate authorities. This can range in complexity from a single, central certificate authority, to the highly decentralized PGP web-of-trust model.
Distinguished Name (DN)
A formal notation describing the holder of a particular x509 certificate.

File Locations

For this document, we assume keys are stored in their default locations on an OpenBSD machine; i.e.

/etc/ssl
SSL public keys
/etc/ssl/private
SSL private keys

In practice, the public key directory should be world readable, and the private key directory should be readable only by root.

Generating an RSA key pair

The following generates an RSA private key. This key also includes sufficient information to generate the public key, if desired.

  # openssl genrsa -out /etc/ssl/private/host.key 1024

To generate an encrypted key (protected by a passphrase):

  # openssl genrsa -3des -out /etc/ssl/private/host.key 1024

Once generated, this key may be manipulated using the openssl rsa command. There are several possible reasons to manipulate this key:

For example, to remove a passphrase from a host key:

  # openssl rsa -in host.key -out host-nopw.pem

To convert a PEM-format key to a DER-format one:

  # openssl rsa -in host.key -outform DER -out host.der

RSA Private key file formats

There are currently 3 formats in use:

PEM (default)
Ths format consists of a base64-encoded DER format with additional header and footer lines.
DER
An ASN.1 DER-encoded format compatible with the PKCS#1 RSAPrivateKey or SubjectPublicKeyInfo format.
NET
This is a format compatible with older Netscape and IIS servers. As it uses unsalted ARC4 for its encryption, it is not particularly secure and should be avoided if possible.

Self-signed certificates

A self-signed certificate is a public key that has been signed by its own private key. Why bother, you ask? Public key infrastructures expect that someone is certifying the authenticity of a public key. If there is no-one else available, a certificate must be self-signed.

Self-signing is useful for generating test certificates for a variety of applications. Production certificates, however, should always be signed using some form of certificate authority - either a commercial entity (such as thawte), or your own personal (or corporate) CA.

Self-signing is accomplished by using the -signkey option of openssl x509. This process takes as input:

And produces as output:

Example:

  # openssl x509 -req -days 365 -in /etc/ssl/private/host.csr \
      -signkey /etc/ssl/private/host.key -out /etc/ssl/host.crt

Certificate Signing Requests (CSRs)

Once the RSA key pair has been generated, a signing request must be created. This request is then submitted to the CA for signing. These requests are created and processed in PKCS#10 format.

  # openssl req -new -key /etc/ssl/private/host.key \
      -out /etc/ssl/private/host.csr

In fact, the RSA key generation and CSR generation can be combined using the -newkey option of openssl req:

  # openssl req -newkey rsa:1024 -keyout /etc/ssl/private/host.key \
      -out /etc/ssl/private/host.csr

Certificate Authority Creation

If we are not using a third-party, CA we must create our own CA infrastructure. This essentially consists of generating a self-signed key pair to serve as the CA's signing key. Because compromise of the CA means compromise of the entire public-key infrastructure, it is important to ensure the CA key both of sufficient bit length, and is protected by a passphrase.

  # openssl req -newkey rsa:2048 -keyout /etc/ssl/private/ca.key \
     -out /etc/ssl/private/ca.csr
  # openssl x509 -req -days 365 -in /etc/ssl/private/ca.csr \
     -signkey /etc/ssl/private/ca.key -out /etc/ssl/ca.crt
  # ln -s /etc/ssl/ca.crt /etc/isakmpd/ca/ca.crt 

Certificate Authority Signatures

At this point, the CA will be used to sign all relevant host (public) keys. This is done using the openssl x509 command.

  # openssl x509 -req -days 365 -CAcreateserial \
     -CA /etc/ssl/ca.crt -CAkey /etc/ssl/private/ca.key \
     -in /etc/ssl/private/host.csr -out /etc/ssl/host.crt
  # chmod 600 /etc/ssl/private/*

Once the keys are signed (and if they are to be used with isakmpd), they must have a subjectAltName extension field added to them for each of the identities that will be bound to the certificate. This is typically done with the certpatch(8) tool, though it may also be done with a clever application of environment variables in the openssl.cnf file (see the Extended Key Usage example, below).

The following example adds a fully qualified domain name identity to an existing certificate. Other identification types are listed below:

  # certpatch -k /etc/ssl/private/ca.key -t FQDN -i "your_FQDN" \
     /etc/ssl/host.crt /etc/ssl/host.crt
  # ln -s /etc/ssl/private/host.key /etc/isakmpd/private/host.key
  # ln -s /etc/ssl/host.crt /etc/isakmpd/certs/host.crt

Note that trusted public keys (namely, those signed at this CA by the process above) can be used directly by isakmpd if placed in the following locations (based on the certificate identification type):

Certificate Identification Types

There are three main identification types for certificates, as defined in RFC 2407.

IP
This may be either an IPv4 dotted-quad address, or an IPv6 address.
FQDN
A Fully Qualified Domain Name. Note that use of this certificate identification type can make the infrastructure vulnerable to DNS-based attacks (if the attacker gains posession of the FQDN-identified keypair
User FQDN (UFQDN)
This format represents a fully-qualified username string. This identification type is useful when a user may not be originating from a fixed IP address. e.g. luser@example.com, or luser@laptop04.example.com.

Note that, for the purposes of isakmpd (under OpenBSD, at least), both FQDN and UFQDN are handled as strings. No verification (name resolution) of the data is performed.

Exporting Certificates for Other Systems

For some tasks, it is useful to be able to export certificates to another machine. Typically, certificates are exported in PKCS#12 format. The following command will perform the export:

# openssl pkcs12 -export -in /etc/ssl/host.crt -out host.p12 \
        -certfile  /etc/ssl/ca.crt -inkey /etc/ssl/private/host.key

IPSec Policy and Keynote

IPsec policy (under OpenBSD, anyway) is enforced by the Keynote trust management system. This is essentially a language used for describing whether a given IPsec connection attempt is legitimate or not. Typically, this policy is located in /etc/isakmpd/isakmpd.policy.

One common policy states the following:

To configure this type of policy, it is essential that the correct distuguished name be extracted from the CA certificate. This may be accomplished by the following:

  # openssl x509 -in /etc/ssl/ca.crt -noout -subject | \
     sed -e 's@^subject= @@g'

Once this DN has been extracted, the isakmpd.policy file may be constructed:

Keynote-version: 2
Authorizer: "POLICY"
Licensees: "DN:/C=CA/ST=Alberta/L=Calgary/O=My company/CN=ca@mycompany.com"
Conditions: app_domain == "IPsec policy" &&
            esp_present == "yes" &&
            esp_enc_alg != "null" -> "true";

Other references include:

Extended Key Usage (EKU) fields

EKU fields are used in X.509 certificates to indicate what applications a particular certificate may be used for. They are represented as OIDs, dotted-decimal strings of 28-bit integers. An OID is a totally general, but uniquely allocated hierarchial identifier used in a variety of standards. A master repository of OIDs is available at http://oid.elibel.tm.fr/.

For many crypto applications, EKU fields are not used at all. Occasionally, such as when interoperating between different vendors' products (e.g. Microsoft, using RADIUS authentication), it may be necessary to add one or more extension to a particular certificate. Some common EKU OIDs are:

1.3.6.1.5.5.7.3.1 (serverAuth)
SSL/TLS Web Server Certificate
1.3.6.1.5.5.7.3.2 (clientAuth)
SSL/TLS Web Client Certificate
1.3.6.1.5.5.7.3.3 (codeSigning)
Code Signing
1.3.6.1.5.5.7.3.4 (emailProtection)
Email Protection
1.3.6.1.5.5.7.3.8 (timeStamping)
Time Stamping
1.3.6.1.4.1.311.2.1.21 (msCodeInd)
Microsoft Individual Code Signing
1.3.6.1.4.1.311.2.1.22 (msCodeCom)
Microsoft Commercial Code Signing
1.3.6.1.4.1.311.10.3.1 (msCTLSign)
Microsoft Trust List Signing
1.3.6.1.4.1.311.10.3.3 (msSGC)
Microsoft Server Gated Crypto (strong crypto export approved)
1.3.6.1.4.1.311.10.3.4 (msEFS)
Microsoft Encrypted File System
2.16.840.1.113730.4.1 (nsSGC)
Netscape Server Gated Crypto (strong crypto export approved)

EKUs are added when a key is signed. To add extensions, they must first be saved to a configuration file; i.e.

  [ ext_client ]
  # OID:1.3.6.1.5.5.7.3.2 = clientAuth to OpenSSL
  extendedKeyUsage=clientAuth
  subjectAltName=critical,email:$ENV::CN

If the above is saved to a file called /etc/ssl/ext.cnf, the following invocation will sign a certificate, adding both the SSL Client Certificate EKU and the subjectAltName extension used by isakmpd.

  # CN=user@example.com openssl x509 -req -days 365 \
         -in /etc/isakmpd/private/user@example.com.csr \
         -CA /etc/ssl/ca.crt \
         -CAkey /etc/ssl/private/ca.key -CAcreateserial \
	 -extfile /etc/ssl/ext.cnf \
	 -extensions ext_client \
         -out /etc/isakmpd/certs/user@example.com.crt

The most recent list of common extensions can likely be extracted from the OpenSSL source code. OIDs associated with Microsoft Cryptography are available from Microsoft, or via a local snapshot.

Useful Tools

More Information

pintday.org » Fresh every Tuesday.