munotes®

X.509: The Certificate and Its Fields

Get access to whole semester resourcesSemester Pass

Chapter Sixty-Four

Syllabus topic Module 2, "Authentication Applications: X.509 Authentication"

Pages 402 to 412 of 678

In one line

An X.509 certificate is a small signed document that says "this public key belongs to this name", signed by an authority whose own public key you already trust.

In the words an answer should use: an X.509 certificate is a data structure, defined by ITU-T Recommendation X.509 and profiled for the Internet by RFC 5280, that binds a subject's name to a public key for a stated validity period; it is issued and digitally signed by a certification authority (CA), so that anyone holding the CA's public key can verify that the binding was made by that CA and has not been altered.

Why certificates exist

The key-distribution chapter of Module 1 ended on a problem: a public key is only useful if you know whose it is. Anyone can generate a key pair and announce "this is the bank's key". A certificate moves the question from "is this the bank's key?" to "did an authority I already trust say so?", and the second question can be answered by checking one signature.

The same chapter set out what a certificate scheme must allow: anyone can read a certificate and learn the owner's name and key; anyone can verify that it came from the CA and is not counterfeit; only the CA can create or change one; and anyone can check that it is still current. X.509 is the format that meets those four requirements, and it is the one the whole Internet uses.

Where X.509 comes from

X.509 is an ITU-T Recommendation, published jointly with ISO as ISO/IEC 9594-8. It was first published in 1988 as part of the X.500 series of Recommendations on directory services, and it defined the certificate format that the rest of the world then adopted. The Recommendation's own history table, and RFC 5280's account of it, give the dates:

YearWhat changed
1988first edition; the certificate format of this edition is version 1
1993second edition; two optional fields added, the issuer and subject unique identifiers, giving version 2
1996the version 3 format completed (June 1996), adding extensions, and published in the 1997 edition
2008RFC 5280 profiles version 3 for the Internet: which fields and extensions Internet software must support
2019the current edition, approved in October 2019 and published as ISO/IEC 9594-8:2020

Version 3 is the only one worth learning in detail. RFC 5280 says that when extensions are used, "as expected in this profile, version MUST be 3". Every certificate a browser sees is version 3.

The certificate's three parts

At the top level a certificate has exactly three parts, and seeing them is most of understanding what a CA does:

  1. tbsCertificate, "to be signed": every field that says something, the name, the key, the dates, the extensions.
  2. signatureAlgorithm: which algorithm the CA used to sign.
  3. signatureValue: the CA's signature on the tbsCertificate bytes, and on nothing else.
munotes.in402

X.509: The Certificate and Its Fields

The signature covers the first part only. The CA hashes the encoded tbsCertificate and signs the hash with its private key. A verifier hashes the same bytes and checks the signature with the CA's public key. Change one byte of the first part and the check fails.

Every field, and what it is for

The fields of tbsCertificate, in order, as RFC 5280 s.4.1 defines them. The last column is the value in the certificate munotes.in served on 30 September 2026, read by the listing below.

FieldWhat it holdsWhy it is theremunotes.in's value
version1, 2 or 3, stored as 0, 1 or 2tells software which fields to expect3
serialNumbera positive integer, unique for this CA, at most 20 bytesissuer name plus serial number identifies exactly one certificate; revocation lists name certificates by it18 bytes
signaturethe algorithm the CA usedmust equal the outer signatureAlgorithmecdsa-with-SHA384
issuerthe CA's distinguished namesays whose public key verifies the signatureLet's Encrypt, YE1
validitynotBefore and notAfterthe period in which the CA warrants it will keep status information about the certificate12 September to 11 December 2026
subjectthe owner's distinguished namethe name being bound to the keyCN=munotes.in
subjectPublicKeyInfothe algorithm and the public key itselfthe whole point of the certificatean elliptic-curve key on P-256
issuerUniqueID, subjectUniqueIDoptional bit strings (version 2 and 3)to tell apart two issuers or subjects with the same nameabsent
extensionsa list of extra fields (version 3 only)everything the first seven fields cannot sayten of them

A distinguished name is a name built from typed parts: country C, organisation O, common name CN, and others. C=US, O=Let's Encrypt, CN=YE1 is one.

Three details carry marks.

The validity period includes both ends. RFC 5280 says the period runs "from notBefore through notAfter, inclusive". munotes.in's certificate runs from 11:54:59 on 12 September to 11:54:58 on 11 December, which is 89 days, 23 hours, 59 minutes and 59 seconds apart, and so exactly 90 days counting both ends.

