npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@quantakrypto/sieve

v0.4.2

Published

Sieve — conformance battery for ML-KEM / ML-DSA implementations. Drives any implementation over a simple stdin/stdout JSON protocol. Zero runtime dependencies.

Readme

@quantakrypto/sieve

Conformance battery for ML-KEM (FIPS 203), ML-DSA (FIPS 204), and SLH-DSA (FIPS 205) implementations. Sieve drives any implementation through a small stdin/stdout JSON protocol and reports where it deviates from the standard.

Zero runtime dependencies — Node built-ins only. Node ≥ 20, ESM.

What Sieve is (and is not)

Sieve tests other people's implementations. It deliberately does not implement ML-KEM/ML-DSA/SLH-DSA, and it never fabricates cryptographic Known-Answer-Test values. Its power comes from two honest sources:

  1. Tests that need no external vectors — self-consistency, structural, and negative/robustness checks that every conforming implementation must pass.
  2. A loader for official NIST ACVP / KAT vectors you supply — exact-value checks whose expected bytes come from your downloaded NIST files, not from Sieve. See vectors/README.md.

The only hard-coded cryptographic constants in Sieve are the public, standardized parameter sizes (e.g. ML-KEM-768 public key = 1184 bytes; SLH-DSA-SHA2-128f signature = 17088 bytes, FIPS 205 Table 2). Those are not secrets and not KAT values.

Install

Within the quantakrypto-tools monorepo it builds with the workspace:

npm install
npm run build            # tsc -b across the workspace

The package exposes a sieve bin and a programmatic API.

How it works

Sieve spawns your implementation (the SUT) as a child process and exchanges newline-delimited JSON: one request per line in, one response per line out, all byte fields base64. Full spec: PROTOCOL.md.

sieve  ──request (NDJSON)──▶  your SUT process
       ◀─response (NDJSON)──  (ML-KEM / ML-DSA)

Quick start (against the mock)

examples/mock-sut.ts is a non-cryptographic reference SUT used only to exercise the harness. It satisfies the protocol with deterministic, correctly sized fake bytes — it provides no security; never use it for anything real.

# run the full ML-KEM-768 battery against the mock
node --import tsx src/cli.ts \
  --impl "node --import tsx examples/mock-sut.ts" \
  --param ml-kem-768 --iterations 32

After npm run build the bin runs directly:

sieve --impl "node ./my-impl.js" --param ml-kem-768 --iterations 64 --json

Pointing Sieve at a REAL implementation

Write a thin adapter that speaks the protocol and calls a vetted library. The adapter is the SUT; Sieve never bundles a crypto implementation.

Example sketch using a Node binding (e.g. a WASM/native ML-KEM library):

// my-impl.js  — adapter only; the crypto comes from a vetted dependency.
import { createInterface } from "node:readline";
import { mlKem768 } from "some-vetted-pqc-lib";   // <- you choose & audit this

const b64 = (u8) => Buffer.from(u8).toString("base64");
const un  = (s)  => new Uint8Array(Buffer.from(s, "base64"));

createInterface({ input: process.stdin }).on("line", (line) => {
  if (!line.trim()) return;
  const r = JSON.parse(line);
  const out = (o) => process.stdout.write(JSON.stringify({ id: r.id, ok: true, ...o }) + "\n");
  const err = (code, message) => process.stdout.write(JSON.stringify({ id: r.id, ok: false, code, message }) + "\n");
  try {
    if (r.op === "keygen")  { const { publicKey, secretKey } = mlKem768.keygen(); return out({ pk: b64(publicKey), sk: b64(secretKey) }); }
    if (r.op === "encaps")  { const { cipherText, sharedSecret } = mlKem768.encapsulate(un(r.pk)); return out({ ct: b64(cipherText), ss: b64(sharedSecret) }); }
    if (r.op === "decaps")  { const ss = mlKem768.decapsulate(un(r.ct), un(r.sk)); return out({ ss: b64(ss) }); }
    return err("unsupported", `op ${r.op}`);
  } catch (e) { err("error", String(e?.message ?? e)); }
});

Then:

sieve --impl "node ./my-impl.js" --param ml-kem-768

For exact-value KAT, also pass --vectors <dir> with official NIST files.

CLI

sieve --impl "<command...>" --param <set> [options]

  --impl  "<cmd...>"   command Sieve spawns and drives (quote the whole thing)
  --param <set>        ml-kem-512 | ml-kem-768 | ml-kem-1024 |
                       ml-dsa-44  | ml-dsa-65  | ml-dsa-87  |
                       slh-dsa-{sha2,shake}-{128,192,256}{s,f}  (12 sets)
  --iterations <N>     randomized iterations (default 32)
  --vectors <dir>      official NIST ACVP vector dir for KAT (else SKIPPED)
  --timing             include the advisory decaps-timing probe
  --only <a,b,...>     run only these categories
  --timeout-ms <N>     per-request timeout (default 10000)
  --pipeline-depth <N> max concurrent in-flight requests for independent-iteration
                       categories (default 16; 1 = strictly serial)
  --inherit-env        pass the FULL parent env to the SUT (DANGEROUS; see below)
  --json               machine-readable report

exit: 0 = PASS, 1 = FAIL, 2 = usage error

Programmatic API

import { runSieve, formatHuman } from "@quantakrypto/sieve";

const report = await runSieve({
  command: ["node", "./my-impl.js"],
  param: "ml-kem-768",
  iterations: 64,
  // vectorsDir: "./vectors/ml-kem-768",
});
console.log(formatHuman(report));
process.exit(report.overall === "PASS" ? 0 : 1);

