← All posts Digital Trust · Part 4 of 7

Designing for Crypto-Agility

Most systems carry at least one cryptographic decision that someone made a decade earlier and assumed would be permanent. It never is. SHA-1 was respectable once. RSA-1024 was the default once. MD5 secured the world's password databases once. The half-life of a cryptographic primitive is shorter than the half-life of the software that depends on it, and that mismatch is among the most reliable sources of expensive, panicked migrations in the field.

This article is about refusing to repeat that mistake. I think of crypto-agility as a property you design into systems, so that the next algorithm change is a configuration exercise rather than a re-architecture. With the post-quantum transition now upon us, the cost of not having that property is about to become very concrete.

Below I cover what agility means, why the clock is already running, and how to build for it: inventory, abstraction, hybrid certificates, and a sequencing strategy that survives contact with production.

What crypto-agility actually means

The term gets used loosely, so I'll start with a tight definition. Crypto-agility is the ability to change the cryptographic algorithms, key types, and parameters a system relies on without re-architecting the system. That's all it means. If swapping a signature algorithm forces you to change wire formats, rewrite storage schemas, re-issue every credential by hand, and coordinate a flag day across forty services, you do not have agility. You have a migration project wearing agility's clothes.

One distinction I insist on with teams: agility is a design property, not a one-time event. You do not "achieve crypto-agility" by completing the PQC migration. You achieve it by building systems whose cryptographic choices are externalised, negotiated, and rotatable, so that this migration, and the next one, and the one after that, are routine. The literature frames it the same way. What counts is how cheaply and safely you can change, rather than which algorithm you happen to run today.

Practically, an agile system tends to share four traits. Algorithms are not hardcoded. The choice of algorithm is configurable and, where the protocol allows, negotiated between parties. Cryptographic operations sit behind a provider abstraction so the implementation can be swapped underneath. And the credential layer (the PKI) can issue, distribute, and rotate keys of new types without bespoke engineering each time.

Why this is urgent now

Two pressures, operating on very different timescales, converge today.

The first is the ordinary, grinding cadence of deprecation. SHA-1 collisions moved from theoretical to demonstrated to cheap, and certificate authorities and browsers spent years dragging the ecosystem off it. RSA-1024 is long gone from any defensible context; RSA-2048 is serviceable now but its trajectory is downward, and prudent designs are already treating 3072-bit as the floor for new long-lived keys. None of this is dramatic, but each step has historically triggered scrambles in organisations that hardcoded assumptions and lost track of where the old primitives lived.

The second pressure is the one that should be reorganising the roadmap: the post-quantum transition. A cryptographically relevant quantum computer would break the asymmetric cryptography underpinning essentially all of today's key establishment and digital signatures: RSA, finite-field and elliptic-curve Diffie-Hellman, ECDSA. We do not know precisely when such a machine arrives. That uncertainty is the reason to start moving now rather than wait.

Harvest now, decrypt later

The threat that makes this urgent today, not on the day a quantum computer is announced, is harvest now, decrypt later. An adversary does not need a quantum computer to act now. They need only to capture and store your encrypted traffic today and decrypt it once the capability exists. Every TLS session protecting data with a meaningful confidentiality lifetime (medical records, state secrets, financial positions, identity data, anything that must stay private for ten, twenty, thirty years) is already exposed if it relies solely on classical key establishment.

If data must stay secret for longer than the lifetime of classical cryptography, then for that data the quantum threat is not a future risk. It is a present one, and the breach may already have happened. It just isn't visible yet.

This is why key establishment should be migrated first, ahead of signatures. A forged signature is a future problem that requires the quantum computer to exist. A harvested key exchange is a problem that is accumulating right now, silently, in every long-lived session.

The NIST PQC outcomes

The standards we build against are now settled enough to design with confidence. The first NIST post-quantum standards landed as:

  • FIPS 203: ML-KEM (derived from CRYSTALS-Kyber): a module-lattice key-encapsulation mechanism for key establishment. This is the workhorse for protecting confidentiality against harvest-now-decrypt-later.
  • FIPS 204: ML-DSA (derived from CRYSTALS-Dilithium): a module-lattice digital signature algorithm, intended as the general-purpose signature default.
  • FIPS 205: SLH-DSA (derived from SPHINCS+): a stateless hash-based signature scheme. Larger and slower, but its security rests only on hash functions, making it a valuable conservative hedge and a good fit for things like firmware and long-lived root signing where signature size matters less than assurance.

