DEV Community

Cover image for A Developer's Guide to Post-Quantum Migration
Vincent Wang
Vincent Wang

Posted on • Originally published at qpher.ai

A Developer's Guide to Post-Quantum Migration

You probably have RSA or ECDSA keys in your codebase right now. Maybe in your JWT auth. Maybe in your TLS config. Maybe in that encryption module someone wrote three years ago.

Here's the thing: NIST is planning to deprecate RSA by 2030 and disallow it by 2035 (NIST IR 8547). Not because RSA is broken today — but because quantum computers will break it, and that timeline is closer than most developers realize.

This isn't a theoretical threat. It has a name: Harvest Now, Decrypt Later (HNDL).

What is Harvest Now, Decrypt Later?

The concept is simple:

  1. Today: Adversaries intercept your encrypted traffic (TLS sessions, API calls, database backups)
  2. Store: They stockpile the encrypted data — storage is cheap
  3. Future: When quantum computers can run Shor's algorithm at scale, they decrypt everything retroactively

The NSA has confirmed that nation-state actors are doing this right now. If your encrypted data has a shelf life longer than ~10 years, it's already at risk.

This matters for every developer, not just cryptographers. If you're writing code that uses RSA, ECDSA, DH, or ECDH — you're writing code with an expiration date.

The New Standards: What Replaces RSA?

In August 2024, NIST finalized three post-quantum cryptographic standards:

Old (Quantum-Vulnerable) New (Quantum-Safe) NIST Standard Use Case
RSA, ECDH, DH ML-KEM-768 (Kyber) FIPS 203 Key encapsulation / encryption
RSA, ECDSA ML-DSA-65 (Dilithium) FIPS 204 Digital signatures
SLH-DSA (SPHINCS+) FIPS 205 Stateless hash-based signatures

The migration timeline from NSA CNSA 2.0:

  • 2027: Prefer PQC for new systems
  • 2030: PQC required for all new systems
  • 2035: Full migration complete — classical crypto disallowed

Step 1: Find Your Quantum-Vulnerable Crypto

You can't migrate what you can't find. The first step is a cryptographic inventory — scanning your codebase for every quantum-vulnerable algorithm.

I built an open-source tool for this: pqc-check

npx pqc-check ./my-project
Enter fullscreen mode Exit fullscreen mode

It scans 9 languages (Python, JS/TS, Go, Java, Rust, C/C++, Ruby, PHP) plus config files, and classifies findings by risk:

  • HIGH: Key exchange & encryption (RSA, DH, ECDH) — vulnerable to HNDL today
  • MEDIUM: Signatures (ECDSA, Ed25519) — forgery risk when quantum computers arrive
  • LOW: Informational (AES, SHA — already quantum-resistant)

Example output:

