quantum-resistant-rustykey 0.12.13 → 0.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -22,6 +22,7 @@ npm add quantum-resistant-rustykey
22
22
  - **SQIsign** Level 5, Level 3, Level 1 NOT approved yet by NIST, refer [cose-sqisign] (https://datatracker.ietf.org/doc/draft-mott-cose-sqisign/)
23
23
  - **ML-DSA** ML-DSA-65, ML-DSA-87
24
24
  - **FN-DSA** FN-DSA-512, FN-DSA-1024
25
+ - **SLH-DSA** (SPHINCS+) SLH-DSA-SHA2-128s / 192s / 256s — hash-based, NIST-standardized ([FIPS 205](https://csrc.nist.gov/pubs/fips/205/final))
25
26
  - **ML-KEM** 512, 768, 1024 using [mlkem-native](https://github.com/pq-code-package/mlkem-native).
26
27
 
27
28
  ### SQISign is 'NIST-on-ramp': get ahead and test TODAY, SQISign is the ONLY signature for constrained-development use
@@ -149,25 +150,130 @@ Notes:
149
150
 
150
151
  ## Usage
151
152
 
152
- ### SQISign-webGPU (browser accelerated)
153
+ ### SQISign-webGPU (browser accelerated "racecar")
153
154
 
154
- Browser-only accelerated SQISign variants: **SQISign-L1-webGPU**, **SQISign-L3-webGPU**, **SQISign-L5-webGPU**.
155
- Requires COOP/COEP headers (`crossOriginIsolated`). See [docs/SQISIGN-WEBGPU.md](./docs/SQISIGN-WEBGPU.md).
155
+ Browser-only accelerated SQISign variants using **SharedArrayBuffer** and **WebGPU**.
156
+ These are separate from the standard server-compatible WASM loaders and are **not available in Node.js**.
156
157
 
157
- ```typescript
158
+ #### Variant names
159
+
160
+ | Security level | Standard loader | Accelerated (browser) |
161
+ |----------------|-----------------|------------------------|
162
+ | L5 | `loadSqisignLvl5()` → SQISign-L5 | `loadSqisignLvl5WebGpu()` → **SQISign-L5-webGPU** |
163
+ | L3 | `loadSqisignLvl3()` → SQISign-L3 | `loadSqisignLvl3WebGpu()` → **SQISign-L3-webGPU** |
164
+ | L1 | `loadSqisignLvl1()` → SQISign-L1 | `loadSqisignLvl1WebGpu()` → **SQISign-L1-webGPU** |
165
+
166
+ Labels are exported as `SQISIGN_WEBGPU_VARIANT_LABELS`.
167
+
168
+ #### Requirements (COOP / COEP)
169
+
170
+ Accelerated SQISign requires a **cross-origin isolated** browsing context:
171
+
172
+ 1. `crossOriginIsolated === true`
173
+ 2. `SharedArrayBuffer` available
174
+ 3. `navigator.gpu` (WebGPU) available
175
+
176
+ Serve these response headers on pages that load the accelerated variants:
177
+
178
+ ```http
179
+ Cross-Origin-Opener-Policy: same-origin
180
+ Cross-Origin-Embedder-Policy: require-corp
181
+ ```
182
+
183
+ ⚠️ IMPORTANT for this highly-tuned "racecar" version
184
+
185
+ Enforcing these headers on a production web app creates a challenging isolation boundary
186
+ - Breaking Third Parties: Every single script, analytic tracker, embedded iframe (like Stripe or YouTube), and cross-origin image on that page will immediately break or be blocked unless they are explicitly served with a Cross-Origin-Resource-Policy header
187
+ - Maintenance Overhead: the accelerated version is browser-only frontend, use our standard web-assembly package in nodejs backend***
188
+ - ok, so you're a self-confessed speed demon, you've read the cautions. But before you jump into this shiny new machine, remember you asked the crew to fit 'racing slicks for dry weather only'. If the weather changes unexpectedly, you'll find yourself behind the wheel of an 'aquatic hydroplaning device'. No airbags.
189
+
190
+ #### Specific risks introduced with this "racecar" version
191
+
192
+ 1. Security unknowns
193
+ - Side-Channel Vulnerabilities are untested. Offloading cryptographic math to a smartphone's WebGPU - billions of them, various model, makes, years - means executing field arithmetic directly on the host computer's GPU threads. Graphics processors are fundamentally optimized for parallel throughput, not constant-time deterministic execution.
194
+ - Novel unseen threats: Running cryptographic primitives on shared GPU hardware makes them highly susceptible to advanced timing and memory-coalescing side-channel attacks. ⚠️ Upstream C formal proofs absolutely do not account for WebGPU compute shader pipeline execution. ⚠️
195
+
196
+ ##### Next.js example
197
+
198
+ ```js
199
+ // next.config.mjs
200
+ async headers() {
201
+ return [
202
+ {
203
+ source: "/your-pqc-page/:path*",
204
+ headers: [
205
+ { key: "Cross-Origin-Opener-Policy", value: "same-origin" },
206
+ { key: "Cross-Origin-Embedder-Policy", value: "require-corp" },
207
+ ],
208
+ },
209
+ ];
210
+ }
211
+ ```
212
+
213
+ Third-party scripts, images, and iframes on the same page must be served with appropriate `Cross-Origin-Resource-Policy` (or `crossorigin` attributes) or they will be blocked under `require-corp`.
214
+
215
+ ##### Worker script (required for bundlers like Next.js)
216
+
217
+ Bundled apps cannot load `sqisign-accel-worker.js` from `node_modules`. Copy it to a public URL:
218
+
219
+ ```bash
220
+ cp node_modules/quantum-resistant-rustykey/dist/sqisign-accel-worker.js public/pqc/
221
+ ```
222
+
223
+ The testbed sync script does this automatically (`pnpm pqc:sync-local`).
224
+
225
+ Default worker URL: `/pqc/sqisign-accel-worker.js`. Override if needed:
226
+
227
+ ```ts
228
+ import { setSqisignAccelWorkerUrl } from "quantum-resistant-rustykey";
229
+ setSqisignAccelWorkerUrl("/your/path/sqisign-accel-worker.js");
230
+ ```
231
+
232
+ If the worker fails to load, the library falls back to main-thread WASM (same crypto, UI may stutter on L5).
233
+
234
+ #### Usage
235
+
236
+ ```ts
158
237
  import {
238
+ benchSqisignWebGpu,
239
+ getSqisignWebGpuSupport,
159
240
  isSqisignWebGpuAvailable,
160
241
  loadSqisignLvl5WebGpu,
161
- benchSqisignWebGpu,
242
+ SQISIGN_WEBGPU_VARIANT_LABELS,
162
243
  } from "quantum-resistant-rustykey";
163
244
 
164
- if (isSqisignWebGpuAvailable()) {
165
- const sq = await loadSqisignLvl5WebGpu();
166
- const bench = await benchSqisignWebGpu("lvl5");
167
- console.log(bench.steps);
245
+ const support = getSqisignWebGpuSupport();
246
+ if (!support.available) {
247
+ console.warn(support.reason);
168
248
  }
249
+
250
+ // Same IFnDsa surface as standard loaders
251
+ const sq = await loadSqisignLvl5WebGpu();
252
+ const kp = sq.keypair();
253
+ const pk = await kp.get("public_key");
254
+ const sk = await kp.get("private_key");
255
+ const msg = new TextEncoder().encode("hello");
256
+ const sig = await sq.sign(msg, sk);
257
+ const ok = await sq.verify(sig, msg, pk);
258
+
259
+ // Built-in keygen + sign + verify benchmark (browser only)
260
+ const bench = await benchSqisignWebGpu("lvl5");
261
+ console.log(bench.algorithm); // SQISign-L5-webGPU
262
+ console.log(bench.steps);
169
263
  ```
170
264
 
265
+ #### Architecture
266
+
267
+ 1. **Web Worker** — SQISign WASM runs off the main thread (worker bundle: `dist/sqisign-accel-worker.js`).
268
+ 2. **SharedArrayBuffer** — enabled when COOP/COEP isolate the origin (required for future pthread WASM builds).
269
+ 3. **WebGPU** — device initialization and compute pipeline warmup for field-arithmetic acceleration.
270
+
271
+ Standard `loadSqisignLvl*` loaders remain unchanged for Node.js and non-isolated browsers.
272
+
273
+ #### Live comparison
274
+
275
+ The [pqc.rustykey.me](https://pqc.rustykey.me) testbed shows side-by-side timings for SQISign-L1/L3/L5 vs SQISign-L1-webGPU / L3 / L5 on the **COSE** and **Verifiable Credentials** tabs when SQISign is selected.
276
+
171
277
  ### Node.js example
172
278
 
173
279
  ```typescript
@@ -308,6 +414,112 @@ Security note for web apps:
308
414
  - prefer HTTPS + short-lived keys
309
415
  - use secure key storage strategy (e.g. IndexedDB + app-level protections)
310
416
 
417
+ ### SLH-DSA (SPHINCS+) — hash-based signatures
418
+
419
+ SLH-DSA is a **stateless hash-based** signature scheme standardized by NIST in [FIPS 205](https://csrc.nist.gov/pubs/fips/205/final). Its security rests only on the security of its underlying hash function, giving it the most conservative assumptions of any signature family in this package — at the cost of large signatures and slow signing. This package ships the three SHA2 **`s` (small-signature)** parameter sets.
420
+
421
+ | Loader | Variant | COSE (provisional) | Public key | Secret key | Signature | W3C appendix |
422
+ | :--- | :--- | :---: | :---: | :---: | :---: | :---: |
423
+ | `loadSlhDsa128()` | SLH-DSA-SHA2-128s | `0x1220` | 32 B | 64 B | 7,856 B | ✅ L1 golden vector |
424
+ | `loadSlhDsa192()` | SLH-DSA-SHA2-192s | `0x1221` | 48 B | 96 B | 16,224 B | generated keys |
425
+ | `loadSlhDsa256()` | SLH-DSA-SHA2-256s | `0x1222` | 64 B | 128 B | 29,792 B | generated keys |
426
+
427
+ > [!NOTE]
428
+ > COSE identifiers above are **provisional** and used for testbed/interop only — SLH-DSA COSE code points are not yet finalized by IANA. Cryptosuite names follow the W3C VC data-integrity pattern: `slhdsa128-rdfc-2024`, `slhdsa128-jcs-2024` (and `slhdsa192-*` / `slhdsa256-*`).
429
+
430
+ > [!WARNING]
431
+ > **SLH-DSA signing is slow and signatures are large** (kilobytes, not the ~200 bytes of SQISign). It is unsuitable for the CTAP2 1024-byte WebAuthn buffer. Prefer it where conservative, hash-only security matters and bandwidth/latency are not constrained (e.g. long-lived certificates, firmware, archival VCs). Verification is comparatively fast.
432
+
433
+ All SLH-DSA loaders expose the same `IFnDsa` interface (`keypair()`, `sign()`, `verify()`, `buffer_to_string()`):
434
+
435
+ ```typescript
436
+ import { loadSlhDsa128 } from "quantum-resistant-rustykey";
437
+
438
+ async function demo() {
439
+ const slh = await loadSlhDsa128(); // or loadSlhDsa192 / loadSlhDsa256
440
+ const kp = slh.keypair();
441
+ const publicKey = await kp.get("public_key");
442
+ const privateKey = await kp.get("private_key");
443
+
444
+ const message = new TextEncoder().encode("Authored by RustyKey (SLH-DSA)");
445
+ const signature = await slh.sign(message, privateKey);
446
+ const isValid = await slh.verify(signature, message, publicKey);
447
+ console.log("SLH-DSA-SHA2-128s valid?", isValid);
448
+ }
449
+
450
+ demo().catch(console.error);
451
+ ```
452
+
453
+ The pure-JS SLH-DSA path is provided via [`@noble/post-quantum`](https://github.com/paulmillr/noble-post-quantum) and works identically in Node.js and the browser (no WASM/COOP-COEP requirements).
454
+
455
+ ## REST endpoint summary — Verifiable Credentials (VC)
456
+
457
+ This library is the cryptographic core behind the **[pqc.rustykey.me](https://pqc.rustykey.me)** testbed. The testbed exposes a small HTTP surface (Next.js route handlers) that wraps the loaders above so you can produce W3C **Verifiable Credential** data-integrity proofs over the wire. The package itself ships no server — this section documents the reference endpoints so integrators can call or replicate them.
458
+
459
+ All endpoints run server-side (`runtime: "nodejs"`) and accept/return JSON.
460
+
461
+ ### `POST /api/pqc/vc/sign` — one-shot signed VC
462
+
463
+ The high-level endpoint: generates a fresh keypair, canonicalizes the document, hashes it, and returns the data-integrity proof value.
464
+
465
+ **Request body**
466
+
467
+ | Field | Type | Description |
468
+ | :--- | :--- | :--- |
469
+ | `document` | object | The unsecured W3C credential payload. |
470
+ | `algorithm` | string | One of the identifiers in the table below. |
471
+ | `dataset_canonicalization` | `"rdfc"` \| `"ics"` | RDF Dataset Canonicalization (`rdfc`) or JSON canonicalization (`ics`/JCS). |
472
+
473
+ **Supported `algorithm` identifiers**
474
+
475
+ | Identifier | Family | Cryptosuite prefix |
476
+ | :--- | :--- | :--- |
477
+ | `SQIsign-L1` / `SQIsign-L3` / `SQIsign-L5` | SQISign | `sqisign1` / `sqisign3` / `sqisign5` |
478
+ | `mldsa44` | ML-DSA | `mldsa44` |
479
+ | `falcon512` | FN-DSA | `falcon512` |
480
+ | `slhdsa128` / `slhdsa192` / `slhdsa256` | **SLH-DSA** | `slhdsa128` / `slhdsa192` / `slhdsa256` |
481
+
482
+ **Response body**
483
+
484
+ ```jsonc
485
+ {
486
+ "runtime": "nodejs",
487
+ "totalMs": 1234.5,
488
+ "algorithm": "slhdsa128",
489
+ "cryptosuite": "slhdsa128-rdfc-2024",
490
+ "dataset_canonicalization": "rdfc",
491
+ "publicKey": "…hex…",
492
+ "privateKey": "…hex…",
493
+ "canonicalizedDoc": "…canonical form…",
494
+ "hash": "…hex…",
495
+ "signature": "z…", // multibase proofValue
496
+ "signatureHex": "…hex…"
497
+ }
498
+ ```
499
+
500
+ **Example**
501
+
502
+ ```bash
503
+ curl -X POST https://pqc.rustykey.me/api/pqc/vc/sign \
504
+ -H "Content-Type: application/json" \
505
+ -d '{
506
+ "document": { "@context": ["https://www.w3.org/ns/credentials/v2"], "type": ["VerifiableCredential"] },
507
+ "algorithm": "slhdsa128",
508
+ "dataset_canonicalization": "rdfc"
509
+ }'
510
+ ```
511
+
512
+ ### `POST /api/pqc/vc/proof` — full pipeline / bring-your-own-keys
513
+
514
+ Lower-level endpoint used by the testbed's step-by-step VC view. It has two modes:
515
+
516
+ - **Proof pipeline** — send `unsecuredDocument`, `family` (`sqisign` \| `mldsa` \| `falcon` \| `slhdsa`), `level` (`l1` \| `l3` \| `l5`), `canonicalization` (`rdfc` \| `jcs`), plus `publicKeyHex` / `secretKeyHex` (and optional `verificationMethod`). Returns each canonicalize → hash → sign → verify step.
517
+ - **Sign-only** — send `hashDataHex` with `family`, `level`, `publicKeyHex`, `secretKeyHex` (and optional `referenceProofValue`) to sign a pre-computed hash and verify it (including against a W3C appendix golden value).
518
+
519
+ ### `PUT /api/pqc/vc/proof` — keygen
520
+
521
+ Send `{ "family": "slhdsa", "level": "l1" }` to get a fresh `publicKeyHex` / `secretKeyHex` and the resolved algorithm label. Handy for pre-provisioning keys before calling the proof pipeline.
522
+
311
523
  ## Building from Source
312
524
 
313
525
  ### Prerequisites
@@ -350,7 +562,7 @@ pnpm build
350
562
 
351
563
  ### Digital Signatures (Node.js & Frontend)
352
564
 
353
- All signature algorithms (**FN-DSA**, **ML-DSA**, and **SQIsign**) share a common interface.
565
+ All signature algorithms (**FN-DSA**, **ML-DSA**, **SQIsign**, and **SLH-DSA**) share a common interface.
354
566
 
355
567
  ```typescript
356
568
  import {
package/dist/index.d.ts CHANGED
@@ -31,6 +31,11 @@ declare function loadFnDsa1024(): Promise<IFnDsa>;
31
31
  declare function loadMlDsa3(): Promise<IFnDsa>;
32
32
  declare function loadMlDsa5(): Promise<IFnDsa>;
33
33
  //#endregion
34
+ //#region src/slhdsa.d.ts
35
+ declare function loadSlhDsa128(): Promise<IFnDsa>;
36
+ declare function loadSlhDsa192(): Promise<IFnDsa>;
37
+ declare function loadSlhDsa256(): Promise<IFnDsa>;
38
+ //#endregion
34
39
  //#region src/sqisign.d.ts
35
40
  declare function loadSqisignLvl1(): Promise<IFnDsa>;
36
41
  declare function loadSqisignLvl3(): Promise<IFnDsa>;
@@ -78,7 +83,7 @@ declare function getSqisignWebGpuSupport(): SqisignWebGpuSupport;
78
83
  declare function isSqisignWebGpuAvailable(): boolean;
79
84
  //#endregion
80
85
  //#region src/sqisign-webgpu.d.ts
81
- /** Host apps (e.g. Next.js) must serve dist/sqisign-accel-worker.js — see docs/SQISIGN-WEBGPU.md */
86
+ /** Host apps (e.g. Next.js) must serve dist/sqisign-accel-worker.js — see the "SQISign-webGPU" section in README.md */
82
87
  declare function setSqisignAccelWorkerUrl(url: string): void;
83
88
  type SqisignBenchSteps = {
84
89
  keygenMs: number;
@@ -100,5 +105,5 @@ declare function loadMlKem768(): Promise<IMlKem>;
100
105
  declare function loadMlKem512(): Promise<IMlKem>;
101
106
  declare function loadMlKem1024(): Promise<IMlKem>;
102
107
  //#endregion
103
- export { SQISIGN_LVL1_KAT0_MSG_HEX, SQISIGN_LVL1_KAT0_PK_HEX, SQISIGN_LVL1_KAT0_SIG_HEX, SQISIGN_LVL1_KAT0_SM_HEX, SQISIGN_LVL3_KAT0_MSG_HEX, SQISIGN_LVL3_KAT0_PK_HEX, SQISIGN_LVL3_KAT0_SIG_HEX, SQISIGN_LVL3_KAT0_SM_HEX, SQISIGN_LVL5_KAT0_MSG_HEX, SQISIGN_LVL5_KAT0_PK_HEX, SQISIGN_LVL5_KAT0_SIG_HEX, SQISIGN_LVL5_KAT0_SM_HEX, SQISIGN_WEBGPU_VARIANT_LABELS, type SqisignBenchSteps, type SqisignWebGpuSupport, type SqisignWebGpuVariant, benchSqisignWebGpu, getSqisignWebGpuSupport, isSqisignWebGpuAvailable, loadFnDsa1024, loadFnDsa512, loadMlDsa3, loadMlDsa5, loadMlKem1024, loadMlKem512, loadMlKem768, loadSqisignLvl1, loadSqisignLvl1WebGpu, loadSqisignLvl3, loadSqisignLvl3WebGpu, loadSqisignLvl5, loadSqisignLvl5WebGpu, setSqisignAccelWorkerUrl };
108
+ export { SQISIGN_LVL1_KAT0_MSG_HEX, SQISIGN_LVL1_KAT0_PK_HEX, SQISIGN_LVL1_KAT0_SIG_HEX, SQISIGN_LVL1_KAT0_SM_HEX, SQISIGN_LVL3_KAT0_MSG_HEX, SQISIGN_LVL3_KAT0_PK_HEX, SQISIGN_LVL3_KAT0_SIG_HEX, SQISIGN_LVL3_KAT0_SM_HEX, SQISIGN_LVL5_KAT0_MSG_HEX, SQISIGN_LVL5_KAT0_PK_HEX, SQISIGN_LVL5_KAT0_SIG_HEX, SQISIGN_LVL5_KAT0_SM_HEX, SQISIGN_WEBGPU_VARIANT_LABELS, type SqisignBenchSteps, type SqisignWebGpuSupport, type SqisignWebGpuVariant, benchSqisignWebGpu, getSqisignWebGpuSupport, isSqisignWebGpuAvailable, loadFnDsa1024, loadFnDsa512, loadMlDsa3, loadMlDsa5, loadMlKem1024, loadMlKem512, loadMlKem768, loadSlhDsa128, loadSlhDsa192, loadSlhDsa256, loadSqisignLvl1, loadSqisignLvl1WebGpu, loadSqisignLvl3, loadSqisignLvl3WebGpu, loadSqisignLvl5, loadSqisignLvl5WebGpu, setSqisignAccelWorkerUrl };
104
109
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/fndsa.ts","../src/mldsa.ts","../src/sqisign.ts","../src/sqisign-kat-lvl1.ts","../src/sqisign-accel-env.ts","../src/sqisign-webgpu.ts","../src/index.ts"],"mappings":";KAAY,YAAA,MAAkB,CAAA,GAAI,OAAA,CAAQ,CAAA;AAAA,UAEzB,OAAA;EAEhB,GAAA,CAAI,GAAA,iCAAoC,YAAY;AAAA;AAAA,UAGpC,aAAA;EAEhB,GAAA,CAAI,GAAA,4BAA+B,YAAY;AAAA;AAAA,UAG/B,MAAA;EAChB,OAAA,IAAW,OAAA;EACX,OAAA,CAAQ,UAAA,QAAkB,aAAA;EAC1B,OAAA,CAAQ,UAAA,OAAiB,WAAA,QAAmB,OAAA;EAC5C,gBAAA,CAAiB,MAAA,QAAc,YAAA;EAC/B,cAAA,CAAe,OAAA,UAAiB,MAAA,QAAc,OAAA,CAAQ,UAAA;EACtD,cAAA,CAAe,gBAAA,EAAkB,UAAA,EAAY,MAAA,QAAc,OAAA;EAC3D,MAAA;AAAA;AAAA,KAOW,cAAA;AAAA,UAEK,MAAA;EAChB,OAAA,IAAW,OAAA;EACX,IAAA,CACC,OAAA,EAAS,UAAA,GAAa,WAAA,WACtB,WAAA,YACE,OAAA,CAAQ,UAAA;EACX,MAAA,CACC,SAAA,EAAW,UAAA,GAAa,WAAA,WACxB,OAAA,EAAS,UAAA,GAAa,WAAA,WACtB,UAAA,YACE,OAAA;EACH,gBAAA,CAAiB,KAAA,EAAO,UAAA,GAAa,WAAA;AAAA;;;iBC8NhB,YAAA,IAAgB,OAAO,CAAC,MAAA;AAAA,iBAKxB,aAAA,IAAiB,OAAO,CAAC,MAAA;;;iBCHzB,UAAA,IAAc,OAAO,CAAC,MAAA;AAAA,iBAKtB,UAAA,IAAc,OAAO,CAAC,MAAA;;;iBCsEtB,eAAA,IAAmB,OAAO,CAAC,MAAA;AAAA,iBAK3B,eAAA,IAAmB,OAAO,CAAC,MAAA;AAAA,iBAK3B,eAAA,IAAmB,OAAO,CAAC,MAAA;;;;AH5VjD;;;;cIKa,wBAAA;;cAIA,wBAAA;;cAIA,yBAAA;;cAGA,yBAAA;;cAGA,wBAAA;AAAA,cAEA,wBAAA;AAAA,cAEA,yBAAA;AAAA,cACA,yBAAA;;cAGA,wBAAA;AAAA,cAEA,wBAAA;AAAA,cAEA,yBAAA;AAAA,cACA,yBAAA;;;KChCD,oBAAA;EACX,SAAA;EACA,mBAAA;EACA,iBAAA;EACA,MAAA;EACA,MAAA;AAAA;AAAA,cAGY,6BAAA;EAAA;;;;KAMD,oBAAA,gBAAoC,6BAA6B;AAAA,iBAU7D,uBAAA,IAA2B,oBAAoB;AAAA,iBAyD/C,wBAAA;;;;iBCTA,wBAAA,CAAyB,GAAW;AAAA,KAiRxC,iBAAA;EACX,QAAA;EACA,MAAA;EACA,QAAA;AAAA;AAAA,iBAGqB,kBAAA,CACrB,OAAA,EAAS,cAAA,EACT,OAAA,YACE,OAAA;EACF,SAAA;EACA,EAAA;EACA,cAAA;EACA,KAAA,EAAO,iBAAA;AAAA;AAAA,iBAkCc,qBAAA,IAAyB,OAAO,CAAC,MAAA;AAAA,iBAIjC,qBAAA,IAAyB,OAAO,CAAC,MAAA;AAAA,iBAIjC,qBAAA,IAAyB,OAAO,CAAC,MAAA;;;iBC/IjC,YAAA,IAAgB,OAAO,CAAC,MAAA;AAAA,iBAIxB,YAAA,IAAgB,OAAO,CAAC,MAAA;AAAA,iBAIxB,aAAA,IAAiB,OAAO,CAAC,MAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/fndsa.ts","../src/mldsa.ts","../src/slhdsa.ts","../src/sqisign.ts","../src/sqisign-kat-lvl1.ts","../src/sqisign-accel-env.ts","../src/sqisign-webgpu.ts","../src/index.ts"],"mappings":";KAAY,YAAA,MAAkB,CAAA,GAAI,OAAA,CAAQ,CAAA;AAAA,UAEzB,OAAA;EAEhB,GAAA,CAAI,GAAA,iCAAoC,YAAY;AAAA;AAAA,UAGpC,aAAA;EAEhB,GAAA,CAAI,GAAA,4BAA+B,YAAY;AAAA;AAAA,UAG/B,MAAA;EAChB,OAAA,IAAW,OAAA;EACX,OAAA,CAAQ,UAAA,QAAkB,aAAA;EAC1B,OAAA,CAAQ,UAAA,OAAiB,WAAA,QAAmB,OAAA;EAC5C,gBAAA,CAAiB,MAAA,QAAc,YAAA;EAC/B,cAAA,CAAe,OAAA,UAAiB,MAAA,QAAc,OAAA,CAAQ,UAAA;EACtD,cAAA,CAAe,gBAAA,EAAkB,UAAA,EAAY,MAAA,QAAc,OAAA;EAC3D,MAAA;AAAA;AAAA,KAQW,cAAA;AAAA,UAEK,MAAA;EAChB,OAAA,IAAW,OAAA;EACX,IAAA,CACC,OAAA,EAAS,UAAA,GAAa,WAAA,WACtB,WAAA,YACE,OAAA,CAAQ,UAAA;EACX,MAAA,CACC,SAAA,EAAW,UAAA,GAAa,WAAA,WACxB,OAAA,EAAS,UAAA,GAAa,WAAA,WACtB,UAAA,YACE,OAAA;EACH,gBAAA,CAAiB,KAAA,EAAO,UAAA,GAAa,WAAA;AAAA;;;iBC6NhB,YAAA,IAAgB,OAAO,CAAC,MAAA;AAAA,iBAKxB,aAAA,IAAiB,OAAO,CAAC,MAAA;;;iBCHzB,UAAA,IAAc,OAAO,CAAC,MAAA;AAAA,iBAKtB,UAAA,IAAc,OAAO,CAAC,MAAA;;;iBCnMtB,aAAA,IAAiB,OAAO,CAAC,MAAA;AAAA,iBAIzB,aAAA,IAAiB,OAAO,CAAC,MAAA;AAAA,iBAIzB,aAAA,IAAiB,OAAO,CAAC,MAAA;;;iBCiQzB,eAAA,IAAmB,OAAO,CAAC,MAAA;AAAA,iBAK3B,eAAA,IAAmB,OAAO,CAAC,MAAA;AAAA,iBAK3B,eAAA,IAAmB,OAAO,CAAC,MAAA;;;;AJ5VjD;;;;cKKa,wBAAA;;cAIA,wBAAA;;cAIA,yBAAA;;cAGA,yBAAA;;cAGA,wBAAA;AAAA,cAEA,wBAAA;AAAA,cAEA,yBAAA;AAAA,cACA,yBAAA;;cAGA,wBAAA;AAAA,cAEA,wBAAA;AAAA,cAEA,yBAAA;AAAA,cACA,yBAAA;;;KChCD,oBAAA;EACX,SAAA;EACA,mBAAA;EACA,iBAAA;EACA,MAAA;EACA,MAAA;AAAA;AAAA,cAGY,6BAAA;EAAA;;;;KAMD,oBAAA,gBAAoC,6BAA6B;AAAA,iBAU7D,uBAAA,IAA2B,oBAAoB;AAAA,iBAyD/C,wBAAA;;;;iBCTA,wBAAA,CAAyB,GAAW;AAAA,KAiRxC,iBAAA;EACX,QAAA;EACA,MAAA;EACA,QAAA;AAAA;AAAA,iBAGqB,kBAAA,CACrB,OAAA,EAAS,cAAA,EACT,OAAA,YACE,OAAA;EACF,SAAA;EACA,EAAA;EACA,cAAA;EACA,KAAA,EAAO,iBAAA;AAAA;AAAA,iBAkCc,qBAAA,IAAyB,OAAO,CAAC,MAAA;AAAA,iBAIjC,qBAAA,IAAyB,OAAO,CAAC,MAAA;AAAA,iBAIjC,qBAAA,IAAyB,OAAO,CAAC,MAAA;;;iBC9IjC,YAAA,IAAgB,OAAO,CAAC,MAAA;AAAA,iBAIxB,YAAA,IAAgB,OAAO,CAAC,MAAA;AAAA,iBAIxB,aAAA,IAAiB,OAAO,CAAC,MAAA"}
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { slh_dsa_sha2_128s, slh_dsa_sha2_192s, slh_dsa_sha2_256s } from "@noble/post-quantum/slh-dsa.js";
1
2
  //#region src/vendor/mlkem.js
2
3
  var wasm_module_default = (() => {
3
4
  var _scriptDir = import.meta.url;
@@ -3148,6 +3149,55 @@ async function loadMlDsa5() {
3148
3149
  return new MlDsaWrapper("dilithium5");
3149
3150
  }
3150
3151
  //#endregion
3152
+ //#region src/slhdsa.ts
3153
+ function getImpl(variant) {
3154
+ if (variant === "sha2_192s") return slh_dsa_sha2_192s;
3155
+ if (variant === "sha2_256s") return slh_dsa_sha2_256s;
3156
+ return slh_dsa_sha2_128s;
3157
+ }
3158
+ var SlhDsaWrapper = class {
3159
+ variant;
3160
+ constructor(variant) {
3161
+ this.variant = variant;
3162
+ }
3163
+ impl() {
3164
+ return getImpl(this.variant);
3165
+ }
3166
+ keypair() {
3167
+ const pairPromise = Promise.resolve().then(() => {
3168
+ const { secretKey, publicKey } = this.impl().keygen();
3169
+ return {
3170
+ public_key: publicKey,
3171
+ private_key: secretKey
3172
+ };
3173
+ });
3174
+ return { get: (key) => pairPromise.then((pair) => key === "public_key" ? pair.public_key : pair.private_key) };
3175
+ }
3176
+ sign(message, private_key) {
3177
+ return Promise.resolve(private_key).then((sk) => this.impl().sign(asBytes(message), asBytes(sk)));
3178
+ }
3179
+ verify(signature, message, public_key) {
3180
+ return Promise.all([
3181
+ Promise.resolve(signature),
3182
+ Promise.resolve(message),
3183
+ Promise.resolve(public_key)
3184
+ ]).then(([sig, msg, pk]) => this.impl().verify(asBytes(sig), asBytes(msg), asBytes(pk)));
3185
+ }
3186
+ buffer_to_string(value) {
3187
+ if (typeof value === "string") return value;
3188
+ return toHex(asBytes(value));
3189
+ }
3190
+ };
3191
+ async function loadSlhDsa128() {
3192
+ return new SlhDsaWrapper("sha2_128s");
3193
+ }
3194
+ async function loadSlhDsa192() {
3195
+ return new SlhDsaWrapper("sha2_192s");
3196
+ }
3197
+ async function loadSlhDsa256() {
3198
+ return new SlhDsaWrapper("sha2_256s");
3199
+ }
3200
+ //#endregion
3151
3201
  //#region src/vendor/sqisignlvl1.js
3152
3202
  var sqisign_lvl1_module_default = (() => {
3153
3203
  var _scriptDir = import.meta.url;
@@ -4557,7 +4607,7 @@ const mainThreadLoaders = {
4557
4607
  lvl3: loadSqisignLvl3,
4558
4608
  lvl5: loadSqisignLvl5
4559
4609
  };
4560
- /** Host apps (e.g. Next.js) must serve dist/sqisign-accel-worker.js — see docs/SQISIGN-WEBGPU.md */
4610
+ /** Host apps (e.g. Next.js) must serve dist/sqisign-accel-worker.js — see the "SQISign-webGPU" section in README.md */
4561
4611
  function setSqisignAccelWorkerUrl(url) {
4562
4612
  customWorkerUrl = url;
4563
4613
  if (worker) {
@@ -4890,6 +4940,6 @@ async function loadMlKem1024() {
4890
4940
  return new MlKemWrapper(mlkem1024_default, { name: "ML-KEM-1024" });
4891
4941
  }
4892
4942
  //#endregion
4893
- export { SQISIGN_LVL1_KAT0_MSG_HEX, SQISIGN_LVL1_KAT0_PK_HEX, SQISIGN_LVL1_KAT0_SIG_HEX, SQISIGN_LVL1_KAT0_SM_HEX, SQISIGN_LVL3_KAT0_MSG_HEX, SQISIGN_LVL3_KAT0_PK_HEX, SQISIGN_LVL3_KAT0_SIG_HEX, SQISIGN_LVL3_KAT0_SM_HEX, SQISIGN_LVL5_KAT0_MSG_HEX, SQISIGN_LVL5_KAT0_PK_HEX, SQISIGN_LVL5_KAT0_SIG_HEX, SQISIGN_LVL5_KAT0_SM_HEX, SQISIGN_WEBGPU_VARIANT_LABELS, benchSqisignWebGpu, getSqisignWebGpuSupport, isSqisignWebGpuAvailable, loadFnDsa1024, loadFnDsa512, loadMlDsa3, loadMlDsa5, loadMlKem1024, loadMlKem512, loadMlKem768, loadSqisignLvl1, loadSqisignLvl1WebGpu, loadSqisignLvl3, loadSqisignLvl3WebGpu, loadSqisignLvl5, loadSqisignLvl5WebGpu, setSqisignAccelWorkerUrl };
4943
+ export { SQISIGN_LVL1_KAT0_MSG_HEX, SQISIGN_LVL1_KAT0_PK_HEX, SQISIGN_LVL1_KAT0_SIG_HEX, SQISIGN_LVL1_KAT0_SM_HEX, SQISIGN_LVL3_KAT0_MSG_HEX, SQISIGN_LVL3_KAT0_PK_HEX, SQISIGN_LVL3_KAT0_SIG_HEX, SQISIGN_LVL3_KAT0_SM_HEX, SQISIGN_LVL5_KAT0_MSG_HEX, SQISIGN_LVL5_KAT0_PK_HEX, SQISIGN_LVL5_KAT0_SIG_HEX, SQISIGN_LVL5_KAT0_SM_HEX, SQISIGN_WEBGPU_VARIANT_LABELS, benchSqisignWebGpu, getSqisignWebGpuSupport, isSqisignWebGpuAvailable, loadFnDsa1024, loadFnDsa512, loadMlDsa3, loadMlDsa5, loadMlKem1024, loadMlKem512, loadMlKem768, loadSlhDsa128, loadSlhDsa192, loadSlhDsa256, loadSqisignLvl1, loadSqisignLvl1WebGpu, loadSqisignLvl3, loadSqisignLvl3WebGpu, loadSqisignLvl5, loadSqisignLvl5WebGpu, setSqisignAccelWorkerUrl };
4894
4944
 
4895
4945
  //# sourceMappingURL=index.js.map