The parameter sets within each (ML-KEM-512/768/1024, the ML-DSA security levels) are themselves a thing you must be able to select and change. Agility applies within a family, not only between families.

You cannot migrate what you cannot see

Before any algorithm changes, there is unglamorous work that determines whether the whole effort succeeds: inventory. Well-funded migrations frequently stall not on the cryptography but on the simple fact that nobody can say where the cryptography is.

The deliverable here is a cryptographic bill of materials (CBOM): a living inventory of every place a cryptographic algorithm, key, or parameter is used across the estate. Building it means looking in places people forget:

  • Protocols and their negotiated suites. TLS versions and cipher suites, SSH, IPsec, VPN configurations.
  • Certificates and keys. Signature and public-key algorithms, key sizes, and above all the validity periods, because data lifetime drives priority.
  • Libraries and their versions. Which crypto library each service links, and whether it even supports the targets yet.
  • Hardware. HSMs, smart cards, TPMs, secure elements, and what they will and will not do in firmware.
  • Hardcoded constants. The algorithm OIDs, curve names, and digest choices buried in source, config templates, and deployment scripts. These are where the next migration goes to die.

A CBOM is not a one-off spreadsheet. It should be generated from automated scanning of source, binaries, certificate stores, and protocol endpoints, and kept current. An inventory that is six months stale is a historical document.

Designing for agility

With visibility in hand, the design principles are straightforward to state and disciplined to enforce.

Externalise the algorithm choice

The cardinal rule: no algorithm names, OIDs, curve identifiers, or key sizes baked into application code. They belong in configuration, validated against an allow-list, with the ability to change them through deployment rather than recompilation. A config-driven policy makes the active posture auditable and the change a reviewable artefact:

crypto_policy:
  version: 3
  # Key establishment — PQC migration is most urgent here
  key_establishment:
    default: hybrid_x25519_mlkem768
    allowed:
      - hybrid_x25519_mlkem768   # classical + PQ, defence in depth
      - mlkem768                 # pure PQ, once peers support it
      - x25519                   # legacy, sunset 2027-01-01
    deprecated:
      - rsa2048_kex

  signatures:
    default: ecdsa_p256
    allowed:
      - mldsa65                  # FIPS 204, general purpose
      - slhdsa_sha2_128s         # FIPS 205, conservative hedge
      - ecdsa_p256
    forbidden:
      - rsa_pkcs1_sha1           # never negotiate

  hashes:
    minimum: sha256
    forbidden: [md5, sha1]

  rsa:
    minimum_modulus_bits: 3072   # floor for new long-lived keys

Negotiate where the protocol allows

TLS already negotiates cipher suites and groups; that mechanism is your friend. Treat the supported-groups and signature-algorithms lists as policy-driven inputs, not constants compiled into a binary. When a peer advertises ML-KEM support, you want to use it by shipping new configuration, not new code.

Abstract the provider

Cryptographic operations should call an interface, not an implementation. PKCS#11 is the established abstraction for exactly this: your application asks the token to "sign with this key handle" and remains indifferent to whether the mechanism behind that handle is ECDSA today and ML-DSA tomorrow. The same discipline applies in software: a provider layer that exposes encapsulate, decapsulate, sign, verify by key handle, with the algorithm resolved from policy, not hardcoded at the call site.

        Application / service code
   (asks: "sign with key X", "establish key with peer")
                     |
        +------------------------------+
        |   Crypto abstraction layer   |   <- algorithm resolved
        |   sign() verify()            |      from crypto_policy,
        |   encapsulate() decapsulate()|      never hardcoded
        +------------------------------+
            |            |          |
        PKCS#11      software     remote
         (HSM)       provider     signing svc
            |            |          |
     ECDSA / ML-DSA   ML-KEM /   ML-DSA / SLH-DSA
     keys in hardware  X25519    in custody service

The point of the diagram is that swapping the bottom row (the actual algorithm) touches neither the application nor the abstraction.

