skip to content

A monitor keys leaf certificates on serialNumber alone and treats authorityKeyIdentifier as proof of the issuer — what breaks?

level: seniorimportance: should knowfreq 40%

answer

  1. unique per issuer, not per world
  2. a pair, not a number
  3. hints narrow, they do not prove
  4. pointers are attacker-chosen strings
  5. only the signature settles who signed

basics

~20 s

Serial numbers are unique only per issuing authority, so certificates from different CAs collide; the unique key is issuer plus serialNumber. authorityKeyIdentifier is an unverified hint written into the certificate, not evidence of who signed it.

solid answer

~40 s

RFC 5280 requires `serialNumber` to be unique for each certificate issued by **a given CA**, which makes `issuer` plus `serialNumber` the identifying pair — serial `03` can and does appear under many authorities. `authorityKeyIdentifier` and `subjectKeyIdentifier` are *identifiers*: short values that let a reader narrow down which key is which, typically derived from the public key but chosen by whoever built the certificate. Nothing checks them. The same applies to the pointer extensions — `authorityInfoAccess` with `id-ad-caIssuers` and `id-ad-ocsp`, plus `cRLDistributionPoints` and `freshestCRL` — which are URLs an issuer embedded and which, in a certificate you have not validated, are attacker-chosen strings. Only verifying the signature establishes which key signed, and that belongs to path validation.

code

json · 22 lines
json
[
  {
    "issuer": "C=EX, O=Public CA Alpha, CN=Alpha TLS G2",
    "serialNumber": "03",
    "subjectAltName": ["dNSName:shop.example.test"],
    "authorityKeyIdentifier": "9b:1c:04:...",
    "authorityInfoAccess": {
      "id-ad-caIssuers": "http://pki.alpha.example/issuer.cer",
      "id-ad-ocsp": "http://status.alpha.example"
    }
  },
  {
    "issuer": "C=EX, O=Registry Internal CA, CN=Registry Issuing CA",
    "serialNumber": "03",
    "subjectAltName": ["dNSName:mail.example.test"],
    "authorityKeyIdentifier": "9b:1c:04:...",
    "authorityInfoAccess": {
      "id-ad-caIssuers": "http://pki.registry.example/ca.cer",
      "id-ad-ocsp": "http://status.registry.example"
    }
  }
]

go deeper

for a junior

Know that a serial number identifies a certificate only within one issuing authority, so the issuer name has to be stored alongside it.

for a middle

Distinguish the identifier extensions, which help you find the right key, from the signature, which is the only field that proves anything about who signed.

for a senior

Design the ingest path accordingly: an identifying tuple rather than a bare serial, a digest over canonical bytes for deduplication, and embedded URLs treated as untrusted input.

for a principal

Set the organisational rule that fields naming things and fields proving things are stored and acted on differently, because every automated pipeline over third-party certificates eventually confuses them.