Dates are written in two forms. Up to 2049 a date is encoded as UTCTime, with a two-digit year; from 2050 it must be GeneralizedTime, with four. A certificate with no well-defined expiry date uses the notAfter value 99991231235959Z.

The issuer and serial number together name one certificate. That is why a revocation list, in the next chapter, is a list of serial numbers.

munotes.in403

X.509: The Certificate and Its Fields

The textbook's notation

The prescribed textbook writes certificates in a compact notation, which is worth being able to read and to write.

  • Y<<X>> means the certificate of user X issued by CA Y.
  • Y{I} means the information I, signed by Y: I together with Y's signature on it.
  • So a certificate of user A issued by a CA is written
CA<<A>> = CA {V, SN, AI, CA, UCA, A, UA, Ap, TA}

where V is the version, SN the serial number, AI the signature algorithm identifier, CA the issuer's name, UCA the issuer's unique identifier, A the subject's name, UA the subject's unique identifier, Ap A's public key, and TA the validity period. The list is the tbsCertificate fields in order, and the braces say the CA signed them.

The 2019 Recommendation writes a signed item the same way, A{...} for information signed by A, and writes Ap for A's public key and Bp[...] for something encrypted under B's public key, which is the notation of the authentication procedures below.

Extensions

Version 3 added extensions, and every modern certificate depends on them. Each extension is three things: an object identifier naming it, a flag saying whether it is critical, and its value.

The critical flag is a rule about unknown extensions. RFC 5280 s.4.2: software "MUST reject the certificate if it encounters a critical extension it does not recognize"; a non-critical extension "MAY be ignored if it is not recognized, but MUST be processed if it is recognized". So a CA marks critical exactly the restrictions it cannot afford to have ignored.

X.509 itself sorts the standard extensions into groups, and the ones in munotes.in's certificate fall into all three:

Key and policy information.

  • Key usage (critical in both certificates below): what the key may be used for. munotes.in's key may make digital signatures only; the CA's key may also sign certificates (keyCertSign) and revocation lists (cRLSign).
  • Extended key usage: finer purposes by name. serverAuth means a TLS server.
  • Subject key identifier and authority key identifier: short fingerprints of the subject's key and of the issuer's key. They let software find the issuer's certificate when a CA has more than one key: munotes.in's authority key identifier equals YE1's subject key identifier, and the run checks it.
  • Certificate policies: which published rules the CA followed when it issued. 2.23.140.1.2.1 is the CA/Browser Forum's "domain validated" policy: the CA checked only that the applicant controls the domain.

Subject and issuer information.

  • Subject alternative name: the names the key really belongs to. For a website this is the list of host names, here munotes.in and www.munotes.in. This, not the subject's common name, is what a browser matches. RFC 9525, November 2023, is blunt: the Common Name "MUST NOT be used to identify a service", because it is free-form text.
munotes.in404

X.509: The Certificate and Its Fields

Certification path constraints.

  • Basic constraints (critical): whether the subject is a CA. munotes.in's says CA: no, so its key must never be accepted as the signer of another certificate. YE1's says CA: yes, path length 0: it may sign certificates, but no further CA may sit below it. RFC 5280 requires this extension, marked critical, in every CA certificate whose key signs certificates.

And three that tell software where to look:

  • Authority information access: where to fetch the issuer's certificate, http://ye1.i.lencr.org/.
  • CRL distribution points: where to fetch the revocation list that would name this certificate if it were revoked, the subject of the next chapter.
  • Certificate Transparency timestamps: signed promises from public logs that this certificate will be added to them within a fixed time (RFC 6962), so that a certificate issued by mistake, or by a CA that has been attacked, cannot be issued in secret. munotes.in's carries two.

The run: reading munotes.in's certificate

The two files below are real certificates as munotes.in served them on 30 September 2026: its own, and its issuer's. A certificate on disk is usually PEM, base64 text between two marker lines; underneath is DER, the binary encoding of the ASN.1 structure RFC 5280 defines, where every item is a tag, a length and a value.

