QERYX COMING SOON
OBSERVATORY

Research Messenger

protocol-spec

Cryptographic Primitives and Parameter Sets

Version
v1.1
Category
protocol-spec
Published
Last updated
Authors
QERYX Research
Primitives ML-KEM-1024 ML-DSA-87 X25519 ChaCha20-Poly1305 AES-256-GCM SHA-512 SHAKE-256 HKDF-SHA-512 Argon2id HMAC-SHA-256
What changed v1.1
  1. v1.1 §1 says where a vault’s key comes from: drawn at random on the iPhone.
  2. v1.0 First publication. The Argon2id parameters it printed as a single spec triple are superseded by the per-surface ladder the site now reads from code.
Contents
  1. §1 The master table
  2. §2 Backend pinning
  3. §3 Level 5 parameter sets
  4. §4 Context framing (FIPS 204 §5.2)
  5. §5 Labeled HKDF
  6. §6 Argon2id
  7. §7 What is deliberately absent
  8. §8 References

Every cryptographic primitive QERYX instantiates, with its parameter set, byte sizes, and the source citation that pins it. Wire-stable values are byte-locked: changing any of them is a backward-incompatible break. This chapter is the anti-drift rail for every other paper — a primitive that does not appear in the master table does not appear in QERYX.

The master table

PrimitiveStandardPublicSecretOutput
ML-KEM-1024FIPS 203 (2024)1568 B3168 B32 B shared secret; 1568 B ciphertext, implicit rejection on every decapsulation
ML-DSA-87FIPS 204 (2024)2592 B4896 B4627 B signature; hedged signing, a registered context on every slot
X25519RFC 774832 B32 B32 B
ChaCha20-Poly1305RFC 8439—32 B key12 B nonce, 16 B tag
AES-256-GCM (CSfC outer)FIPS 197 + SP 800-38D—32 B key12 B nonce, 16 B tag
SHA-512FIPS 180-4——64 B
SHAKE-256 / SHA3-256FIPS 202——extendable
HKDF-SHA-512RFC 5869——PRK 64 B, ≤255×64 B
Argon2idRFC 9106—32 B random salt32 B
HMAC-SHA-256RFC 2104——16 B truncated token

Source citations for every row live in docs/SPEC/01-primitives.md §2.1, each pointing into crypto-core/src/.

Asymmetric keys are generated by the FIPS 203 and FIPS 204 key-generation algorithms from the platform random number generator; symmetric keys are drawn from the same generator or derived through HKDF-SHA-512 from established shared secrets, and the iPhone vault's own key is drawn from the generator. In the iPhone app, Argon2id derives the keys from a vault's PIN and from a local backup's passphrase. The vault's 24 recovery words are drawn, not chosen: they carry 256 bits from the same generator, and PBKDF2-HMAC-SHA-256 at 100,000 iterations turns them into the key that seals a copy of the vault key for recovery.

Backend pinning

Every ML-KEM and ML-DSA operation dispatches to an audited library whose validated configuration is not the one QERYX builds link. QERYX's own module boundary is not CMVP-certified, and CAVP validation of the implementation is a laboratory step we have not taken. Two unmaintained third-party PQ crates were removed in the 2026-04 migration for concrete reasons:

  • The KyberSlash timing attacks (IACR ePrint 2024/1049; TCHES 2025) recover ML-KEM private keys in minutes on unpatched reference implementations — one removed crate tracked reference C that was never patched past the 2023-12-29 disclosure.
  • The other implemented a round-3 signature variant rather than the final FIPS 204 ML-DSA parameterization.
  • The pinned backend's ML-KEM kernels are audited secret-independent, and its ML-DSA signs hedged by default per FIPS 204 Appendix D.

Level 5 parameter sets

Both lattice primitives run at NIST security category 5 — the only category CNSA 2.0 accepts for National Security Systems.

ParameterML-KEM-1024ML-DSA-87
Ring degree n256256
Modulus q33298,380,417
Rankk = 4(k, l) = 8 × 7
Classical security256 bit256 bit
Quantum security128 bit192 bit
NIST OID2.16.840.1.101.3.4.4.32.16.840.1.101.3.4.3.19