Hybrid and composite certificates

During the transition we do not get to flip a switch. Peers, libraries, and hardware will support the new algorithms on wildly different timelines, and the new algorithms themselves are young enough that prudence argues against betting everything on them alone. The answer is to run two algorithms in parallel.

For key establishment this is hybrid key exchange: combine a classical mechanism (say X25519) with a PQ KEM (ML-KEM) so the session is secure if either remains unbroken. You get protection against harvest-now-decrypt-later from the PQ component and protection against an immature-PQ surprise from the classical component.

For credentials, composite certificates bind two public keys and carry two signatures, so a single credential satisfies both a classical verifier and a PQ-aware one during the long coexistence period:

Certificate
  Subject: CN=service.internal.example
  SubjectPublicKeyInfo:
    compositeKEM:
      - X25519        (classical)
      - ML-KEM-768    (FIPS 203)
  Signature:
    compositeSignature:
      - ECDSA-P256          over TBSCertificate
      - ML-DSA-65 (FIPS 204) over TBSCertificate
  Note: a verifier validates BOTH signatures; the cert is
        trusted only if both verify. Either algorithm being
        broken later does not silently downgrade trust.

The cost: size

This is where architecture, not just cryptography, gets involved. PQ keys and signatures are large compared with what we are used to. An ML-DSA-65 signature is on the order of a few kilobytes; an ML-KEM public key and ciphertext likewise dwarf a 32-byte X25519 value. Compose those with classical algorithms and a certificate that was once a couple of kilobytes can grow substantially. The architectural consequences are real:

  • Handshakes grow, sometimes spilling past the packet sizes and buffers assumed by middleboxes and embedded stacks, so expect fragmentation and amplification concerns.
  • Storage and bandwidth for certificates, chains, CRLs and logs all increase, which matters at the scale of millions of credentials.
  • Hardware such as smart cards, TPMs and older HSMs may lack the memory, firmware, or mechanisms for PQ keys at all. The CBOM should have already told you where this constraint bites.

None of this justifies delay. It does mean testing against real constraints early instead of discovering them at cut-over.

A migration strategy that survives production

I sequence these migrations the same way every time, because the order is what keeps the risk bounded.

  1. Inventory. Stand up the CBOM and keep it current. No work proceeds on a part of the estate you cannot see.
  2. Prioritise by data lifetime. Rank systems by how long their data must stay confidential. Long-confidentiality key establishment goes first, because that is where harvest-now-decrypt-later is already costing you. Signatures, whose forgery needs the quantum computer to actually exist, can follow.
  3. Pilot. Prove the new algorithms in a contained environment against real hardware, real handshake sizes, and real peers. Measure performance and failure modes before they touch production.
  4. Run hybrid. Deploy hybrid key exchange and composite certificates so you gain protection immediately while retaining interoperability with everything not yet upgraded. This is the long phase, and that is fine.
  5. Cut over. Once the ecosystem and your own dependencies support pure PQ, retire the classical component. If you externalised the policy, that is a configuration change and a re-issuance rather than an engineering effort.

Testing and governing the lifecycle

Agility you never exercise is only a claim. So algorithm rotation should be treated as something to rehearse: run negotiation downgrade tests, verify that forbidden algorithms are actually refused, and periodically practise rotating a key type in a staging estate to confirm the path still works. The crypto-policy document becomes a governed artefact: versioned, reviewed, with owners and sunset dates on every deprecated entry, and tied to the CBOM so that a change in policy maps to a known set of affected systems.

Governance also means deciding deliberately rather than drifting. Who is allowed to add an algorithm to the allow-list? What evidence is required to move something from deprecated to removed? When does a sunset date trigger enforcement? These are organisational questions, and answering them is as much a part of crypto-agility as any line of code.

The organisations that come through the post-quantum transition calmly will not be the ones who guessed the right algorithm earliest. They will be the ones who built systems where the algorithm was never the hard part to change. Build for the migration after this one, and this one becomes far more manageable. That is the case for treating agility as architecture. The next part turns to where this discipline is tested hardest: the identity of machines and IoT devices, where the constraints are tightest and the credentials most numerous.

Next: Machine & IoT Identity →