-----BEGIN CERTIFICATE-----
MIIDkjCCAxmgAwIBAgISBf++q0njvGQyUykj6Cj+EYiQMAoGCCqGSM49BAMDMDMx
CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQwwCgYDVQQDEwNZ
RTEwHhcNMjYwOTEyMTE1NDU5WhcNMjYxMjExMTE1NDU4WjAVMRMwEQYDVQQDEwpt
dW5vdGVzLmluMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEtlAU0VbQfEk4HTrX
5hIWuUpiQ20GHhNVuqE+ZDVD9ULSrOf4Kg8qSn0gtLQPRk5fVBf/1lUus8ioEKMA
V2+Tt6OCAikwggIlMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcD
ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTYT4mXaBFZ9hSOXEPu3Mg0+5NmNTAf
BgNVHSMEGDAWgBS7IMpHC/7X5Zz5jwkqo4w3RbG82DAzBggrBgEFBQcBAQQnMCUw
IwYIKwYBBQUHMAKGF2h0dHA6Ly95ZTEuaS5sZW5jci5vcmcvMCUGA1UdEQQeMByC
Cm11bm90ZXMuaW6CDnd3dy5tdW5vdGVzLmluMBMGA1UdIAQMMAowCAYGZ4EMAQIB
MC4GA1UdHwQnMCUwI6AhoB+GHWh0dHA6Ly95ZTEuYy5sZW5jci5vcmcvMTcuY3Js
MIIBDQYKKwYBBAHWeQIEAgSB/gSB+wD5AHYA1219ENGn9XfCx+lf1wC/+YLJM1pl
4dCzAXMXwMjFaXcAAAGgla4X3QAABAMARzBFAiBCYhMg08b9CrBS19uyuz3wZStw
W7DE7t8ZSDPcUvBD4gIhAMD7yhJN64KP6bWG5H6ZA68VLvNZCiRLQrsvnH92e8bO
AH8AqCbL4wrGNRJGUz/gZfFPGdluGQgTxB3ZbXkAsxI8VScAAAGgla4azQAIAAAF
ADH5KHsEAwBIMEYCIQCQybl79cSWejo8WdCZ3O4BS7uIG/gVa+gwzM4PHheFCgIh
AIgzHibZCL4C2UUgOwU0rHkIHnhr05PVx6KajQca6AZiMAoGCCqGSM49BAMDA2cA
MGQCMAR9Skrz1wHkFWwr/d/D28Pjlo8+ZPALlN7CuZG728/ZJy+h/Wn68R5HhziI
YSN6OwIwRID/awRkE2KqxXBIPSQ+zj2S4d/UivmhZt2GHve0KRjTiuh1JUdx4iH1
MqrwigZp
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIICizCCAhGgAwIBAgIQXd1w3TH4AchcGGp6BLgK/jAKBggqhkjOPQQDAzAuMQsw
CQYDVQQGEwJVUzENMAsGA1UEChMESVNSRzEQMA4GA1UEAxMHUm9vdCBZRTAeFw0y
NTA5MDMwMDAwMDBaFw0yODA5MDIyMzU5NTlaMDMxCzAJBgNVBAYTAlVTMRYwFAYD
VQQKEw1MZXQncyBFbmNyeXB0MQwwCgYDVQQDEwNZRTEwdjAQBgcqhkjOPQIBBgUr
gQQAIgNiAAQHZVB1/mimla2hfSurylScjPMZaOJXLz/NnAc2sylm8WDyhU9Ccp+z
ASQi5vSwGGJjSGklkD9fdPR8GpyDIOIjCEfrnbt/v+ZSEPLLEGbaM6EccDbN7p9x
teIm2Avf+ryjge4wgeswDgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUF
BwMBMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFLsgykcL/tflnPmPCSqj
jDdFsbzYMB8GA1UdIwQYMBaAFKPIJlqOoUzQNWP8myPIOq5W809WMDIGCCsGAQUF
BwEBBCYwJDAiBggrBgEFBQcwAoYWaHR0cDovL3llLmkubGVuY3Iub3JnLzATBgNV
HSAEDDAKMAgGBmeBDAECATAnBgNVHR8EIDAeMBygGqAYhhZodHRwOi8veWUuYy5s
ZW5jci5vcmcvMAoGCCqGSM49BAMDA2gAMGUCMQDgjUEahFT/h3DRakqiPZpLvPgf
Zwkt6K2EOMmh1nvEzl83eMLYcod4GCl3b0J1Nn0CMBNYmEQJb4CEG5WoOe7aRn/L
VKu6saHmHEynI7ysIPd8zQsK1HdmhlHKlw9Z5GpGvA==
-----END CERTIFICATE-----

The listing reads the DER with a forty-line reader, prints every field and extension, and then checks the CA's signature. The signature is ECDSA on the curve P-384, the elliptic-curve scheme of the signature standard chapters; the curve's constants are taken from FIPS 186-4 and checked before use.

