@iden-q/post-quantum
v1.2.0
Published
IdenQ post-quantum cryptography (cipher_payload v2, login_envelope v1, mldsa_signature v1) - generated from the IdenQ Crypto IR
Readme
@iden-q/post-quantum (TypeScript) — generated by iqcgen 1.2.0
Do not edit these sources. They are compiled from the IdenQ Crypto IR in
specs/ and regenerated with iqcgen generate.
Requires: Node 20+ (LTS 22 and 24 tested); browsers from Chrome 111, Firefox 113, Safari 16.4, Edge 111.
npm install && npm testRuns in the browser and in Node 20+: the only platform APIs used are
crypto.getRandomValues and TextEncoder/TextDecoder. Base64 is implemented in
runtime.ts, so nothing depends on btoa or Buffer.
Passphrase-rooted hybrid post-quantum secret encryption (cipher_payload v2)
A passphrase is stretched with Argon2id into a master key; an ML-KEM-768 keypair is derived deterministically from that master key (so nothing has to be stored or synced); encapsulating to it yields a post-quantum shared secret which is mixed with a symmetric KEK to wrap a random per-secret data key. An attacker needs the passphrase — breaking ML-KEM alone, or recording traffic today to decrypt after a quantum computer exists, does not help.
import { encrypt, decrypt } from '@iden-q/post-quantum';async encrypt(plaintext: string, passphrase: string)— Encrypt a secret under a passphrase.async decrypt(payload: struct, passphrase: string)— Decrypt a payload with the passphrase that produced it.
cipherPayloadToJson() produces exactly the wire object the IdenQ services
expect (base64url); cipherPayloadFromJson() validates one.
Hybrid X25519 + ML-KEM-768 public-key envelope (login_envelope v1)
Seals a short credential to a recipient's static hybrid public key. Classical and post- quantum defence in depth: an interceptor who strips TLS must break BOTH X25519 and ML- KEM-768 to recover the key-encryption key, and neither alone is enough. The recipient opens it with the matching private keys.
import { seal, unseal, deriveRecipientKeys } from '@iden-q/post-quantum';seal(plaintext: bytes, recipientXPk: bytes, recipientMlKemEk: bytes)— Seal a plaintext to a recipient's static hybrid public key.unseal(envelope: struct, xSk: bytes, mlKemDk: bytes)— Open an envelope with the recipient's private keys.deriveRecipientKeys(seed: bytes)— Derive a recipient key set deterministically from a 96-byte seed.
envelopeToJson() produces exactly the wire object the IdenQ services
expect (base64); envelopeFromJson() validates one.
ML-DSA-44 detached signature (mldsa_signature v1)
Post-quantum digital signatures (FIPS 204, ML-DSA-44). A signer derives a key pair
deterministically from a seed and signs a message; a verifier checks the signature
against the pinned public key and fails closed on anything that does not verify. Pure
ML-DSA with an empty context string, so the signing input is the message itself — the
shape a JWS ML-DSA-44 assertion needs.
import { deriveSigningKeys, signingKeysFromPrivateJwk, sign, verify } from '@iden-q/post-quantum';deriveSigningKeys(seed: bytes)— Derive a signing key pair deterministically from a 32-byte seed.signingKeysFromPrivateJwk(jwk: struct)— Derive the signing key pair from a private AKP JWK.sign(sk: bytes, message: bytes)— Sign a message with a signing key.verify(signed: struct, pk: bytes)— Verify a signed message against a pinned verification key.
signedMessageToJson() produces exactly the wire object the IdenQ services
expect (base64); signedMessageFromJson() validates one.
Licence
IdenQ Proprietary Licence. See LICENSE — this software is licensed, not sold.
Third-party components keep their own terms; see THIRD-PARTY-NOTICES.md.