A monitor ingesting certificates issued for a registry's own zone is reading structures nobody in the organisation created. Everything in them is an assertion, and the fields divide cleanly into two jobs: **naming** a thing, and **proving** a thing. Almost every design error in such a system comes from treating a naming field as a proof. ## serialNumber names one certificate, per issuer The profile's requirement is specific: `serialNumber` is a positive integer assigned by the CA, unique for each certificate **that CA** issues. The uniqueness scope is the issuer, not the world. So: - Two authorities can both issue a certificate with serial `03`, and both are conforming. - The identifying pair is `issuer` plus `serialNumber`. That pair, and not the serial alone, is what a revocation entry or a status query names. - The value is an integer that readers must be able to handle at up to 20 octets. A 64-bit column will silently truncate or loudly reject real certificates; store it as bytes or as text. Keying a store on the serial alone therefore produces collisions between unrelated authorities, and the failure is worse than a duplicate-key error: an upsert overwrites one authority's certificate with another's, and the record that remains is a chimera nobody issued. ## authorityKeyIdentifier and subjectKeyIdentifier are hints `subjectKeyIdentifier` carries a short value identifying the public key in this certificate. `authorityKeyIdentifier` carries the corresponding value for the key that is supposed to have signed it, and may also carry the issuer's name and serial. The profile suggests computing the value as a hash of the public key, but permits any method that identifies the key uniquely, and requires `authorityKeyIdentifier` to be non-critical. What they are for is **narrowing candidates**: when several keys could plausibly be the issuer's, the identifier says which one to try first. What they are not is evidence. Consider what a hostile or simply mistaken submitter can do: build a certificate, write any `authorityKeyIdentifier` into it, self-sign it, and hand it to your monitor. Every field parses. The identifier points confidently at a well-known authority. Nothing about that authority was involved. The only thing that establishes which key signed is verifying `signatureValue` over the `tbsCertificate` with a candidate public key — a different exercise, belonging to path validation, and one the identifier merely speeds up. ## The pointer extensions are strings, not services | Extension | What it holds | What it is in an unvalidated certificate | |---|---|---| | `authorityInfoAccess` with `id-ad-caIssuers` | Where the issuer's certificate may be fetched | A URL chosen by whoever built the certificate | | `authorityInfoAccess` with `id-ad-ocsp` | Where status may be requested | The same | | `cRLDistributionPoints` | Where a revocation list is published | The same | | `freshestCRL` | Where an incremental list is published | The same | Read as fields, they are useful metadata: a monitor can record which endpoints an authority advertises and notice when they change. Read as instructions, they are a request generator pointed wherever a submitter likes. An ingest path that dereferences every URL it finds in an unvalidated certificate has handed control of its outbound requests to its input, and that is before considering the volume a bulk feed can produce. Fetching them is a deliberate decision made after validation, with its own rules — and what to do with the results is a different subject entirely. ## What the monitor should record 1. The `issuer` name and `serialNumber` **as a pair**, which is the certificate's identifying tuple. 2. A digest over the certificate's canonical encoding, as a stable deduplication key that survives repackaging. 3. The `subjectAltName` entries, which are the names the registry actually cares about. 4. `notBefore` and `notAfter`, so an alert can be scoped to the window the issuer intended. 5. The pointer extensions and key identifiers as **untrusted strings**, recorded verbatim and dereferenced by nothing on the ingest path. ## The general rule The distinction generalises past this leaf. Fields that *name* — serial numbers, key identifiers, distinguished names, URLs — are copied into the structure by whoever assembled it, and a signature over them proves only that the signer was willing to sign that text. Fields that *prove* are cryptographic, and there is exactly one of them in a certificate. A senior answer says which of the two a given field is before saying anything else about it.

  • What does establish which key signed a certificate?
    Verifying the `signatureValue` over the DER encoding of the `tbsCertificate` with a candidate issuer's public key. The `authorityKeyIdentifier` only shortens the list of candidates worth trying; building and validating a complete path is a separate exercise with its own rules.
  • Your ingest table stores serialNumber in a 64-bit integer column. What goes wrong?
    Readers are expected to handle serial values up to 20 octets, so anything wider than eight bytes either overflows or fails to insert. Store the serial as bytes or as text, and key the row on the issuer name together with it.
  • Is it safe to fetch the URLs in authorityInfoAccess for every certificate you ingest?
    No. In a certificate you have not validated, those URLs are content chosen by whoever submitted it, so dereferencing them on ingest turns the monitor into a request generator aimed wherever a submitter points it. Record them as data; fetch, if at all, as a separate deliberate step.

saying these in an interview costs you the question

  • Says serial numbers are globally unique and identify a certificate alone
  • Treats authorityKeyIdentifier as proof of which CA issued the certificate
  • Thinks matching subjectKeyIdentifier and authorityKeyIdentifier means the signature checks out
  • Calls the URLs in authorityInfoAccess trustworthy because a CA wrote them
  • Assumes any serial number fits in a 64-bit integer