Package Exports
- @maatara/core-pqc
Readme
Ma'atara Core PQC Toolkit
A portable, audited Post-Quantum Cryptography toolkit for browser and Node.js environments.
Features
Ma'atara Core PQC Toolkit
A portable, audited Post-Quantum Cryptography toolkit for browser and Node.js. Includes deterministic helpers for governance multisig and NFT/art token flows.
Features
- Kyber ML-KEM-768 (key encapsulation)
- Dilithium2 (sign/verify)
- HKDF-SHA256 (key derivation)
- AES-256-GCM (AEAD)
- Base64url helpers and constant‑time compare
- Deterministic preimage builders (JCS) for governance, mint, transfer, and anchor
- Royalty validation and multisig attestation verification
Install
npm install @maatara/core-pqcInitialize WASM once on startup:
import { initWasm } from '@maatara/core-pqc';
await initWasm();Core PQC usage
import {
kyberKeygen, kyberEncaps, kyberDecaps,
dilithiumKeygen, dilithiumSign, dilithiumVerify,
hkdfSha256, aesGcmWrap, aesGcmUnwrap, b64uEncode
} from '@maatara/core-pqc';
await initWasm();
// Kyber
const { public_b64u, secret_b64u } = await kyberKeygen();
const { kem_ct_b64u, shared_b64u } = await kyberEncaps(public_b64u);
const { shared_b64u: shared2 } = await kyberDecaps(secret_b64u, kem_ct_b64u);
// Dilithium
const signKeys = await dilithiumKeygen();
const msg = b64uEncode(new TextEncoder().encode('hello pqc'));
const sig = await dilithiumSign(msg, signKeys.secret_b64u);
const ok = await dilithiumVerify(msg, sig.signature_b64u, signKeys.public_b64u);Deterministic helpers (multisig and NFT)
All helpers return canonical JSON and a base64url message suitable for signing with Dilithium2.
import {
jcsCanonicalize,
buildPolicyPreimage,
buildMintPreimage,
buildTransferPreimage,
buildAnchorPreimage,
validateRoyalty,
verifyAttestations,
dilithiumSign
} from '@maatara/core-pqc';
// 1) Governance policy (multisig)
const policy = { version: 'v1', threshold: 2, signers: [{ id: 'a', publicKeyB64u: '...' }, { id: 'b', publicKeyB64u: '...' }] };
const { canonical: govCanon, msg_b64u: govMsg } = await buildPolicyPreimage(policy);
const att = await dilithiumSign(govMsg!, signerSecret);
// 2) Mint preimage (royalty optional)
const header = { createdAt: Date.now(), royalty: { receiver: '0xabc...', bps: 500 } };
const asset = { id: 'uuid', sha256: '...', mediaType: 'image/png' };
if (!await validateRoyalty(header.royalty.receiver, header.royalty.bps)) throw new Error('Bad royalty');
const { msg_b64u: mintMsg } = await buildMintPreimage(header, asset);
const mintSig = await dilithiumSign(mintMsg!, signerSecret);
// 3) Transfer preimage
const { msg_b64u: xferMsg } = await buildTransferPreimage({ assetId: 'uuid', to: 'did🔑...' });
const xferSig = await dilithiumSign(xferMsg!, signerSecret);
// 4) Anchor preimage (Merkle root + chains)
const { msg_b64u: anchorMsg } = await buildAnchorPreimage('user-123', 'deadbeef...', '2025-01', { apf: ['root1','root2'] });
// Verify a set of governance attestations for a canonical message
const validCount = await verifyAttestations(govMsg!, [
{ alg: 'dilithium2', publicKeyB64u: signerPub1, signatureB64u: sig1.signature_b64u },
{ alg: 'dilithium2', publicKeyB64u: signerPub2, signatureB64u: sig2.signature_b64u }
], [signerPub1, signerPub2]);Notes app integration (independent repo)
Use the deterministic helpers to prepare messages client‑side, sign, and POST to the Core Worker endpoints.
import {
initWasm,
buildMintPreimage,
dilithiumSign,
verifyAttestations
} from '@maatara/core-pqc';
await initWasm();
// Build preimage and sign
const { msg_b64u } = await buildMintPreimage(header, asset);
const sig = await dilithiumSign(msg_b64u!, userSecret_b64u);
const attestation = { alg: 'dilithium2', publicKeyB64u: userPublic_b64u, signatureB64u: sig.signature_b64u };
// Optionally validate locally before submit
const valid = await verifyAttestations(msg_b64u!, [attestation], [userPublic_b64u]);
if (!valid) throw new Error('Attestation failed');
// Submit to Core
await fetch(`${CORE_URL}/api/assets/mint`, {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ header, asset, attestations: [attestation] })
});Build from source
# Build npm wrapper
cd packages/core-pqc
npm run buildWASM bindings live in @maatara/core-pqc-wasm (Rust + wasm-bindgen). This package consumes those exports and provides a browser/Node‑friendly API.
Security notes
- Zero‑knowledge: server never receives user secrets/DEKs
- Post‑quantum primitives (Kyber, Dilithium)
- Constant‑time operations where applicable
- Deterministic JSON canonicalization (JCS‑like) for signature stability
License
Apache‑2.0
Veritas Block Preimage (v2 JCS)
Blocks (Veritas chain) now use a canonical JCS JSON preimage for signatures (version 2). Legacy version 1 used a plain JSON.stringify of an object with insertion ordering. The new helper ensures deterministic ordering consistent with governance/asset preimages.
Helper:
import { buildBlockPreimage } from '@maatara/core-pqc';
const { canonical, msg_b64u } = await buildBlockPreimage({
index: block.index.toString(), // string (bigint safe)
timestamp: block.timestamp.toString(),
previousHash: block.previousHash,
dataHash: block.dataHash,
metadataHash: block.metadataHash,
signatureAlg: 'dilithium2',
ownerPublicKey: dilithiumPublicKeyB64u,
contentType: block.contentType || 'application/json',
version: 2,
});
// Sign msg_b64u with Dilithium secretCanonical object fields included (lexicographically ordered by JCS):
- contentType
- dataHash
- index (string)
- metadataHash
- ownerPublicKey (Dilithium public key, base64url)
- previousHash
- signatureAlg
- timestamp (string)
- version
Excluded: signature, encryptionKeyHash, any transient fields.
Message to sign: base64url( UTF-8(canonical JSON) ). No hashing layer (if you need prehash use Dilithium pre-hash mode externally before signature—current flow signs raw canonical bytes).
Migration Notes (v1 -> v2)
- Existing blocks signed under legacy scheme still verify: server falls back to legacy ordering if JCS verification fails.
- New blocks should set
version: 2and use Dilithium key forownerPublicKey(not the userId hash) to assert authorship. - Enable server debug logging of preimage by setting env
DEBUG_PREIMAGE=1. - Future breaking change removal: once all clients migrate, legacy fallback can be removed.
Client Checklist
- Always stringify bigint counters to decimal strings before building the preimage.
- Provide the true Dilithium public key as
ownerPublicKey. - Do not inject extra fields; they will be ignored (and change canonical ordering if you wrongly sign them locally).
- Ensure base64url is unpadded (
-/_substitutions). The helper already does this.