All projects

Open source

Post-quantum fixes in public-sector code

Three pull requests to open-source projects of the Ministry of VWS, the City of Amsterdam and the Fundament community. Each one started as a PQNavigator finding and ended as a change that is safe to merge today.

The problem

A scan report full of "quantum-vulnerable" findings is easy to produce and easy to ignore. Maintainers need a change that fixes something real, does not break production, and explains itself. I wanted to show that post-quantum migration can start with small, reviewable steps.

Three fixes, three patterns

  • Make the algorithm configurable (VWS)

    A proxy signed its login JWT with a hardcoded RS256 constant. I made the algorithm configurable, defaulting to ML-DSA-65 (FIPS 204) with an automatic RS256 fallback when no post-quantum key is configured. Production keeps working unchanged until the keys are there.

  • Shorten the lifetime when you cannot switch yet (Fundament)

    A Kubernetes operator created an RSA-4096 CA valid for 10 years. cert-manager cannot issue ML-DSA certificates yet, so switching was impossible. Instead I cut the lifetime to 3 years with a 90-day renewal window, which limits how long anything it signs stays vulnerable.

  • Protect data that must stay secret for years (Amsterdam)

    A proxy to the national population register handles citizen service numbers. I added opt-in hybrid post-quantum TLS (X25519MLKEM768) against “harvest now, decrypt later”, and upgraded stored BSN encryption from Fernet (AES-128) to AES-256-GCM.

Decisions and trade-offs

Every change is opt-in or has a fallback. A maintainer can merge it without changing production behaviour, then switch it on when they are ready. That matters more than being cryptographically perfect.

I measured instead of guessing. An ML-DSA-65 signature makes the JWT grow from 658 bytes to 4,733 bytes, which is fine for a server-to-server call but worth knowing. For the CA, I checked the new lifetime against Mosca’s inequality (X + Y < Z) and wrote a design record on the path to a real ML-DSA CA.

Tests prove it works. The TLS change comes with a real loopback handshake test, so the new setting is shown to do something, not just to be accepted by the config parser.

Result

Three pull requests, 432 lines added across 16 files, each backed by the AIVD/CWI/TNO PQC Migration Handbook. They are open for review; the status on this site updates itself from GitHub.

The pull requests

joey.oosenbrug@gmail.com