What is an X.509 certificate? Fields, format and uses
An X.509 certificate is a data structure that binds a public key to a subject, such as a domain name, and a certificate authority signs it to assert that binding [1]. The format comes from ITU-T Recommendation X.509 [2], and RFC 5280 profiles it for the internet [1]. TLS requires X.509 version 3 for the certificates both sides send, unless the two ends negotiate another type (RFC 8446 §4.4.2.2, §4.4.2.3) [3]. So an SSL/TLS certificate is an X.509 certificate: "X.509" names the format, "SSL certificate" names the use. This SSL and TLS glossary entry covers the fields, the extensions TLS reads and Go's x509: errors.
- Current version
- version 3, stored as the value 2 [1]
- Encoding
- ASN.1, signed as DER [1]; files hold DER or PEM text
- Structure
- to-be-signed data, the signature algorithm, the signature value [1]
- Read with
openssl x509 -in cert.pem -noout -text[7]
What an X.509 certificate contains
An X.509 certificate is one ASN.1 sequence of three parts: the to-be-signed certificate (tbsCertificate), the algorithm the issuer signed it with, and the signature value [1]. openssl asn1parse decodes the DER of this page's test certificate and shows them:
$ openssl asn1parse -in cert.pem -i
0:d=0 hl=4 l= 827 cons: SEQUENCE
4:d=1 hl=4 l= 736 cons: SEQUENCE
744:d=1 hl=2 l= 10 cons: SEQUENCE
756:d=1 hl=2 l= 73 prim: BIT STRINGThe 736-byte sequence is the to-be-signed part, with these fields [1]:
| Field | What it holds |
|---|---|
| Version | 3 (value 2) whenever extensions are present, §4.1.2.1 |
| Serial number | a positive integer, unique among the certificates one CA issues, §4.1.2.2 |
| Signature | the signature algorithm; must match the outer one, §4.1.1.2 |
| Issuer | the name of the authority that signed it, §4.1.2.4 |
| Validity | notBefore and notAfter: the dates between which it may be used (§6.1.3) and the CA keeps status information about it (§4.1.2.5) |
| Subject | the name of the entity that holds the public key, §4.1.2.6 |
| Subject public key info | the public key and its algorithm, such as RSA 2048 or ECDSA P-256 |
| Extensions | names and usage rules, version 3 only, §4.2 |
Versions 1, 2 and 3
X.509 version 3 extends version 2 with extensions. A certificate with only the basic fields should be version 1, and CAs that follow RFC 5280 must not use the unique identifiers versions 2 and 3 allow [1]. Signing the test request without extensions, OpenSSL 3.0.13 wrote Version: 1 (0x0).
The extensions that matter for TLS
For names and usage, a TLS client reads the extensions listed below. Each extension in an X.509 version 3 certificate is marked critical or non-critical, and RFC 5280 sets the rule: a system that meets a critical extension it does not recognize must reject the certificate, and an unknown non-critical one may be ignored [1].
Subject Alternative Name. The host names the certificate covers. Under RFC 9525, a server's identity can only be expressed in this extension, and the subject's common name is not used [4]. See Subject Alternative Names.
Basic Constraints. Whether the certified public key may verify signatures on other certificates. A website certificate has
CA:FALSE; a CA certificate whose key signs certificates hasCA:TRUE, with the extension marked critical [1].Key Usage and Extended Key Usage. What the key may do. A website certificate carries
TLS Web Server Authentication, theserverAuthpurpose; a client certificate for mutual TLS carriesTLS Web Client Authentication[1].
Issuer, revocation and log extensions
The other X.509 extensions point a client to the issuing certificate authority, its revocation list and public logs:
Authority Information Access. Where to download the issuer's certificate, as a single certificate in DER or a certs-only CMS bundle, and, if offered, the OCSP responder's address (RFC 5280 §4.2.2.1) [1].
CRL Distribution Points. Where the issuer publishes its revocation list. CRLs list revoked certificates by serial number [1]. See revocation.
Subject and Authority Key Identifiers. Identify this certificate's key and the key that signed it, to make building the certification path easier [1].
Signed Certificate Timestamps. A log's signed promise to add the certificate to its public record, stored under OID 1.3.6.1.4.1.11129.2.4.2 (RFC 6962 §3, §3.3) [5]; see Certificate Transparency.
Critical and non-critical: a test
The test leaf was signed twice with an unknown extension under a private OID, once critical and once not. Here is what OpenSSL 3.0.13 and Go 1.27.2 did with each certificate:
| Unknown extension | openssl verify | Go crypto/x509 |
|---|---|---|
| marked critical | error 34 … unhandled critical extension | x509: unhandled critical extension |
| not critical | OK | verified |
How to read an X.509 certificate
openssl x509 -text prints every field [7]. Shortened output for the test certificate:
$ openssl x509 -in cert.pem -noout -text
Certificate:
Data:
Version: 3 (0x2)
Signature Algorithm: ecdsa-with-SHA256
Issuer: CN = Example Test Intermediate
Validity
...
Subject: CN = example.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
X509v3 extensions:
X509v3 Subject Alternative Name:
DNS:example.com, DNS:www.example.com
...
Signature Algorithm: ecdsa-with-SHA256The two algorithms belong to different keys. rsaEncryption is the subject's own key. ecdsa-with-SHA256 is how the intermediate signed, and it appears twice because RFC 5280 requires the copy inside the signed data to match the one outside [1]. Printing single fields, reading a live server with openssl s_client and checking expiry are on OpenSSL commands.
Why one changed byte breaks the certificate
The issuer signs the DER encoding of the whole to-be-signed part [1], so editing any field invalidates the signature. In the test, one letter of www.example.com in the DER file was changed, and this is what OpenSSL then read and said:
$ openssl x509 -inform der -in tampered.der -noout -ext subjectAltName
X509v3 Subject Alternative Name:
DNS:example.com, DNS:www.xxample.com
$ openssl verify -CAfile root.pem -untrusted int.pem tampered.der
error 7 at 0 depth lookup: certificate signature failureThis is why an expiring certificate cannot be extended and has to be replaced; see renewal. Certificate pins on a public key hash the DER of the subject public key info (RFC 7469 §2.4) [6], so a new certificate for the same key keeps the pin valid.
File formats: PEM, DER and others
X.509 defines the content, not the file. A certificate is saved as DER, the binary encoding, or as PEM, the DER bytes in base64 between -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- lines; PEM's labels and line rules have their own glossary entry. File extensions such as .crt, .cer and .pem do not reliably tell you which encoding a file uses. PFX (PKCS#12) and P7B (PKCS#7) bundle X.509 certificates, PFX together with the private key. Telling them apart and converting is on certificate formats.
Where X.509 certificates are used
The key purposes RFC 5280 defines for Extended Key Usage name the jobs: TLS server authentication, TLS client authentication, code signing, email protection, time stamping and OCSP signing [1].
HTTPS and TLS. The server sends its X.509 certificate during the TLS handshake [3], and the client checks the chain, dates and names.
Client authentication. In mutual TLS the client sends a certificate too, under the same X.509v3 rule [3].
Email. S/MIME agents process X.509 certificates and validate them as RFC 5280 describes (RFC 8550) [9].
VPNs. IKEv2 carries DER-encoded X.509 certificates in its Certificate payload (RFC 7296 §3.6) [9].
The format is the same in each case; the extensions and the trust store that checks them differ. Path validation starts from a trust anchor, such as the top CA of a hierarchy [1]; on the web those are root certificates. SSH is the exception. Servers are identified by host keys (RFC 4251 §4.1), and OpenSSH certificates are, in its manual's words, "a different, and much simpler, format to the X.509 certificates" [10]; see SSL vs SSH.
X.509 errors in Go programs
Messages that begin with x509: come from Go's crypto/x509 package; when TLS fails, Go's crypto/tls puts tls: failed to verify certificate: in front of them [8]. Docker Engine, Kubernetes and Terraform are written in Go [11]; when they verify a certificate with Go's standard library, these are the texts they print. Each row was reproduced with Go 1.27.2 on the test chain:
| Message | What failed | Test case |
|---|---|---|
x509: certificate signed by unknown authority | no path to a trusted root; causes and fixes as for unable to get local issuer certificate | intermediate not supplied; root not in the pool |
x509: certificate has expired or is not yet valid: … | the date check; the browser equivalent is ERR_CERT_DATE_INVALID | clock set after notAfter |
x509: certificate is valid for example.com, www.example.com, not b.example.com | the requested name is not in the Subject Alternative Name list | host b.example.com |
x509: certificate relies on legacy Common Name field, use SANs instead | the name is only in the subject's common name, with no SAN extension | leaf without SAN |
x509: unhandled critical extension | a critical extension Go does not know | private OID marked critical |
FAQ
What is an X.509 certificate?
A data structure in the X.509 format that binds a public key to a name, such as a domain name, signed by a certificate authority. SSL/TLS certificates are X.509 certificates.
Is an SSL certificate an X.509 certificate?
Yes. TLS requires X.509 version 3 unless both sides negotiate another type. "SSL certificate" describes the use; X.509 describes the structure. [3]
What is the difference between X.509 and PEM?
X.509 is the certificate's structure. PEM is one way to store it in a file: the DER encoding in base64 text between BEGIN and END lines.
What does "x509: certificate signed by unknown authority" mean?
A Go program could not link the server's certificate to a root it trusts. In the test above, it appeared both when the intermediate was missing and when the root was not trusted.
What is the latest version of X.509?
Version 3, the newest of the three RFC 5280 defines; the version field holds 2. It added extensions, including Subject Alternative Name, which TLS relies on. [1]
Sources
RFC 5280, X.509 certificate and CRL profile: §3.1, §4.1, §4.2, §5.1.2.6, §6.
ITU-T Recommendation X.509, Public-key and attribute certificate frameworks.
RFC 8446, TLS 1.3: §4.4.2, §4.4.2.2, §4.4.2.3.
RFC 9525, Service Identity in TLS: §2, Appendix A.
RFC 6962, Certificate Transparency: §3, §3.3.
RFC 7469, Public Key Pinning: §2.4.
OpenSSL 3.0 manual: openssl-x509, option
-text; openssl-asn1parse; X509_STORE_CTX_get_error (errors 7 and 34).Go 1.27.2 source, crypto/x509/verify.go; crypto/x509/x509.go; crypto/tls/common.go.
RFC 8550, S/MIME 4.0 Certificate Handling: Abstract; RFC 7296, IKEv2: §3.6.
RFC 4251, SSH architecture: §4.1; ssh-keygen(1) manual, Certificates.
go.mod of moby/moby, kubernetes/kubernetes, hashicorp/terraform.