X.509
Public key infrastructure (PKI, the trust model) is specified by ITU X.509 (the specification), and these two terms can be used interchangeably.
PKI serves the same purpose as PGP Web of Trust: to securely bind a crypto public key to a subject, or in Wikipedia's terms, to "to establish the authenticity of the binding between a public key and its owner." Both PKI and Web of Trust are built upon asymmetric cryptography.
Instead of being a decentralized protocol like Web of Trust, PKI is centralized such that users can trust a single root certification authority ("trust annchor") and therefore automatically trusting the tree of all certificates issued by that authority.
PKI is has tree-like architecture. It begins with a certification authority (CA), which is usually self-signed, issuing a list of certificates, likely other intermediate CAs, and these intermediate CAs further issue certificates, likely leaf certificates.
The CA is responsible for validating the authenticity of the public key and its owner. Trusting a CA means trusting its responsibilitie, and thus, trusting all certificates issued by the CA are authentic (the public keys are indeed belong to who they claim to be).
When the relying party validates a certificate, it will check the certificate itself (e.g., within validity period) and check that against its issuer (higher in the tree), and the issuer of the issuer, and so on, until it encounters an error or reaches a CA certificate that is hard-coded in its trusted CA store.
Certificate
A X.509 certificate is an envelope of a cryptography public key + lots of attributes, like the subject name and issuer.
The cryptography public key itself has nothnig about expiry, owner, usages, etc. A X.509 certificates combines a public key with a name and other required properties (like expiry time, signature, extensions). All certificates at least have the following attribtues:
- Version: X.509 certificate version, V1, V2, or V3. V3 is most commonly used today, and V2 is never widely used.
- Serial Number: A CA-defined number that uniquely identifies the certificate within the CA.
- Issuer: Subject name of the CA.
- Subject: Subject name of the certificate.
- Validity: Not before and not after.
- Signature: The above parts signed by the CA's private key.
Certificates can be safely published to the Internet, and private keys are not. X.509 defines nothing about private key format and storage.
A certificate is only valid if it is signed by a trusted certification authority.
Certification Authority (CA)
CA validates the binding between a subject name and its public key and issues a certificate to the subject ("certifying" the public key is authentic).
This is implemented using digital signatures. Once the trust relationship is validated (through some mechanisms, like HTTP challenge. X.509 does not define these mechanisms):
- The CA crafts an certificate that has the subject's name public key, and other necessary attributes like the subject of the CA itself, expiry time, serial number, and restrictions.
- Sign that certificate with the CA private key, put the signature bytes into a location in the final certificate (that part is not considered during calculating the signature, obviously), and a valid certificate is produced.
Subjects have no control over certificates at all. The only thing they can do is to generate a private key and request a certificate from a CA. The CA decides all attributes of the produced certificates, and this may include necessary restrictions. The CA may or may not take client's requests into consideration: for example, the client may request for a longer validity period, but it is up to the CA to set the validity period. Because the final certificate is digitally-signed by the CA using its private key, it is not tamperable.
X.509 does not define how the subject requests certificates from the CA (i.e., the protocol), and lots of protocols exist (ACME is one of them). However, there are some standards on defining the format of the request the client sends to the CA while trying to get a certificate. See below.
Relying Party and Certification Validation
Relying party is the client that needs to validate a certificate, using a CA. This is basically checking the signature of the presented certificate against its issuer (CA)'s public key, which is previously known.
When a certificate is presented from a peer, the following procedure happens:
- Validate the certificate properties, like validity period, extensions, etc.
- Find the issuer certificate. The subject of the issuer and signature is in the certificate itself, and the relying party has to lookup the issuer on its own. If the issuer certificate is included in the certificate bundle (a full- chain certificate), it could be used. If the issuer is in the local trusted CA store, it could be used and trusted. Otherwise, it will fail.
- Validate the signature and subject against the issuer.
- Validate the issuer certificate and go back to 1. If the issuer certificate is not explicitly trusted locally (i.e., it is not in the local root CA store but is presented by the peer, it should not be trusted, and it should be validated as well, using the same procedure, until a trusted CA is found.)
Extensions
Because certificates are completely defined by the CA, it may apply additional restrictions or add extra information to the certificates, through the extension mechanism.
X.509 V3 certificates (almost all certificates today) may also contain optional extensions that restrict the trust of the certificates or provide additional info.
For example, an extension may define that the certificate shall only be trusted
with domain names ending with .DN42
. This extension is called
"basicConstraints".
For example, another extension may provide a URL to CA policies to certificates.
For another example, the CA may put the URL to itself to issued certificates, so relying parties can easily lookup the CA (recall that the relying party has to validate each level of the tree, from bottom to top, when validating the certificate). This extension is called "authorityInfomationAccess".
In implementation, the extension list is encoded as a map in the certificate. The key is an OID (object ID) that uniquely represents the extension ID, and the value is a byte-array encoding that extension.
Extensions may be marked as critical by the CA. Because not all extensions are supported by all clients (even a lot of proprietary extensions exist), the interpretation of the extensions varies. Marking an extension critical tells relying parties to reject that certificate if the extension is unknown. Not marking it as critical (which is default), tells the relying party to silently ignore the extension if it is unsupported. This is a trade-off between security and compatibility. Some extensions, like basicConstraints, contain important security-sensitive values (like the basicConstraints extension defines whether a certificate can be used as a CA or not: in other words, if it is false, then no certificates that issued by this certificate shall be trusted). Therefore, basicConstraints is always marked as critical.
Note that although an extension is marked as critical, it does nothing when the relying party only partially parses the extension, and the behaviour is implementaion-defined.
Validity, Revocation, and Certificate Revocation List (CRL)
Because all certificates have validity periods, the CA only needs to ensure that the authentic relationship between public key and subject name holds within the validity period. The CA needs to re-validate the trust relationship to issue a renewed certificate.
If there are unexpected circumstances like key compromise, the CA can revoke issued certificates before their expiry by publishing a CRL.
Certificate Revocation List (CRL) is a list signed by the CA that lists the serial numbers of issued certificates to tell relying parties that they are revoked before expiry.
Because X.509 is a tree-like structure, it is impossible for the CA to notify relying parties directly for revocation. Therefore, the CA periodically publishes CRLs, listing all revoked serial numbers, and clients just need to check it upon validation and reject certificates if needed.
CRL entries contain three fields: serial number, revocation reason, and revocation date. The whole CRL is signed by the CA using the same mechanism of issuing certificates. Delta CRL is also supported to revoke large amount of certificates.
Other mechanisms for early revocation also exist, like OSCP.
The CA usually include the URL to its CRL inside an extension in the issued certificates, so relying parties can automatically find the CRLs. This extension is called "crlDistributionPoints", or CDP.
Multi-tier PKI Hierarchy
In the most simplest form, there is a single root CA, and it issues a list of certificates. Relying parties hard-code the root CA, and they can easily validate presented certificates.
However, this mechanism is neither scalable nor secure.
- The root CA is hard-coded, so it is hard to rotate them. Imagine having thousands of relying parties in a network, and the root CA expires or even worse, is compromised. It would be a nighmare to replace all of them.
- Frequently use the root CA to sign everything increases the attack surface. Usually, the CA runs an online program that automatically receives client signing requests, validates, and issues certificates. Having the root CA to do so would greatly enlarge the attack surface. It is a good practice to have the root CA offline.
Therefore, people have multi-tier PKI. That is, an offline root CA issues an intermediate CA, which is online and issues leaf certificates. Relying parties only hard-code a long-living root CA, and the intermediate CA can be easily rotated.
Root CA is a self-signed, highly-secure, and long-living CA. It is at the top of the PKI hierarchy, with issuer equals to itself. It only issues and revokes intermediate CAs.
Intermediate CA is signed by the root CA, and it handles the signing of leaf certificates. It is usually shorter in validity, and it is online.
Certification Signing Request (CSR)
Note that this is not part of the X.509 specification.
Although X.509 does not define a way for requesting a certificate from the CA, there are some other specifications defining the format the the client encodes its subject and public key to be sent to the CA.
Certification Signing Request (CSR), defined in PKCS#10, is a widely-used format for encoding the subject, public key, and other requested properties to be sent to the CA for signing.
The CSR still needs to be signed by the subject holder, and this mechanism works exactly same as the CA signing a certificate or CRL. Signing proves that the entity presenting the CSR indeed holds the private key of the requested public key. The signature must match the presented public key in the CRL.
It doesn't control what the CA signs. It is up to the CA that decides whether to use the requested attributes. The only thing the CA has to use is the public key of the CSR.
It doesn't define how to send the signed CSR to the CA, nor does it define how to handle CA challenges or errors.
Certificate Request Protocols
Note that this is not part of the X.509 specification.
There are some widely-used Internet protocols that defines how to send CSR to CA and handle challenges:
- ACME: The widely-used protocol for web. Does HTTP, TLS, and DNS challenges.
- SCEP: A simple protocol for requesting certificates, designed by Cisco, frequently used in network devices.
- MS-WCCE: The proprietary protocol used by ADCS (Microsoft's online CA software) that accepts certificates from domain-joined Windows devices. It is based-on DCOM+, protected by Kerberos.
TLS
Note that this it not part of the X.509 specification.
Main article: TLS
TLS is a widely-used L5 protocol for establishing a mutually-trusted TCP tunnel upon a untrusted network.
The server presents a X.509 certificate in the ServerHello message, and the client (relying party) validates it.
Similar thing happens when the client presents a certificate in the ClientHello message.
Then, they exchange a symmetric encryption key for the data exchange. The key exchange is based on asymmetric encryption.
Root CA Requirements, CAB Forum, Web CA
Note that this it not part of the X.509 specification.
X.509 only defines some basic rules for the root CA, like basicConstraints must have CA equals to TRUE.
The CA / Browser forum (CAB) has a specification that defines the must and must not's for root CAs. For example, the root CA must not have anything except for commonName and country in its subject.
Please read CA-Browser-Forum-BR-v2.0.0.pdf section 7.1.2.1 for allowed root CA configurations.
Invalid root CA configurations are perfectly fine with X.509 itself and lots of tools (like OpenSSL), but browsers may not support or trust them.
Cross-sign
TODO
Common Extensions
basicConstraints: Define whether the certificate is a CA or not, and optional pathlen restrictions and name restrictions. Critical.
keyUsage: Basic key usage like digitalSignature and cRLSign.
extendedKeyUsage: Like serverAuth.
crlDistributionPoints: URLs to the CRL of the issuer CA.
authorityInformationAccess: URL to the issuer CA.
subjectAlternativeName: Domain, DNS, etc.
It is useful to use openssl x509 -text -noout -in /path/to/cert
to check an
existing certificate and read through X.509 specifications for the extension in
interest.
ASN.1, Encoding, BER, DER, and PEM
Note that this it not part of the X.509 specification.
Main article: ASN.1
In X.509 spec, all data structures (like a certificate or a CRL) are defined in the Abstract Syntax Notation 1 (ASN.1) syntax.
ASN.1 is a way of defining structures, including their name, fields, types, and order, but it does not define a serialization or deserialization method. Take it as Protobuf without the binary part. It is worth noting that ASN.1 is not limited to X.509 at all. Any application can use ASN.1 to represent data, but it is not popular today.
ASN.1 has lots of built-in data types, like BOOL
, INTEGER
, OCTET STRING
,
BIT STRING
, UTCTime
, GeneralizedTime
, NULL
, OID
, and so on. We can use
them to define custom SEQUENCE
(struct), SEQUENCE OF
(list), and SET OF
.
Complex types also exist, for example: ONE OF
and ENUMERATION
.
ASN.1 have various encoding rules, and the one most commonly used today along X.509 is Distinguished Encoding Rule (DER). They are all binary encoding rules. ASN.1 can also be encoded into / decoded from XML.
DER is a strict subset of Basic Encoding Rule (BER). BER allows for ambiguities,
like infinite SEQUENCE
length, multiple BOOL
true encodings, optional
GeneralizedTime
timezones, etc. DER eliminates these ambiguities and only
allowes a single representation of a ASN.1 structure.
In X.509, extension values are represented as OCTET STRING
, which is just a
byte array encoded in hex string. The byte array is actually the DER-encoded
value of the extension. The format varies, but it should be DER-encoded.
In X.509 and PKCS#10, the signature of certificate, CRL, and CSR are actually the signature to the DER-encoded value except for the signature field.
Because DER and BER are binary formats, they are hard for humans to read and
copy. Therefore, a popular (but poorly-defined) format is PEM. PEM is as simple
as the base64 encoding of an arbitrary binary (each line is at max 64 chars
long) with a header and footer (-----BEGIN XXX-----
-----END XXX-----
).
PEM originally stands for "Privacy-enhanced mail". It is never used in anything
related to privacy and mail, but it is constantly (mis)used in the field of PKI.
The name inside header and footer is also poorly standarized. CSRs sometime have
BEGIN NEW CERTIFICATION REQUEST
, and sometimes it is just
BEGIN CERTIFICATION REQUEST
.
Learn more
- smallstep.com/blog/everything-pki: A very beginner-friendly article describing PKI. It doesn't tell anything about OIDs, AIA, and Key Usages stuff.
- letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der: Let's Encrypt's introduction on ASN.1 and DER.
- lapo.it/asn1js: Online tool for decoding ASN.1 DER structure.
- OpenSSL: Implements everything inside X.509. Its
-text
option is especially useful. - www.itu.int/rec/T-REC-X.509: X.509 spec.
- www.itu.int/rec/T-REC-X.680: X.680 spec.
- www.itu.int/rec/T-REC-X.690: X.690 spec.
- www.pkiglobe.org/pkcs10.html: PKCS#10.
Created: November 5, 2023