Back to the courseDownload Markdown

Step-by-step — PQC · Hybrid Signing

Lab 5 enables a strict verifier policy locally. In a deployed federation, a hub can pin a peer’s advertised PQ key and reject a later downgrade for that peer. Requiring PQ from every peer is a separate opt-in setting, AIMARKET_PQC_REQUIRE=1. This policy covers off-chain signatures. Base escrow transactions still use the EVM signature scheme.

Audience: engineers migrating signing to post-quantum without breaking today's federation. Languages: COURSE_LANG=en|ru|es|fr|zh · catalogs in i18n/ · this guide in English. Other languages: RU · ES · FR · ZH


Why this course

Signatures are statements about the past. A receipt disputed years from now must already resist a quantum adversary. Replacing Ed25519 with ML-DSA alone breaks interoperability today (fail-closed verifiers, young libraries). The AIMarket hub ships hybrid: Ed25519 + ML-DSA-65 over the same canonical — see the LIVE envelope at https://modelmarket.dev/.well-known/ai-market.json (pq_algorithm=ml-dsa-65).

This course teaches: why hybrid, dual-orbit identity, sign a receipt, verify offline, and refuse single-orbit (phase 3). It never presents SIM crypto as LIVE.


Setup (10 minutes)

git clone https://github.com/alexar76/aimarket-courses.git
cd aimarket-courses/pqc-hybrid-signing-course
pip install -e ".[dev]"            # cryptography>=42 required
pip install -e ".[pqc,dev]"        # optional: dilithium-py for local ML-DSA
pytest -q

Without dilithium-py you can still verify Ed25519 and inspect LIVE hybrid fields — PQ sign is labeled skipped, never faked.

export COURSE_LANG=ru   # or es|fr|zh
python labs/lab01_why_hybrid.py
PQC_COURSE_FETCH_LIVE=1 python labs/lab01_why_hybrid.py   # optional LIVE

Module M1 — Why hybrid

Lab: labs/lab01_why_hybrid.py · ~15 min

  1. Read the four bullets: classical alone, PQ alone, hybrid, downgrade.
  2. Confirm envelope_is_hybrid is false for classical-only shapes.
  3. Optional: PQC_COURSE_FETCH_LIVE=1 — inspect LIVE hub signature; classical verified offline; PQ verified only if dilithium is installed.

Exercise: assert why_hybrid_brief keys; classical shape is not hybrid.


Module M2 — Key identity

Lab: labs/lab02_key_identity.py · ~15 min

  1. HybridSigner(enable_pq=True) prints dual public keys (or labeled PQ skip).
  2. Remember: pin both keys out-of-band. A self-asserted PQ key is worthless against a broken classical key.

Exercise: assert classical key present; PQ key or pq_skipped.


Module M3 — Sign a receipt

Lab: labs/lab03_sign_receipt.py · ~20 min

  1. Sign a capability receipt over receipt_canonical.
  2. Inspect algorithm / value and optional pq_*.
  3. If dilithium missing: message says PQ skipped — classical signature is still real.

Exercise: sign_receipt; assert Ed25519 fields; hybrid if PQ available.


Module M4 — Verify offline

Lab: labs/lab04_verify_offline.py · ~20 min

  1. Verify your signed receipt with pinned keys — no hub callback.
  2. Wrong message → classical fails.
  3. Optional LIVE fetch verifies classical on the hub envelope offline.

Exercise: offline verify; never claim PQ success without dilithium.


Module M5 — Capstone: hybrid gate

Lab: labs/lab05_hybrid_gate_capstone.py · ~25 min

  1. strip_pq simulates a downgrade attack.
  2. refuse_single_orbit must refuse classical-only even if Ed25519 verifies.
  3. require_pq=False still accepts classical (migration phase).
  4. Full hybrid accepted only when ML-DSA is real locally.

Exercise: implement the refuse path; accept hybrid only when PQ is real.


Exercises & certificate

# fill # YOUR CODE HERE in courselib/exercises.py (see exercise_solutions.py)
python labs/run_exercises.py
python labs/run_exercises.py --certificate "Your Name"

Browser checkboxes do not issue certificates.


Self-check


Troubleshooting

Symptom Fix
cryptography ImportError pip install -e ".[dev]"
PQ always skipped pip install -e ".[pqc]"
Live fetch fails offline OK — tests skip; or set PQC_COURSE_WELL_KNOWN
Exercises all fail fill stubs; CI checks exercise_solutions