HIGH  src/auth/jwt.py:42
      RSA-2048 key generation (PKCS#1)
      → Migrate to ML-DSA-65 (FIPS 204)

HIGH  src/api/encryption.ts:18
      ECDH key agreement (P-256)
      → Migrate to ML-KEM-768 (FIPS 203)

MEDIUM  src/utils/signing.go:67
        ECDSA P-256 signature
        → Migrate to ML-DSA-65 (FIPS 204)
Enter fullscreen mode Exit fullscreen mode

For CI/CD integration, use SARIF output:

# .github/workflows/pqc-scan.yml
name: PQC Vulnerability Scan
on: [push, pull_request]
jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npx pqc-check . --format sarif > pqc-results.sarif
      - uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: pqc-results.sarif
Enter fullscreen mode Exit fullscreen mode

This puts quantum-vulnerability findings directly in your PR's Security tab.

Step 2: Understand What to Prioritize

Not all findings are equally urgent. Prioritize by:

Priority 1 — Data at rest with long retention:
If you're encrypting data that will be stored for 10+ years (financial records, healthcare data, legal documents), migrate these to PQC first. This data is already in the HNDL danger zone.

Priority 2 — Key exchange in network protocols:
TLS, VPN, and API encryption using RSA/ECDH key exchange. Intercepted traffic is being stored by adversaries now.

Priority 3 — Digital signatures:
ECDSA and RSA signatures. These are only at risk when quantum computers actually exist — not from retroactive attacks. Still important, but lower urgency.

Not urgent — Symmetric crypto:
AES-256, SHA-256, HMAC — these are already quantum-resistant (Grover's algorithm only gives a quadratic speedup, so AES-256 effectively becomes AES-128, which is still secure). You'll see these as LOW findings in pqc-check.

Step 3: The Hybrid Approach (Start Here)

You don't need to rip out RSA overnight. The recommended migration strategy is hybrid cryptography — running classical + post-quantum algorithms simultaneously.

If the classical algorithm is broken, PQC protects you. If PQC has an undiscovered weakness, the classical algorithm is your safety net. You get the best of both worlds.

Real-world examples that are already shipping:

  • Chrome: X25519+ML-KEM-768 hybrid key exchange in TLS (default since Chrome 131, Nov 2024)
  • Firefox: X25519+ML-KEM-768 hybrid key exchange (default since Firefox 135, Feb 2025)
  • Signal: PQXDH protocol using ML-KEM-1024 for post-quantum key agreement
  • Apple iMessage: PQ3 protocol using ML-KEM-1024 (device keys) and ML-KEM-768 (ratchet keys)

Code Example: Hybrid Encryption with Qpher SDK

If you want to try PQC encryption without managing key infrastructure yourself:

Python:

from qpher import Qpher

client = Qpher(api_key="qph_live_...")

# Encrypt with ML-KEM-768 (FIPS 203)
result = client.kem.encrypt(
    plaintext=b"sensitive financial record",
    key_version=1,
)
# result.ciphertext is quantum-safe

# Decrypt
decrypted = client.kem.decrypt(
    ciphertext=result.ciphertext,
    key_version=result.key_version,
)
Enter fullscreen mode Exit fullscreen mode

Node.js:

import { Qpher } from '@qpher/sdk';

const client = new Qpher({ apiKey: 'qph_live_...' });

// Sign with ML-DSA-65 (FIPS 204)
const signed = await client.signatures.sign({
  message: Buffer.from('Invoice #12345'),
  keyVersion: 1,
});

// Verify
const result = await client.signatures.verify({
  message: Buffer.from('Invoice #12345'),
  signature: signed.signature,
  keyVersion: signed.keyVersion,
});
// result.valid === true
Enter fullscreen mode Exit fullscreen mode

SDKs available for Python (pip install qpher), Node.js (npm install @qpher/sdk), and Go.

Step 4: Build a Migration Roadmap

Here's a realistic 5-step framework:

1. Inventory (This Week)

Run npx pqc-check on every repo. Export JSON results for tracking.

2. Assess (This Month)

Map each finding to data retention periods. Anything encrypting data stored > 10 years = Priority 1.

3. Plan (This Quarter)

Choose your hybrid strategy. Most teams should start with hybrid mode (classical + PQC) rather than pure PQC.

4. Pilot (Next Quarter)

Pick one non-critical system — internal API encryption, backup encryption, document signing — and deploy PQC there. Measure performance impact.

5. Migrate (6-18 Months)

Roll out to production systems. Core encryption, customer data at rest, external API endpoints.

Common Questions

Q: Is this really urgent? Quantum computers aren't here yet.
The threat is HNDL — data intercepted today, decrypted later. If your data has a 10+ year shelf life, the urgency is now, not when quantum computers arrive.

Q: What about performance?
ML-KEM-768 encapsulation takes under 0.1ms natively (~0.02ms with AVX2). ML-DSA-65 signing takes ~0.2ms natively (~1ms via Python FFI). For most applications, the overhead is negligible. The bigger challenge is larger key and ciphertext sizes (ML-KEM-768 public keys are ~1.2KB vs. 32 bytes for X25519).

Q: Is AES-256 quantum-vulnerable?
No. AES is symmetric cryptography. Grover's algorithm reduces its effective security from 256 bits to 128 bits — still very secure. Focus your migration on public-key crypto: RSA, ECDSA, ECDH, DH.

Q: What if the new PQC algorithms have undiscovered vulnerabilities?
This is why the hybrid approach exists. If ML-KEM is somehow broken, your classical X25519 layer still protects you. Belt and suspenders.

TL;DR

  1. Run npx pqc-check ./your-project to find all quantum-vulnerable crypto
  2. Prioritize long-lived encrypted data and key exchange over signatures
  3. Start hybrid — don't wait for pure PQC; use classical + PQC together
  4. Pilot on a non-critical system this quarter
  5. Track the CNSA 2.0 timeline: 2030 (PQC required) → 2035 (classical disallowed)

The migration will take years. The scan takes 30 seconds. Start there.


pqc-check is MIT licensed and free. Qpher provides managed PQC key infrastructure if you don't want to run your own. Both built by me — happy to answer questions in the comments.

Top comments (0)