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.3.1

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.3.1
File Interpreter ABI Platform
q_armor_pqc-0.3.1-cp313-none-any.whl CPython 3.13 none any Details
q_armor_pqc-0.3.1-cp312-none-any.whl CPython 3.12 none any Details
q_armor_pqc-0.3.1-cp311-none-any.whl CPython 3.11 none any Details

Total release size: 34.0 kB

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

Download URL q_armor_pqc-0.3.1-cp313-none-any.whl
Size 11.3 kB
Tags CPython 3.13
SHA-256 checksum
How to use checksums
46b4215419b5c03fc62e20e795bf6ec3d9a77cd53c106a5f8209b9427bf1f240
BLAKE2b-256 checksum
How to use checksums
792a0a7ed8ec7391d5576d2a860be88a8d72fbb7caec1e37ad3bc9bc46540407
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 11, 2026.

Transparency log

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

Download URL q_armor_pqc-0.3.1-cp312-none-any.whl
Size 11.2 kB
Tags CPython 3.12
SHA-256 checksum
How to use checksums
73f7106a668f264480f849eff51035ef9577d517a0f7d47df5b1ce92e1f506e0
BLAKE2b-256 checksum
How to use checksums
c874546ebf6d09eb1e59f7300f86fdccf8ac6e8cfedf51904d8d9be62f3d1bbd
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 11, 2026.

Transparency log

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

Download URL q_armor_pqc-0.3.1-cp311-none-any.whl
Size 11.4 kB
Tags CPython 3.11
SHA-256 checksum
How to use checksums
bb53909b4c563225e4494cf2a621ef4532b9ab6a37b0e0868ceed84a14eae308
BLAKE2b-256 checksum
How to use checksums
9acd7bf95d594f0bd8225eea921ebe9188fe0265022bef828e4e18e0ae6305c5
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 11, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.3.1 This release

3 release files

0.3.0

3 release files

0.2.0

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