# Every field of a real certificate, read from its bytes, and the CA's signature checked.
import base64, datetime, hashlib

def der_of(path):                         # PEM is base64 between two marker lines
    lines = open(path).read().split('\n')
    return base64.b64decode(''.join(l for l in lines if l and not l.startswith('-----')))

def tlv(d, i):                            # one DER element: (tag, value start, value end)
    tag, n, j = d[i], d[i + 1], i + 2
    if n & 0x80:                          # long form: the next (n - 128) bytes hold the length
        k = n & 0x7F
        n, j = int.from_bytes(d[j:j + k], 'big'), j + k
    return tag, j, j + n

def items(d, start, end):                 # the elements inside a SEQUENCE, SET or wrapper
    out, i = [], start
    while i < end:
        tag, s, e = tlv(d, i)
        out.append((tag, s, e, i))        # i is where the whole element begins
        i = e
    return out

def oid(b):
    arcs, v = [b[0] // 40, b[0] % 40], 0
    for byte in b[1:]:
        v = (v << 7) | (byte & 0x7F)
        if not byte & 0x80:
            arcs.append(v)
            v = 0
    return '.'.join(map(str, arcs))

NAMES = {'1.2.840.10045.4.3.3': 'ecdsa-with-SHA384', '1.2.840.10045.2.1': 'EC public key',
         '1.2.840.10045.3.1.7': 'P-256', '1.3.132.0.34': 'P-384', '2.5.4.3': 'CN',
         '2.5.4.6': 'C', '2.5.4.10': 'O', '2.5.29.15': 'keyUsage', '2.5.29.37': 'extKeyUsage',
         '2.5.29.19': 'basicConstraints', '2.5.29.14': 'subjectKeyIdentifier',
         '2.5.29.35': 'authorityKeyIdentifier', '1.3.6.1.5.5.7.1.1': 'authorityInfoAccess',
         '2.5.29.17': 'subjectAltName', '2.5.29.32': 'certificatePolicies',
         '2.5.29.31': 'cRLDistributionPoints', '1.3.6.1.4.1.11129.2.4.2': 'CT timestamps',
         '1.3.6.1.5.5.7.3.1': 'serverAuth', '2.23.140.1.2.1': 'domain validated'}
USAGE = ['digitalSignature', 'nonRepudiation', 'keyEncipherment', 'dataEncipherment',
         'keyAgreement', 'keyCertSign', 'cRLSign', 'encipherOnly', 'decipherOnly']

def name(d, s, e):                        # SEQUENCE of SET of (type, string)
    parts = []
    for _, s1, e1, _ in items(d, s, e):
        for _, s2, e2, _ in items(d, s1, e1):
            (_, a, b, _), (_, c, f, _) = items(d, s2, e2)
            parts.append(NAMES.get(oid(d[a:b]), oid(d[a:b])) + '=' + d[c:f].decode())
    return ', '.join(parts)

def when(d, s, e):
    return datetime.datetime.strptime(d[s:e].decode(), '%y%m%d%H%M%SZ')

def uris(d, s, e, tag=0x86):              # every [6] URI or [2] dNSName, however deep
    found = []
    for t, s1, e1, _ in items(d, s, e):
        if t == tag:
            found.append(d[s1:e1].decode())
        elif t & 0x20:                    # constructed: look inside
            found += uris(d, s1, e1, tag)
    return found

def extension(d, key, s, e):
    if key == 'keyUsage':
        _, a, b = tlv(d, s)
        bits = int.from_bytes(d[a + 1:b], 'big') << 8 >> 8
        width = (b - a - 1) * 8
        return ' '.join(u for k, u in enumerate(USAGE) if k < width and bits >> (width - 1 - k) & 1)
    if key == 'basicConstraints':
        inner = items(d, *tlv(d, s)[1:])
        ca = bool(inner and inner[0][0] == 0x01 and d[inner[0][1]] != 0)
        path = [int.from_bytes(d[a:b], 'big') for t, a, b, _ in inner if t == 0x02]
        return 'CA: ' + ('yes' if ca else 'no') + (', path length %d' % path[0] if path else '')
    if key == 'extKeyUsage' or key == 'certificatePolicies':
        found, stack = [], [tlv(d, s)[1:]]
        while stack:
            a, b = stack.pop()
            for t, s1, e1, _ in items(d, a, b):
                if t == 0x06:
                    o = oid(d[s1:e1]); found.append(NAMES.get(o, o))
                elif t == 0x30:
                    stack.append((s1, e1))
        return ', '.join(found)
    if key == 'subjectKeyIdentifier':
        _, a, b = tlv(d, s)
        return d[a:b].hex().upper()[:16] + '...'
    if key == 'authorityKeyIdentifier':
        _, a, b = tlv(d, s)
        return d[items(d, a, b)[0][1]:items(d, a, b)[0][2]].hex().upper()[:16] + '...'
    if key == 'subjectAltName':
        return ', '.join(uris(d, *tlv(d, s)[1:], tag=0x82))
    if key in ('authorityInfoAccess', 'cRLDistributionPoints'):
        return ', '.join(uris(d, *tlv(d, s)[1:]))
    if key == 'CT timestamps':
        return '%d signed timestamps from public logs' % len(scts(d[s:e]))
    return '(%d bytes)' % (e - s)

def scts(blob):                           # TLS-encoded list inside an OCTET STRING
    _, a, b = tlv(blob, 0)
    body, found, i = blob[a + 2:b], [], 0
    while i < len(body):
        n = int.from_bytes(body[i:i + 2], 'big')
        found.append(body[i + 2:i + 2 + n]); i += 2 + n
    return found

def read(path):
    d = der_of(path)
    _, s, e = tlv(d, 0)
    (_, ts, te, tstart), (_, as_, ae, _), (_, ss, se, _) = items(d, s, e)
    f = items(d, ts, te)
    cert = {'der': d, 'tbs': (tstart, te), 'fields': f,
            'version': d[items(d, f[0][1], f[0][2])[0][1]] + 1,
            'serial': d[f[1][1]:f[1][2]],
            'algorithm': NAMES[oid(d[items(d, f[2][1], f[2][2])[0][1]:items(d, f[2][1], f[2][2])[0][2]])],
            'issuer': name(d, f[3][1], f[3][2]), 'subject': name(d, f[5][1], f[5][2]),
            'from': when(d, *items(d, f[4][1], f[4][2])[0][1:3]),
            'until': when(d, *items(d, f[4][1], f[4][2])[1][1:3])}
    spki = items(d, f[6][1], f[6][2])
    alg = items(d, spki[0][1], spki[0][2])
    cert['curve'] = NAMES[oid(d[alg[1][1]:alg[1][2]])]
    point = d[spki[1][1] + 1:spki[1][2]]              # skip the unused-bits byte
    half = (len(point) - 1) // 2
    cert['Q'] = (int.from_bytes(point[1:1 + half], 'big'), int.from_bytes(point[1 + half:], 'big'))
    cert['extensions'] = []
    for _, xs, xe, _ in items(d, *tlv(d, f[7][1])[1:]):
        parts = items(d, xs, xe)
        key = NAMES.get(oid(d[parts[0][1]:parts[0][2]]), oid(d[parts[0][1]:parts[0][2]]))
        critical = len(parts) == 3 and d[parts[1][1]] != 0
        cert['extensions'].append((key, critical, extension(d, key, parts[-1][1], parts[-1][2])))
    rs = items(d, ss + 1, se)                          # BIT STRING holding SEQUENCE {r, s}
    cert['r'], cert['s'] = [int.from_bytes(d[a:b], 'big') for _, a, b, _ in items(d, rs[0][1], rs[0][2])]
    return cert

leaf, ca = read('munotes-leaf.pem'), read('ye1.pem')
print('THE CERTIFICATE munotes.in SERVED ON 30 SEPTEMBER 2026 (%d bytes of DER)' % len(leaf['der']))
print('  version               %d' % leaf['version'])
print('  serial number         %s (%d bytes)' % (leaf['serial'].hex().upper(), len(leaf['serial'])))
print('  signature algorithm   %s' % leaf['algorithm'])
print('  issuer                %s' % leaf['issuer'])
print('  not before            %s UTC' % leaf['from'])
print('  not after             %s UTC' % leaf['until'])
print('  subject               %s' % leaf['subject'])
print('  public key            EC point on %s' % leaf['curve'])
print('  extensions, %d of them:' % len(leaf['extensions']))
for key, critical, value in leaf['extensions']:
    print('    %-24s %-9s %s' % (key, 'critical' if critical else '', value))
span = leaf['until'] - leaf['from']
print('  validity              %s, so %d days counting both ends' % (span, span.days + 1))

print()
print('ITS ISSUER, %s' % ca['subject'])
print('  issued by             %s' % ca['issuer'])
print('  public key            EC point on %s' % ca['curve'])
for key, critical, value in ca['extensions']:
    if key in ('basicConstraints', 'keyUsage', 'subjectKeyIdentifier'):
        print('    %-24s %-9s %s' % (key, 'critical' if critical else '', value))
ski = [v for k, c, v in ca['extensions'] if k == 'subjectKeyIdentifier'][0]
aki = [v for k, c, v in leaf['extensions'] if k == 'authorityKeyIdentifier'][0]
print('  the leaf\'s authority key identifier equals this subject key identifier:', aki == ski)

# ---- ECDSA verification on P-384 (constants from FIPS 186-4 D.1.2.4) ---------------------
p = 2**384 - 2**128 - 2**96 + 2**32 - 1
n = 0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973
b = 0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef
G = (0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7,
     0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f)
a = p - 3

def add(P, Q):
    if P is None: return Q
    if Q is None: return P
    if P[0] == Q[0] and (P[1] + Q[1]) % p == 0: return None
    if P == Q: lam = (3 * P[0] * P[0] + a) * pow(2 * P[1], -1, p) % p
    else:      lam = (Q[1] - P[1]) * pow(Q[0] - P[0], -1, p) % p
    x = (lam * lam - P[0] - Q[0]) % p
    return (x, (lam * (P[0] - x) - P[1]) % p)

def mul(k, P):
    R = None
    while k:
        if k & 1: R = add(R, P)
        P, k = add(P, P), k >> 1
    return R

def on_curve(P):
    return (P[1] ** 2 - (P[0] ** 3 + a * P[0] + b)) % p == 0

def verify(tbs, r, s, Q):
    e = int.from_bytes(hashlib.sha384(tbs).digest(), 'big')
    w = pow(s, -1, n)
    X = add(mul(e * w % n, G), mul(r * w % n, Q))
    return X is not None and X[0] % n == r

print()
print('THE CA\'S SIGNATURE, CHECKED WITH NOTHING BUT INTEGERS')
print('  P-384 base point is on the curve, and n times it is the point at infinity:',
      on_curve(G) and mul(n, G) is None)
print('  the issuer\'s public key is a point on P-384:', on_curve(ca['Q']))
tbs = leaf['der'][leaf['tbs'][0]:leaf['tbs'][1]]
print('  signed part of the leaf: %d bytes, hashed with SHA-384' % len(tbs))
print('  signature verifies with the issuer\'s key :', verify(tbs, leaf['r'], leaf['s'], ca['Q']))
forged = tbs.replace(b'munotes.in', b'munotes.io')
later = tbs.replace(b'261211115458Z', b'271211115458Z')
assert forged != tbs and later != tbs            # prove each edit really changed the bytes
print('  one name changed, munotes.in to munotes.io:', verify(forged, leaf['r'], leaf['s'], ca['Q']))
print('  expiry moved a year later                :', verify(later, leaf['r'], leaf['s'], ca['Q']))
munotes.in405

X.509: The Certificate and Its Fields

THE CERTIFICATE munotes.in SERVED ON 30 SEPTEMBER 2026 (918 bytes of DER)
  version               3
  serial number         05FFBEAB49E3BC6432532923E828FE118890 (18 bytes)
  signature algorithm   ecdsa-with-SHA384
  issuer                C=US, O=Let's Encrypt, CN=YE1
  not before            2026-09-12 11:54:59 UTC
  not after             2026-12-11 11:54:58 UTC
  subject               CN=munotes.in
  public key            EC point on P-256
  extensions, 10 of them:
    keyUsage                 critical  digitalSignature
    extKeyUsage                        serverAuth
    basicConstraints         critical  CA: no
    subjectKeyIdentifier               D84F8997681159F6...
    authorityKeyIdentifier             BB20CA470BFED7E5...
    authorityInfoAccess                http://ye1.i.lencr.org/
    subjectAltName                     munotes.in, www.munotes.in
    certificatePolicies                domain validated
    cRLDistributionPoints              http://ye1.c.lencr.org/17.crl
    CT timestamps                      2 signed timestamps from public logs
  validity              89 days, 23:59:59, so 90 days counting both ends

ITS ISSUER, C=US, O=Let's Encrypt, CN=YE1
  issued by             C=US, O=ISRG, CN=Root YE
  public key            EC point on P-384
    keyUsage                 critical  digitalSignature keyCertSign cRLSign
    basicConstraints         critical  CA: yes, path length 0
    subjectKeyIdentifier               BB20CA470BFED7E5...
  the leaf's authority key identifier equals this subject key identifier: True

THE CA'S SIGNATURE, CHECKED WITH NOTHING BUT INTEGERS
  P-384 base point is on the curve, and n times it is the point at infinity: True
  the issuer's public key is a point on P-384: True
  signed part of the leaf: 797 bytes, hashed with SHA-384
  signature verifies with the issuer's key : True
  one name changed, munotes.in to munotes.io: False
  expiry moved a year later                : False
munotes.in406

X.509: The Certificate and Its Fields

What the run establishes, in order.

munotes.in407

X.509: The Certificate and Its Fields

Every field is there, in RFC 5280's order, and each matches what openssl x509 -text prints for the same file: version 3, an 18-byte serial number, the issuer YE1, 90 days of validity, the subject munotes.in, a P-256 key, and ten extensions.

munotes.in408

X.509: The Certificate and Its Fields

The end-entity certificate and the CA certificate differ where the chapter says they do. munotes.in's key usage is digital signatures only and its basic constraints say CA: no; YE1's key usage adds certificate signing and revocation-list signing, and its basic constraints say CA: yes, path length 0.

The two certificates are linked by key identifiers. The leaf's authority key identifier equals YE1's subject key identifier.

The CA's signature verifies from nothing but integers. Hash the 797 signed bytes with SHA-384, run ECDSA verification on P-384 with YE1's public key, and the result is True.

Any change breaks it. One letter of the host name changed, munotes.in to munotes.io, and the signature fails. The expiry moved one year later, and it fails. This is the whole security of a certificate: its content can be read by anyone and changed by no one but the CA.

X.509's authentication procedures

Besides the certificate, X.509 describes how two parties who hold each other's certificates can authenticate. The current Recommendation keeps these in its Annex N, which describes five procedures; the three set in examinations are one-way, two-way and three-way. In each, a token is a small message signed by its sender.

The symbols: A{...} is information signed by A; tA is a timestamp holding an expiry; rA is a nonce, a number A never repeats; B is B's name; Bp[...] is information encrypted under B's public key.

One-way     A -> B    A{tA, rA, B}
Two-way     A -> B    A{tA, rA, B}
            B -> A    B{tB, rB, A, rA}
Three-way   A -> B    A{tA, rA, B}
            B -> A    B{tB, rB, A, rA}
            A -> B    A{rB, B}

Any token may also carry signed data (sgnData) and a secret for B encrypted under B's public key (Bp[encData]), which is how a session key is sent.

ProcedureWhat it provesWhat the receiver checksNeeds synchronised clocks
One-waythe identity of A; that the token was made by A and meant for B; its integrity and freshnessA's certificate has not expired; the signature; that B is the named recipient; the timestamp is current; optionally that rA is not a replayyes
Two-wayall of that, plus the same about B's reply to Athe same checks, made by A on B's tokenyes
Three-waythe same as two-wayeach side checks that its own nonce came backno: the timestamps may be zero
munotes.in409

X.509: The Certificate and Its Fields

The three-way procedure is what removes the clocks. In the two-way procedure freshness rests on timestamps, so both clocks must agree, which is the Kerberos trade again. In the three-way procedure each party sends a nonce and demands it back signed by the other, so freshness rests on the nonces, and the Recommendation says the timestamps "need not be checked".

The 2019 edition adds two five-way procedures involving a third party it calls a trust broker, which checks both certificates for A and B. They are recorded here so that a reference to "five-way authentication" is recognised; the one-, two- and three-way procedures are the ones to know.

Distinctions that carry marks

End-entity certificateCA certificate
Basic constraintsCA: no, or absentCA: yes, critical, with an optional path length
Key usagesignatures, key agreement, key enciphermentadds keyCertSign and cRLSign
Examplemunotes.inLet's Encrypt YE1
Critical extensionNon-critical extension
Software that does not recognise itmust reject the certificatemay ignore the extension
Software that recognises itmust process itmust process it
Used forrestrictions that must not be skipped: basic constraints, key usageinformation: key identifiers, where to fetch things
Version 1 (1988)Version 2 (1993)Version 3 (1996)
Unique identifiersnoyesyes
Extensionsnonoyes
In use todayrarelynoeverywhere

What beginners get wrong here

Saying a certificate is encrypted. It is signed, not encrypted. Anyone can read every field of it, as the run does. The signature stops it being changed, not read.

Saying the CA signs the whole certificate. It signs the tbsCertificate part. The signature cannot sign itself.

Saying the common name identifies the website. Software matches the host name against the subject alternative name, and RFC 9525 forbids using the common name for that.

Thinking a certificate says the owner is honest. It says a CA checked a name against a key, under a stated policy. A domain-validated certificate proves only that the applicant controlled the domain when it applied.

Thinking a certificate within its dates is safe to trust. It may have been revoked. Checking that is the next chapter.

Quick revision

  • X.509: ITU-T Recommendation, = ISO/IEC 9594-8; v1 1988, v2 1993 (unique identifiers), v3 June 1996 (extensions); Internet profile RFC 5280 (2008); current edition October 2019.
  • Three parts: tbsCertificate, signatureAlgorithm, signatureValue; the CA signs the hash of the first.
  • Fields: version, serial number, signature algorithm, issuer, validity (inclusive), subject, subject public key info, two unique identifiers, extensions.
  • Notation: CA<<A>> = CA {V, SN, AI, CA, UCA, A, UA, Ap, TA}; Y{I} is I signed by Y.
  • Critical extension not recognised means reject; non-critical may be ignored.
  • Key extensions: key usage, extended key usage, subject and authority key identifiers, certificate policies, subject alternative name (what browsers match), basic constraints (CA or not, path length), authority information access, CRL distribution points.
  • Authentication procedures: one-way A{tA, rA, B}; two-way adds B{tB, rB, A, rA}; three-way adds A{rB, B} and needs no synchronised clocks.
munotes.in410

X.509: The Certificate and Its Fields

Test yourself

1. Define an X.509 certificate and name its three top-level parts. It is a data structure, standardised by ITU-T X.509 and profiled for the Internet by RFC 5280, in which a certification authority binds a subject's name to a public key for a validity period and signs the result. Its three parts are the tbsCertificate, holding every field to be signed; the signatureAlgorithm, naming the algorithm the CA used; and the signatureValue, the CA's signature on the encoded tbsCertificate.

2. List the fields of a version 3 certificate and state what each is for. Version, which tells software which fields to expect; serial number, unique for the issuing CA; signature, the algorithm the CA used; issuer, the CA's name; validity, the not-before and not-after dates; subject, the owner's name; subject public key information, the algorithm and the key; the optional issuer and subject unique identifiers; and extensions, which carry everything else, such as key usage, basic constraints and the subject's alternative names.

3. Write the textbook's notation for a certificate of user A issued by a CA, and explain each symbol. CA<<A>> = CA {V, SN, AI, CA, UCA, A, UA, Ap, TA}. V is the version, SN the serial number, AI the signature algorithm identifier, CA the issuer's name, UCA the issuer's unique identifier, A the subject's name, UA the subject's unique identifier, Ap A's public key and TA the validity period; the braces preceded by CA mean the whole list is signed by the CA.

4. What does it mean for an extension to be marked critical? It means that software that does not recognise the extension, or cannot process what it contains, must reject the whole certificate. A non-critical extension may be ignored by software that does not recognise it. CAs mark critical the restrictions that must not be skipped, such as basic constraints and key usage.

munotes.in411

X.509: The Certificate and Its Fields

5. How do the basic constraints of munotes.in's certificate and of its issuer differ, and why? munotes.in's certificate says CA: no, so its key may never be accepted as the signer of another certificate; it belongs to a website, not an authority. Its issuer YE1 says CA: yes with a path length of zero, so it may sign certificates, but only end-entity ones: no further CA may appear below it in a chain.

6. Explain the three-way authentication procedure, and what it gains over the two-way one. A sends B a token signed by A containing a timestamp, a nonce rA and B's name; B replies with a token signed by B containing its own timestamp, a nonce rB, A's name and rA; A then sends a token signed by A containing rB and B's name. Each party checks that its own nonce came back signed by the other. Because freshness rests on the returned nonces, the timestamps need not be checked, so the parties do not need synchronised clocks, which the two-way procedure does.

7. A browser connects to www.munotes.in. Which field does it match the host name against? The subject alternative name extension, which lists munotes.in and www.munotes.in. The subject's common name is not used: RFC 9525 says the Common Name must not be used to identify a service.

munotes.in412

The rest of this subject

These notes are cut from the University's printed syllabus. Open the syllabus itself for the same subject.

Issue
Done!