SecurityEngineering/x509Certs
A Web PKI x509 Certificate Primer
X.509 (in this document referred as x509) is an ITU standard to describe certificates. Three versions of the x509 standard have been defined for web-pki. In this document we will be referring to the current standard in use for web pki: x509 v3, which is described in detail in rfc 5280.
In general x509 certificates bind a signature to a validity period, a public key, a subject, an issuer, and a set of extensions. The extensions define extra properties of the certificate such as extra attributes of the certificate or constraints on the use of the certificate. In order for a certificate to be valid a three requirements are needed:
- There is a verification path from the site certificate to a trusted certificate of the user agent (ie if you follow the issuer path you will end on a self-signed certificate that is considered trusted by the browser).
- The attributes of the certificates in the verification path have valid parameters for that verification (for example the validity period of all the certificates are valid for the time the verification is being done)
- Revocation checks are considered OK for that particular validation.
One issue that is not commonly known is that the x509 trust graph is not a forest (a bunch of trees where each root is a trusted root) but a cyclic graph, where the same key/issuer can be a root or an intermediate for another root in the browsers key store (when roots create intermediates for each other is sometimes called cross-signing).
Extensions
While RFC 5280 defines 16 extensions for webpki in this document we will be describing the six extensions we considered critical for understanding. Certificates can have other extensions not described on RFC 5280, but that is our of the scope of this document. Extensions can be marked as critical or non-critical, conforming certificate verification libraries should stop processing verification when encountering a critical extension that they do not understand ( and should continue prococessing if the extension is marked as non-critical) mozila::pkix has this behavior.
Subject Alternate Name
This extension defines what other names (such as DNS names) are valid for this certificate. This is allows for a certificate to be used for more than one fqdn, for example you can have a certifcate to be balid for both a.example.com and b.example.com
Basic Constraints
This allows certificates to be asserted as CA certificates (it is mandatory for CA certificates). I can also be used to express the maximum depth of the trust patch from this particular CA.
Key Usage
This extension is used to constrain the purpose for the key in the certificate. More than one key usage can be asserted. Examples of key usages are: digitalSginature, keyEncipherement, dataEncipherement, keyCertSig, crlSign. For CA certificates the keyCertSign bit MUST be asserted.
Extended Key Usages
This is annother bitfield to contrain the usages of the key of the certificate. Its is directed mostly at what type of application the certificate what issued for. Examples of extended key usages are: serverAuth, clientAutn and OCSPSigning. For end-entity certificates for PKI this extension is required to exist witht he serverAuth bit asserted.
Name Constraints
This is an extension exclusive for CA and indicates limits on the name space for its children. This is one of the most powerful extensions for business to have as they help limit risk imposed by losing the private key of the CA.
Authority Information Access
This extension primary use to to describe the OCSP location for revocation checking. It is mandatory for certificates that chain up to a root in the Mozilla CA program.
Self Signed Certs
These are the steps to generate a certificate for www.example.com. Replace this value for the actual server name in the steps below.
1. Generate key:
- "openssl genpkey -algorithm RSA -out key.pem -pkeyopt rsa_keygen_bits: 2048"
- A 2048 is considered secure for the next 4 years.
2. Generate csr
- "openssl req -new -key key.pem -days 1096 -extensions v3_ca -batch -out example.csr - utf8 -subj '/CN=www.example.com'
- Make a new Certificate Signing Request (CSR) that will be valid for 3 years.
3. Write extensions file (make a new file with name openssl.ss.cnf with the following contents)
- basicConstraints = CA:FALSE
- subjectAltName =DNS:www.example.com
- extendedKeyUsage =serverAuth
4. Self-sign csr (using SHA256) and append the extensions described in the file
- "openssl x509 -req -sha256 -days 3650 -in example.csr -signkey key.pem -set-serial $ANY_INTEGER -extfile openssl.ss.cnf -out example.pem"
You can now use example.pem as your certfile
Running your Own CA
This isa little more complicated. It has requires building 3 certificates: a long term root cert, a medium tem intermediate and a short term end-entity cert. The reason for this is that allows us to have a relatively simple long term root to be distributed to clients and some flexibility on the intermediate so that we can change parameters if security research indicates so.
Generate your CA Root
We assume you are the domain owner of *.example.com and *.example.net. Update the values below to match your domains. We also assume that this computer is NOT connected to the internet.
1. Generate key
- "openssl genpkey -algorithm RSA -out rootkey.pem -pkeyopt rsa_keygen_bits: 4096"
- A 4096 is considered secure for the next 15 years.
2. Generate csr
- "openssl req -new -key rootkey.pem -days 5480 -extensions v3_ca -batch -out root.csr - utf8 -subj '/C=US/O=Orgname/OU=SomeInternalName'
- Make a new Certificate Signing Request (CSR) that will be valid for 15 years.
3. Write extensions File (openssl.root.cnf)
- basicConstraints = critical, CA:TRUE
- keyUsage = keyCertSign, cRLSign
- subjectKeyIdentifier = hash
- nameConstraints = permitted;DNS:example.com,permitted;DNS:example.net
4. Self-sign csr (using SHA256) and append the extensions described in the file
- "openssl x509 -req -sha256 -days 3650 -in root.csr -signkey rootkey.pem -set-serial $ANY_SMALL_INTEGER -extfile openssl.root.cnf -out root.pem"
Now you have ca pem file with its associated key.
Generate your Intermediate cert
This intermediate is designed for 8 years.
1. Generate key
"openssl genpkey -algorithm RSA -out r=intkey.pem -pkeyopt rsa_keygen_bits: 3072"
- A 3072 bit key is considered secure for the next 8 years.
2. Generate csr
- "openssl req -new -key intkey.pem -days 2922 -extensions v3_ca -batch -out int.csr - utf8 -subj '/C=US/O=Orgname/OU=SomeInternalName2'
- Make a new Certificate Signing Request (CSR) that will be valid for 8 years.
3. Write extensions File (openssl.int.cnf)
- basicConstraints = critical, CA:TRUE
- authorityKeyIdentifier = keyid, issuer
- subjectKeyIdentifier = hash
- keyUsage = keyCertSign, cRLSign
- extendedKeyUsage =serverAuth
- authorityInfoAccess = OCSP;URI:http://ocsp.example.com:8888/
4. Sign the intemediate csr with the root key and the intermediate extensions
- "openssl x509 -req -sha256 -days 2922 -in int.csr -CAkey rootkey.pem -CA root.pem -set_serial $SOME_LARGE_INTEGER -out int.pem -extfile openssl.int.cnf"
Generate the end entity certificate
Assuming this is for www.example.com
1. Generate key
- "openssl genpkey -algorithm RSA -out eekey.pem -pkeyopt rsa_keygen_bits: 2048"
- A 2048 is considered secure for the next 4 years.
2. Generate csr
- "openssl req -new -key key.pem -days 1096 -extensions v3_ca -batch -out example.csr - utf8 -subj '/CN=www.example.com'
- Make a new Certificate Signing Request (CSR) that will be valid for 3 years.
3. Write extensions file (make a new file with name openssl.ss.cnf with the following contents)
- basicConstraints = CA:FALSE
- subjectAltName =DNS:www.example.com
- extendedKeyUsage =serverAuth
- authorityInfoAccess = OCSP;URI:http://ocsp.example.com:80/
4. Intermediate sings the csr (using SHA256) and appends the extensions described in the file
- "openssl x509 -req -sha256 -days 1096 -in example.csr -CAkey intkey.pem -CA int.pem -set_serial $SOME_LARGE_INTEGER -out www.example.com.pem -extfile openssl.int.cnf"
Security Notes
There are several organizations that try to find recommendations regarding the security parameters for key/hash sizes given current computational power. For the end date of our root cert (2017). These are the recomendations of bit sizes (from http://www.keylength.com/ ) by:
Asymmetric | ECC(Key) | Hash | |
---|---|---|---|
Linestra(2004) | 1902 | 172 | 172 |
Ecrypt 2012 | 2432 | 224 | 224 |
NIST 2012 | 2048 | 224 | 224 |
ANSSI 2010 | 4096 | 200 | 256 |
RFC 3766 | 2358 | 200 | --- |
BSI | 1976 | 256 | 256 |
In other words, SHA1 is now deprecated for new uses. We should use at least 3072 key sizes and at least a 256 ECC curve. Thus the recommendation here for the root to be 4096 if using RSA and p384 for the root key. (p384 also chosen for compatibility as most SSL/TLS implementations support this part of suite B).