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

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

q_armor_pqc-0.1.2-cp313-none-any.whl (11.3 kB view details)

Uploaded CPython 3.13

q_armor_pqc-0.1.2-cp312-none-any.whl (11.3 kB view details)

Uploaded CPython 3.12

q_armor_pqc-0.1.2-cp311-none-any.whl (11.4 kB view details)

Uploaded CPython 3.11

File details

Details for the file q_armor_pqc-0.1.2-cp313-none-any.whl.

File metadata

  • Download URL: q_armor_pqc-0.1.2-cp313-none-any.whl
  • Upload date:
  • Size: 11.3 kB
  • Tags: CPython 3.13
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for q_armor_pqc-0.1.2-cp313-none-any.whl
Algorithm Hash digest
SHA256 49621c4c3be2fdd7b267ba2b851831411ae7bb9c252483c0b8e7255f2293690a
MD5 9bc86f2b65893c36995bd8405840d807
BLAKE2b-256 1dcbba2e6e9312fea618bd07caf3aeef70a43ed5bbf3acaf889b51b5371f8a9b

See more details on using hashes here.

Provenance

The following attestation bundles were made for q_armor_pqc-0.1.2-cp313-none-any.whl:

Publisher: release.yml on iden-q/iden-q-quantum-armor

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file q_armor_pqc-0.1.2-cp312-none-any.whl.

File metadata

  • Download URL: q_armor_pqc-0.1.2-cp312-none-any.whl
  • Upload date:
  • Size: 11.3 kB
  • Tags: CPython 3.12
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for q_armor_pqc-0.1.2-cp312-none-any.whl
Algorithm Hash digest
SHA256 8fcf799811b5ed73468a139eaa2d371102c5333091d62fb181e285b90bb5c025
MD5 0e473318db2365b18fc360f4f92c6c38
BLAKE2b-256 51b7ddc44137bc682440ad85ca4b5ced6cf5bcce148773c41a5db34958d9ecee

See more details on using hashes here.

Provenance

The following attestation bundles were made for q_armor_pqc-0.1.2-cp312-none-any.whl:

Publisher: release.yml on iden-q/iden-q-quantum-armor

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file q_armor_pqc-0.1.2-cp311-none-any.whl.

File metadata

  • Download URL: q_armor_pqc-0.1.2-cp311-none-any.whl
  • Upload date:
  • Size: 11.4 kB
  • Tags: CPython 3.11
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for q_armor_pqc-0.1.2-cp311-none-any.whl
Algorithm Hash digest
SHA256 6981188d21c8a953b801c1af8e19768fc4e5b874c4396a13548c4fe1357e96ad
MD5 d81bbe0e381063c6f0948fd944d6c940
BLAKE2b-256 21e09fa3472478d82930d9dfaa7613401d69124b6021179f191645c7ad9a0493

See more details on using hashes here.

Provenance

The following attestation bundles were made for q_armor_pqc-0.1.2-cp311-none-any.whl:

Publisher: release.yml on iden-q/iden-q-quantum-armor

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.2 This release

3 files

0.1.1

3 files

0.1.0

3 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