Skip to main content

q-armor-pqc

ML-DSA-65 (FIPS 204) for QArmor, and an interim package by design: it exists to be deleted.

PyPI Python Licence FIPS 204

A cryptographic primitive with two implementations has two behaviours, and you find out which one you were running during the incident. This package exists so that QArmor has exactly one, until the place it belongs can hold it.

iden-q-post-quantum is the L2 generator's emission (iqcgen) and the only place in the estate where a cryptographic primitive has one source and one KAT gate. It carries ML-KEM-768 and ML-DSA-44, in Python and in TypeScript. The DVN's on-chain attestations sign with ML-DSA-65 (SAD §6.4.2), and no language emits that primitive. Per ADR-22 it is a spec missing from the generator (SAD D-7), not a second library, and the generator is private. While that gate stays closed, this package is where ML-DSA-65 lives.

When the emission publishes ML-DSA-65, this package is deleted. It is not versioned in parallel, not migrated, not maintained: q_armor_lib and q_armor_chain change the import to the emission and packages/q-armor-pqc/ disappears from the workspace. It is published to PyPI only because q-armor-lib pins it, and a published library cannot depend on an editable.

Install

pip install q-armor-pqc            # ML-DSA-65 with a development Ed25519 fallback
pip install 'q-armor-pqc[pqc]'     # + liboqs-python: real ML-DSA-65

Read this before you deploy it. QARMOR_REQUIRE_PQC=1 demands liboqs and fails if it is absent. Without that variable, ML-DSA-65 falls back to Ed25519, which is classical, and says so with a RuntimeWarning at import. It is the only live exception to "NIST algorithms only" (CLAUDE.md), and it is stated rather than hidden. The KEM has no fallback.

What is here, and what is delegated

  • MLDSA65: liboqs, or Ed25519 in development. The only thing that justifies the package.
  • MLKEM768: delegates to the emission. ML-KEM-768 has not been implemented here since 2026-08-23: a second implementation over liboqs meant the same primitive on two backends, one inside the KAT gate and one outside (ADR-13, the SAD's S-6 scenario). The wrapper stays because encapsulate never returned the raw secret but HKDF-SHA3-256(ss), while the emission derives with HKDF-SHA256: changing the import alone would have changed the AES key, a cryptographic change dressed up as a refactor. The emission's keygen is deterministic from a seed, and the seed comes from secrets.
  • aead_encrypt / aead_decrypt: AES-256-GCM from cryptography.

The KEM's X25519 fallback is gone, and that went with the delegation: the emission is pure Python and a hard dependency, so the "liboqs is absent" case no longer exists for the KEM.

About the name

In this estate "crypto" means blockchain, not cryptography: quantum-armor-crypto is the DVN (SAD §4.2, §6.4, ADR-18). And q-crypto-* is the prefix of the L2 generator (q-crypto-gen) and of what it emits. This distribution's previous name, q-crypto-py, broke both rules and was also the one the SAD used for the Python emission; the directory packages/q-armor-crypto/ inverted ADR-18 in the tree itself. Both were renamed on 2026-09-02, before the first publication, so that name would never reach an index. pqc is what it contains; armor, who it belongs to.

A dependency on a private module, said out loud

pqc_engine imports iden_q_post_quantum._runtime, not the emission's public API. Checked against iden-q-post-quantum 1.2.0: what is public is seal/unseal (a hybrid X25519 and ML-KEM-768 envelope), encrypt/decrypt by passphrase, derive_recipient_keys and the ML-DSA-44 signature. There is no public raw KEM: mlkem768_keygen, encapsulate and decapsulate live only in _runtime. QArmor's session needs the raw KEM to derive its own key, so this dependency contradicts "consumers depend on published outputs" (ADR-22) and is recorded as what it is: a gap in the generator with the same shape as D-7, a missing public KEM API spec, to be closed upstream rather than wrapped here.

Tests

tests/ carries the package's own suite: that the KEM's AES key is HKDF-SHA3-256 of the emission's secret (and not the raw secret, nor HKDF-SHA256), that encapsulate and decapsulate converge, that a signature verifies only its own message, and that AES-GCM rejects a tampered tag.

What is still open is an ML-DSA-65 KAT against the FIPS 204 vectors: with QARMOR_REQUIRE_PQC undefined the signature runs over Ed25519, and a test that has only passed there has not seen ML-DSA-65. It is exercised as well from q-armor-lib's session and proofs tests, from the DVN worker's, and from api/.

The QArmor family

Five packages, one version, published together from a single tag.

Package What it is
q-armor-lib Detection, scoring and the control-plane client
q-armor-cli q-armor, the operator's command line
q-armor-proxy Enterprise runtime: protection proxy, firewall, SIEM webhook
q-armor-chain DVN worker and QArmorDVN.sol
q-armor-pqc This one, and it is interim

Next

idenq.io

Metadata

Release files for q-armor-pqc 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for q-armor-pqc 0.2.0
File Interpreter ABI Platform
q_armor_pqc-0.2.0-cp313-none-any.whl CPython 3.13 none any Details
q_armor_pqc-0.2.0-cp312-none-any.whl CPython 3.12 none any Details
q_armor_pqc-0.2.0-cp311-none-any.whl CPython 3.11 none any Details

Total release size: 34.0 kB

Release files / q_armor_pqc-0.2.0-cp313-none-any.whl

Download URL q_armor_pqc-0.2.0-cp313-none-any.whl
Size 11.3 kB
Tags CPython 3.13
SHA-256 checksum
How to use checksums
a700c7626b7d7433ee8c65844ec5b39d87c5434c2392a138b0709936a177dab6
BLAKE2b-256 checksum
How to use checksums
643241fc5b0292ccbf1a4ef729439b0cf52c2d39c8958fe94678c40cf8cb9b1d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.

Transparency log

Release files / q_armor_pqc-0.2.0-cp312-none-any.whl

Download URL q_armor_pqc-0.2.0-cp312-none-any.whl
Size 11.2 kB
Tags CPython 3.12
SHA-256 checksum
How to use checksums
f5b711ee1c51c443fcf3b8a29c9f7317333866ae9d83b4cc01297c4a7c094f74
BLAKE2b-256 checksum
How to use checksums
97c93a532461a10bd8c26b3bbf8003fb6a206a9d7d012e334508c536973d9fff
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.

Transparency log

Release files / q_armor_pqc-0.2.0-cp311-none-any.whl

Download URL q_armor_pqc-0.2.0-cp311-none-any.whl
Size 11.4 kB
Tags CPython 3.11
SHA-256 checksum
How to use checksums
d8e674241612a71be93582ff6060eb7d6396e370326a6757176d3d744b8c564b
BLAKE2b-256 checksum
How to use checksums
67071482a5a67c61845600f1c89a99fe37a12c3f668028085d07c9651df03fa6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.

Transparency log

Release history Release notifications | RSS feed

0.3.1

3 release files

0.3.0

3 release files

This release

0.2.0 This release

3 release files

0.1.2

3 release files

0.1.1

3 release files

0.1.0

3 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page