Deterministic ML-DSA signing is never used on mobile: FIPS 204 warns the deterministic variant is vulnerable to fault-injection differential attacks. Every signature draws fresh 256-bit randomness.

Context framing — FIPS 204 §5.2, load-bearing

Every ML-DSA-87 signature on the message, handshake, group-key, call, receipt and manifest paths carries an explicit FIPS 204 §5.2 context string over len(ctx) ‖ ctx ‖ M, and every byte of the context is inside the signed pre-image, so a signature minted for one slot fails verification in another. The signer in code wraps that structure a second time:

pre-image = 0x00 || 0x00 || (0x00 || len(ctx) || ctx || M)   // in code: the §5.2 structure wrapped once more

That is self-consistent and domain-separated but not byte-identical to a single-framing FIPS 204 verifier; the migration to single framing is staged behind a dual-accept window that is already open on the verify side. A signature computed under one non-empty context deterministically fails verification under another. Two paths still verify without a context — the relay's control-frame check and the legacy first-message rung — and while the dual-accept window is open a context-bound signature is also a valid context-free signature over its own framed bytes; both are named in Known Limitations and close with the framing flip. Reserved context strings cover the protocol slots: message authentication, handshake transcript, device pairing, the offline release manifest and the witness-quorum attestation, both ESv1 legs, call initiation, the pre-key handshake, KTS tree heads and leaves, FSOR destruction roots, destruction proofs, and the three slots reserved for the QLEAP directory. The full table with citations is in the source chapter.

Labeled HKDF

labeled_hkdf(IKM, label, context, len):
    info = "QERYX-v1-" || label || context
    return HKDF-SHA-512(IKM, salt = None, info, len)

The "QERYX-v1-" prefix is wire-stable; bumping it is a session-state break. A boundary-collision-safe variant (labeled_hkdf_strict) injects a reserved delimiter byte between label and context for new protocol slots; existing slots stay byte-locked for forward compatibility — an external review finding (F-005) closed with exactly this split. The full label catalog is printed in the Reviewer FAQ.

Argon2id

SurfaceMemoryPassesLanesClassSource
Vault (in-app)m ≥ 128 MiBt ≥ 3p = 4enforced floor — device-calibrated upwardcrypto-core/src/argon2_password.rs
Local backup (Secret Phrase)m = 256 MiBt = 4p = 2enforced constantArgon2idLocalBackupService.swift
Relay sign-in hashm = 64 MiBt = 3p = 4enforced constant, rolling rehashbackend/src/services/mod.rs
Secure Enclave wrapper (software custody envelope)m = 64 MiBt = 3p = 2enforced constant — the weakest rung in codeSecureEnclaveKeyWrapper.swift

Every rung is Argon2id (RFC 9106) with a 32-byte random salt and a 32-byte output. The vault calibrates itself to the device against a time budget and the calibrator clamps its result up to the BALANCED profile, so a manipulated clock can only raise the cost. Every number on this site is read from those constants at build time and names its surface; the spec constant is never quoted as a value in code.

What is deliberately absent

Each absence below is a decision with a reason attached. Nothing here was left out because including it was inconvenient.

  • No ECDSA or RSA classical signatures anywhere in the message path. CNSA 2.0 requires ML-DSA-87 for software and firmware signing by 2027; QERYX is already there.
  • No ML-DSA-65 fallback. Removed 2026-04-20 per an external audit — there is no negotiation variable to downgrade.
  • No Curve25519 EdDSA in the identity path — X25519 is key exchange only; identity signatures are ML-DSA-87.
  • No SHA-1, no MD5, anywhere in the dependency tree.

References

  1. QERYX Protocol Specification §2 — docs/SPEC/01-primitives.md, snapshot 2026-05-01.
  2. NIST FIPS 203 (ML-KEM) and FIPS 204 (ML-DSA), 2024.
  3. RFC 5869 (HKDF), RFC 7748 (X25519), RFC 8439 (ChaCha20-Poly1305), RFC 9106 (Argon2).
  4. KyberSlash: division timing attacks on ML-KEM reference code — IACR ePrint 2024/1049.
  5. CNSA 2.0 and FIPS Conformance Posture — the per-line conformance mapping for this table.