Category catalog

| Category | Family | Bug class | What it checks | |----------------------|---------|-----------|----------------| | correctness | ML-KEM | — | keygen→encaps(pk)→decaps(sk,ct) ⇒ ss_encaps === ss_decaps over N iterations. | | determinism | ML-KEM | — | repeated decaps(sk, ct) returns identical ss. | | implicit-rejection | ML-KEM | AF-02 | decaps of a corrupted ct returns a valid-length ss with no error/crash, is deterministic, and differs from the honest ss. No exact-value assertions. | | sizes | ML-KEM | AF-05 | emitted pk/sk/ct/ss lengths match the set; wrong-length pk/ct/sk are rejected with a defined error; FIPS 203 §7.2 ek modulus-range check — a correctly-sized-but-out-of-range encapsulation key ( coefficient ≥ q) is rejected. | | robustness | ML-KEM | AF-05 | empty / non-base64 / oversized inputs ⇒ defined error, never crash/silent-accept. | | dsa | ML-DSA | AF-05 | sign→verify ⇒ true; tampered message/signature ⇒ false; wrong message ⇒ false; pk/sk/sig sizes for ml-dsa-44/65/87; wrong-length verify input rejected; deterministic-vs-hedged signing advisory (surfaced, never fails). | | slh-dsa | SLH-DSA | AF-05 | same self-consistency surface as dsa for the 12 FIPS 205 parameter sets: sign→verify, tamper checks, pk/sk/sig sizes, signing-mode advisory, wrong-length verify rejection. | | kat | all | — | SKIPPED unless --vectors <dir> of official ACVP files is given; then checks decaps/seeded-keygen/seeded-encaps/sigVer against those exact expected values. Never fabricated. | | timing | ML-KEM | (AF-02) | ADVISORY only. Coarse decaps timing for valid vs. invalid ct. Reports a signal but never changes the verdict — cross-process timing is noisy and not proof of (non-)constant-time behavior. |

The overall verdict is FAIL if any non-advisory category fails, else PASS. A skip (e.g. KAT with no vectors) never causes a failure.

Honest stance on KAT vectors

Sieve ships no test vectors. Hard-coding "expected" ciphertext or shared-secret bytes would be both a maintenance hazard and a correctness lie if ever mistyped. Instead:

  • Self-consistency and structural categories give strong coverage with no external data.
  • For exact-value conformance, download the official NIST ACVP vectors and pass --vectors. The loader (src/vectors.ts) parses the standard ACVP JSON.

See vectors/README.md for sources and the file format.

Bug classes

  • AF-02 — implicit-rejection / Fujisaki–Okamoto reject-path mistakes (erroring on bad ct, constant/unkeyed reject secrets, non-determinism).
  • AF-05 — size/format confusion (accepting or emitting wrong-length artifacts, crashing on malformed input, accepting an out-of-range ek).

Security: the SUT runs with a scrubbed environment

The SUT is code you point Sieve at — frequently a third-party or candidate implementation. Sieve drives it with the harness's own OS privileges, so by default Sieve spawns it with a scrubbed, minimal environment: only a small allow-list (PATH, HOME, LANG, locale/temp vars, plus Windows spawn essentials) is copied from the parent process. Harness secrets in the parent env — CI tokens, NPM_TOKEN, cloud credentials, signing keys — are not forwarded, so an untrusted SUT cannot read them.

  • Pass explicit variables your SUT needs with env (programmatic) — these are layered on top of the scrubbed base.
  • Widen the allow-list with envAllowlist (copy named parent vars).
  • --inherit-env / inheritEnv: true restores the full parent environment. Use it only for trusted, local implementations you control.

Treat any non-trusted SUT as you would untrusted code generally — sandbox it (container / seccomp) if its provenance is unknown.

Throughput: bounded-concurrency pipelining

The SUT protocol is id-correlated (each response echoes its request id), so independent requests can be in flight at once. Categories whose iterations are mutually independent (correctness, determinism, dsa, slh-dsa) pipeline up to --pipeline-depth (default 16) requests against the single SUT process; the results are reassembled in request order so the verdict is identical to a serial run. Dependent steps within one iteration (e.g. keygen→encaps→decaps for a single key) and order-sensitive categories (timing) stay strictly serial. Set --pipeline-depth 1 to force the legacy serial behavior.

Algorithm scope

Sieve drives the three stateless NIST PQC schemes: ML-KEM (FIPS 203), ML-DSA (FIPS 204), and SLH-DSA (FIPS 205). The 12 standardized SLH-DSA parameter sets (slh-dsa-{sha2,shake}-{128,192,256}{s,f}) are supported with size and self-consistency categories; their public byte sizes come from FIPS 205 Table 2.

Out of scope: SP 800-208 stateful hash signatures (LMS / XMSS / HSS). These are deliberately not supported. Their security depends on one-time use of each leaf key — the signer must persist and advance secret state across signing operations, and reusing state catastrophically breaks the scheme. A stateless, request/response conformance harness like Sieve cannot model or verify the state-management guarantees that dominate SP 800-208 correctness; doing so safely requires a different, state-aware harness with durable per-key state tracking. LMS/XMSS are also intended for narrow uses (firmware/boot signing), not the general PQC migration Sieve targets.

License

Apache-2.0.

Support & training

Questions, commercial support, or post-quantum readiness training for your team — visit quantakrypto.com or email [email protected].