leviathan-crypto 2.0.1 → 3.0.0
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/CLAUDE.md +88 -281
- package/LICENSE +4 -0
- package/README.md +275 -87
- package/dist/aes/aes-cbc.d.ts +40 -0
- package/dist/aes/aes-cbc.js +158 -0
- package/dist/aes/aes-ctr.d.ts +50 -0
- package/dist/aes/aes-ctr.js +141 -0
- package/dist/aes/aes-gcm-siv.d.ts +67 -0
- package/dist/aes/aes-gcm-siv.js +217 -0
- package/dist/aes/aes-gcm.d.ts +61 -0
- package/dist/aes/aes-gcm.js +226 -0
- package/dist/aes/cipher-suite.d.ts +21 -0
- package/dist/aes/cipher-suite.js +179 -0
- package/dist/aes/embedded.d.ts +1 -0
- package/dist/aes/embedded.js +26 -0
- package/dist/aes/generator.d.ts +14 -0
- package/dist/aes/generator.js +103 -0
- package/dist/aes/index.d.ts +58 -0
- package/dist/aes/index.js +125 -0
- package/dist/aes/ops.d.ts +60 -0
- package/dist/aes/ops.js +164 -0
- package/dist/aes/pool-worker.d.ts +1 -0
- package/dist/aes/pool-worker.js +92 -0
- package/dist/aes/types.d.ts +1 -0
- package/dist/aes/types.js +23 -0
- package/dist/aes.wasm +0 -0
- package/dist/blake3/embedded.d.ts +1 -0
- package/dist/blake3/embedded.js +26 -0
- package/dist/blake3/index.d.ts +143 -0
- package/dist/blake3/index.js +620 -0
- package/dist/blake3/types.d.ts +102 -0
- package/dist/blake3/types.js +31 -0
- package/dist/blake3/validate.d.ts +29 -0
- package/dist/blake3/validate.js +80 -0
- package/dist/blake3.wasm +0 -0
- package/dist/chacha20/cipher-suite.d.ts +10 -0
- package/dist/chacha20/cipher-suite.js +98 -13
- package/dist/chacha20/generator.d.ts +12 -0
- package/dist/chacha20/generator.js +91 -0
- package/dist/chacha20/index.d.ts +100 -3
- package/dist/chacha20/index.js +169 -35
- package/dist/chacha20/ops.d.ts +57 -6
- package/dist/chacha20/ops.js +107 -27
- package/dist/chacha20/pool-worker.js +14 -0
- package/dist/chacha20/types.d.ts +1 -32
- package/dist/cte-wasm.d.ts +1 -0
- package/dist/cte-wasm.js +3 -0
- package/dist/cte.wasm +0 -0
- package/dist/curve25519.wasm +0 -0
- package/dist/ecdsa/der.d.ts +23 -0
- package/dist/ecdsa/der.js +192 -0
- package/dist/ecdsa/ecprivatekey-der.d.ts +32 -0
- package/dist/ecdsa/ecprivatekey-der.js +230 -0
- package/dist/ecdsa/embedded.d.ts +1 -0
- package/dist/ecdsa/embedded.js +25 -0
- package/dist/ecdsa/index.d.ts +124 -0
- package/dist/ecdsa/index.js +366 -0
- package/dist/ecdsa/types.d.ts +31 -0
- package/dist/ecdsa/types.js +28 -0
- package/dist/ecdsa/validate.d.ts +18 -0
- package/dist/ecdsa/validate.js +92 -0
- package/dist/ed25519/embedded.d.ts +1 -0
- package/dist/ed25519/embedded.js +31 -0
- package/dist/ed25519/index.d.ts +70 -0
- package/dist/ed25519/index.js +308 -0
- package/dist/ed25519/types.d.ts +27 -0
- package/dist/ed25519/types.js +27 -0
- package/dist/ed25519/validate.d.ts +7 -0
- package/dist/ed25519/validate.js +77 -0
- package/dist/embedded/aes-pool-worker.d.ts +1 -0
- package/dist/embedded/aes-pool-worker.js +5 -0
- package/dist/embedded/aes.d.ts +1 -0
- package/dist/embedded/aes.js +3 -0
- package/dist/embedded/blake3.d.ts +1 -0
- package/dist/embedded/blake3.js +3 -0
- package/dist/embedded/chacha20-pool-worker.d.ts +1 -0
- package/dist/embedded/chacha20-pool-worker.js +5 -0
- package/dist/embedded/chacha20.d.ts +1 -1
- package/dist/embedded/chacha20.js +2 -2
- package/dist/embedded/curve25519.d.ts +1 -0
- package/dist/embedded/curve25519.js +3 -0
- package/dist/embedded/mldsa.d.ts +1 -0
- package/dist/embedded/mldsa.js +3 -0
- package/dist/embedded/mlkem.d.ts +1 -0
- package/dist/embedded/mlkem.js +3 -0
- package/dist/embedded/p256.d.ts +1 -0
- package/dist/embedded/p256.js +3 -0
- package/dist/embedded/serpent-pool-worker.d.ts +1 -0
- package/dist/embedded/serpent-pool-worker.js +5 -0
- package/dist/embedded/serpent.d.ts +1 -1
- package/dist/embedded/serpent.js +2 -2
- package/dist/embedded/sha2.d.ts +1 -1
- package/dist/embedded/sha2.js +2 -2
- package/dist/embedded/sha3.d.ts +1 -1
- package/dist/embedded/sha3.js +2 -2
- package/dist/embedded/slhdsa.d.ts +1 -0
- package/dist/embedded/slhdsa.js +3 -0
- package/dist/errors.d.ts +92 -1
- package/dist/errors.js +111 -1
- package/dist/fortuna.d.ts +18 -12
- package/dist/fortuna.js +166 -99
- package/dist/index.d.ts +42 -11
- package/dist/index.js +65 -20
- package/dist/init.d.ts +1 -3
- package/dist/init.js +73 -7
- package/dist/keccak/embedded.js +1 -1
- package/dist/keccak/index.d.ts +2 -0
- package/dist/keccak/index.js +4 -2
- package/dist/loader.d.ts +1 -19
- package/dist/loader.js +26 -32
- package/dist/merkle/blake3-tree.d.ts +35 -0
- package/dist/merkle/blake3-tree.js +187 -0
- package/dist/merkle/checkpoint.d.ts +58 -0
- package/dist/merkle/checkpoint.js +217 -0
- package/dist/merkle/index.d.ts +19 -0
- package/dist/merkle/index.js +37 -0
- package/dist/merkle/merkle-log.d.ts +130 -0
- package/dist/merkle/merkle-log.js +207 -0
- package/dist/merkle/merkle-verifier.d.ts +126 -0
- package/dist/merkle/merkle-verifier.js +296 -0
- package/dist/merkle/proof.d.ts +70 -0
- package/dist/merkle/proof.js +300 -0
- package/dist/merkle/sha256-tree.d.ts +33 -0
- package/dist/merkle/sha256-tree.js +145 -0
- package/dist/merkle/signed-log.d.ts +156 -0
- package/dist/merkle/signed-log.js +356 -0
- package/dist/merkle/signed-note.d.ts +309 -0
- package/dist/merkle/signed-note.js +648 -0
- package/dist/merkle/sth.d.ts +31 -0
- package/dist/merkle/sth.js +31 -0
- package/dist/merkle/storage.d.ts +40 -0
- package/dist/merkle/storage.js +71 -0
- package/dist/merkle/tree.d.ts +68 -0
- package/dist/merkle/tree.js +94 -0
- package/dist/mldsa/embedded.d.ts +1 -0
- package/dist/{kyber → mldsa}/embedded.js +5 -5
- package/dist/mldsa/expand.d.ts +53 -0
- package/dist/mldsa/expand.js +188 -0
- package/dist/mldsa/format.d.ts +16 -0
- package/dist/mldsa/format.js +68 -0
- package/dist/mldsa/hashvariant.d.ts +32 -0
- package/dist/mldsa/hashvariant.js +248 -0
- package/dist/mldsa/index.d.ts +142 -0
- package/dist/mldsa/index.js +463 -0
- package/dist/mldsa/keygen.d.ts +16 -0
- package/dist/mldsa/keygen.js +232 -0
- package/dist/mldsa/params.d.ts +21 -0
- package/dist/mldsa/params.js +55 -0
- package/dist/mldsa/sha3-helpers.d.ts +30 -0
- package/dist/mldsa/sha3-helpers.js +124 -0
- package/dist/mldsa/sign.d.ts +36 -0
- package/dist/mldsa/sign.js +380 -0
- package/dist/mldsa/types.d.ts +91 -0
- package/dist/mldsa/types.js +25 -0
- package/dist/mldsa/validate.d.ts +55 -0
- package/dist/mldsa/validate.js +125 -0
- package/dist/mldsa/verify.d.ts +29 -0
- package/dist/mldsa/verify.js +269 -0
- package/dist/mldsa.wasm +0 -0
- package/dist/mlkem/embedded.d.ts +1 -0
- package/dist/mlkem/embedded.js +27 -0
- package/dist/mlkem/indcpa.d.ts +49 -0
- package/dist/{kyber → mlkem}/indcpa.js +48 -48
- package/dist/mlkem/index.d.ts +37 -0
- package/dist/{kyber → mlkem}/index.js +41 -31
- package/dist/mlkem/kem.d.ts +21 -0
- package/dist/{kyber → mlkem}/kem.js +48 -13
- package/dist/{kyber → mlkem}/params.d.ts +4 -4
- package/dist/{kyber → mlkem}/params.js +2 -2
- package/dist/mlkem/suite.d.ts +12 -0
- package/dist/{kyber → mlkem}/suite.js +17 -12
- package/dist/{kyber → mlkem}/types.d.ts +4 -3
- package/dist/{kyber → mlkem}/types.js +1 -1
- package/dist/mlkem/validate.d.ts +23 -0
- package/dist/{kyber → mlkem}/validate.js +24 -20
- package/dist/{kyber.wasm → mlkem.wasm} +0 -0
- package/dist/p256.wasm +0 -0
- package/dist/ratchet/index.d.ts +8 -0
- package/dist/ratchet/index.js +38 -0
- package/dist/ratchet/kdf-chain.d.ts +13 -0
- package/dist/ratchet/kdf-chain.js +85 -0
- package/dist/ratchet/ratchet-keypair.d.ts +9 -0
- package/dist/ratchet/ratchet-keypair.js +61 -0
- package/dist/ratchet/root-kdf.d.ts +4 -0
- package/dist/ratchet/root-kdf.js +124 -0
- package/dist/ratchet/skipped-key-store.d.ts +14 -0
- package/dist/ratchet/skipped-key-store.js +154 -0
- package/dist/ratchet/types.d.ts +36 -0
- package/dist/ratchet/types.js +26 -0
- package/dist/serpent/cipher-suite.d.ts +10 -0
- package/dist/serpent/cipher-suite.js +144 -56
- package/dist/serpent/generator.d.ts +12 -0
- package/dist/serpent/generator.js +97 -0
- package/dist/serpent/index.d.ts +62 -1
- package/dist/serpent/index.js +97 -21
- package/dist/serpent/pool-worker.js +28 -102
- package/dist/serpent/serpent-cbc.d.ts +16 -6
- package/dist/serpent/serpent-cbc.js +58 -37
- package/dist/serpent/shared-ops.d.ts +63 -0
- package/dist/serpent/shared-ops.js +178 -0
- package/dist/serpent/types.d.ts +1 -5
- package/dist/serpent.wasm +0 -0
- package/dist/sha2/hash.d.ts +2 -0
- package/dist/sha2/hash.js +53 -0
- package/dist/sha2/hkdf.js +5 -5
- package/dist/sha2/index.d.ts +22 -1
- package/dist/sha2/index.js +80 -11
- package/dist/sha2/types.d.ts +41 -2
- package/dist/sha2.wasm +0 -0
- package/dist/sha3/hash.d.ts +2 -0
- package/dist/sha3/hash.js +53 -0
- package/dist/sha3/index.d.ts +87 -3
- package/dist/sha3/index.js +317 -19
- package/dist/sha3/kmac.d.ts +121 -0
- package/dist/sha3/kmac.js +800 -0
- package/dist/sha3.wasm +0 -0
- package/dist/shared/pkcs7.d.ts +22 -0
- package/dist/shared/pkcs7.js +84 -0
- package/dist/sign/ctx.d.ts +41 -0
- package/dist/sign/ctx.js +102 -0
- package/dist/sign/envelope.d.ts +45 -0
- package/dist/sign/envelope.js +152 -0
- package/dist/sign/hasher.d.ts +9 -0
- package/dist/sign/hasher.js +132 -0
- package/dist/sign/index.d.ts +11 -0
- package/dist/sign/index.js +34 -0
- package/dist/sign/sign-stream.d.ts +25 -0
- package/dist/sign/sign-stream.js +112 -0
- package/dist/sign/suites/ecdsa-p256.d.ts +2 -0
- package/dist/sign/suites/ecdsa-p256.js +120 -0
- package/dist/sign/suites/ed25519.d.ts +3 -0
- package/dist/sign/suites/ed25519.js +165 -0
- package/dist/sign/suites/hybrid-classical.d.ts +23 -0
- package/dist/sign/suites/hybrid-classical.js +526 -0
- package/dist/sign/suites/hybrid-pq.d.ts +4 -0
- package/dist/sign/suites/hybrid-pq.js +234 -0
- package/dist/sign/suites/mldsa.d.ts +7 -0
- package/dist/sign/suites/mldsa.js +161 -0
- package/dist/sign/suites/slhdsa.d.ts +7 -0
- package/dist/sign/suites/slhdsa.js +176 -0
- package/dist/sign/types.d.ts +106 -0
- package/dist/sign/types.js +28 -0
- package/dist/sign/verify-stream.d.ts +30 -0
- package/dist/sign/verify-stream.js +227 -0
- package/dist/slhdsa/embedded.d.ts +1 -0
- package/dist/slhdsa/embedded.js +26 -0
- package/dist/slhdsa/index.d.ts +149 -0
- package/dist/slhdsa/index.js +493 -0
- package/dist/slhdsa/params.d.ts +26 -0
- package/dist/slhdsa/params.js +70 -0
- package/dist/slhdsa/prehash.d.ts +68 -0
- package/dist/slhdsa/prehash.js +307 -0
- package/dist/slhdsa/sign.d.ts +39 -0
- package/dist/slhdsa/sign.js +116 -0
- package/dist/slhdsa/types.d.ts +129 -0
- package/dist/slhdsa/types.js +27 -0
- package/dist/slhdsa/validate.d.ts +60 -0
- package/dist/slhdsa/validate.js +127 -0
- package/dist/slhdsa/verify.d.ts +32 -0
- package/dist/slhdsa/verify.js +107 -0
- package/dist/slhdsa.wasm +0 -0
- package/dist/stream/header.js +8 -8
- package/dist/stream/index.d.ts +1 -0
- package/dist/stream/index.js +1 -0
- package/dist/stream/open-stream.js +65 -22
- package/dist/stream/seal-stream-pool.d.ts +2 -0
- package/dist/stream/seal-stream-pool.js +100 -33
- package/dist/stream/seal-stream.d.ts +1 -1
- package/dist/stream/seal-stream.js +48 -19
- package/dist/stream/seal.js +6 -6
- package/dist/stream/types.d.ts +3 -1
- package/dist/stream/types.js +1 -1
- package/dist/types.d.ts +22 -1
- package/dist/types.js +1 -1
- package/dist/utils.d.ts +9 -10
- package/dist/utils.js +84 -59
- package/dist/wasm-source.d.ts +9 -8
- package/dist/wasm-source.js +1 -1
- package/dist/x25519/embedded.d.ts +1 -0
- package/dist/x25519/embedded.js +31 -0
- package/dist/x25519/index.d.ts +43 -0
- package/dist/x25519/index.js +159 -0
- package/dist/x25519/types.d.ts +25 -0
- package/dist/x25519/types.js +27 -0
- package/dist/x25519/validate.d.ts +2 -0
- package/dist/x25519/validate.js +39 -0
- package/package.json +123 -64
- package/SECURITY.md +0 -276
- package/dist/ct-wasm.d.ts +0 -1
- package/dist/ct-wasm.js +0 -3
- package/dist/ct.wasm +0 -0
- package/dist/docs/aead.md +0 -323
- package/dist/docs/architecture.md +0 -932
- package/dist/docs/argon2id.md +0 -302
- package/dist/docs/chacha20.md +0 -674
- package/dist/docs/exports.md +0 -241
- package/dist/docs/fortuna.md +0 -313
- package/dist/docs/init.md +0 -302
- package/dist/docs/loader.md +0 -161
- package/dist/docs/serpent.md +0 -519
- package/dist/docs/sha2.md +0 -613
- package/dist/docs/sha3.md +0 -546
- package/dist/docs/types.md +0 -276
- package/dist/docs/utils.md +0 -367
- package/dist/embedded/kyber.d.ts +0 -1
- package/dist/embedded/kyber.js +0 -3
- package/dist/kyber/embedded.d.ts +0 -1
- package/dist/kyber/indcpa.d.ts +0 -49
- package/dist/kyber/index.d.ts +0 -38
- package/dist/kyber/kem.d.ts +0 -21
- package/dist/kyber/suite.d.ts +0 -13
- package/dist/kyber/validate.d.ts +0 -19
|
@@ -1,932 +0,0 @@
|
|
|
1
|
-
# Architecture
|
|
2
|
-
|
|
3
|
-
> [!NOTE]
|
|
4
|
-
> `leviathan-crypto` v2.0 packages five WASM modules (Serpent, ChaCha20, SHA-2, SHA-3, Kyber), generic streaming AEAD via CipherSuite, and worker pool parallelism. It supersedes `leviathan` (TypeScript reference) and `leviathan-wasm` (WASM primitives), both of which remain unchanged as development references.
|
|
5
|
-
|
|
6
|
-
> ### Table of Contents
|
|
7
|
-
> - [Vision](#vision)
|
|
8
|
-
> - [Scope](#scope)
|
|
9
|
-
> - [Repository Structure](#repository-structure)
|
|
10
|
-
> - [Architecture: TypeScript over WASM](#architecture-typescript-over-wasm)
|
|
11
|
-
> - [Five Independent WASM Modules](#five-independent-wasm-modules)
|
|
12
|
-
> - [init() API](#init-api)
|
|
13
|
-
> - [Public API Classes](#public-api-classes)
|
|
14
|
-
> - [Build Pipeline](#build-pipeline)
|
|
15
|
-
> - [Module Relationship Diagrams](#module-relationship-diagrams)
|
|
16
|
-
> - [npm Package](#npm-package)
|
|
17
|
-
> - [Buffer Layouts](#buffer-layouts)
|
|
18
|
-
> - [Test Suite](#test-suite)
|
|
19
|
-
> - [Correctness Contract](#correctness-contract)
|
|
20
|
-
> - [Known Limitations](#known-limitations)
|
|
21
|
-
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
## Vision
|
|
25
|
-
|
|
26
|
-
`leviathan-crypto` is a strictly-typed, audited WebAssembly cryptography library for
|
|
27
|
-
the web. It combines two previously separate efforts:
|
|
28
|
-
|
|
29
|
-
**leviathan.** Developer-friendly TypeScript API, strict types, audited against specs and known-answer test vectors.
|
|
30
|
-
|
|
31
|
-
**leviathan-wasm.** AssemblyScript WASM implementation of the same primitives, running outside the JavaScript JIT for predictable execution and practical constant-time guarantees.
|
|
32
|
-
|
|
33
|
-
The unified library exposes the TypeScript API from leviathan, backed by the WASM
|
|
34
|
-
execution engine from leviathan-wasm. Developers get ergonomic, well-typed classes.
|
|
35
|
-
The runtime gets deterministic cryptographic computation outside the JIT.
|
|
36
|
-
|
|
37
|
-
**The fundamental insight:** JavaScript engines provide no formal constant-time
|
|
38
|
-
guarantees for arbitrary code. WASM execution is deterministic and not subject to
|
|
39
|
-
JIT speculation. For a cryptography library, this distinction matters. The TypeScript
|
|
40
|
-
layer handles API ergonomics; the WASM layer handles all cryptographic computation.
|
|
41
|
-
|
|
42
|
-
---
|
|
43
|
-
|
|
44
|
-
## Scope
|
|
45
|
-
|
|
46
|
-
### In scope
|
|
47
|
-
|
|
48
|
-
| Module | Primitives |
|
|
49
|
-
| ------------------ | ----------------------------------------------------------------------------------------------------------------------- |
|
|
50
|
-
| `serpent` | Serpent-256 block cipher: ECB, CTR mode, CBC mode |
|
|
51
|
-
| `serpent` + `sha2` | `SerpentCipher` (CipherSuite for STREAM construction: CBC+HMAC-SHA256) |
|
|
52
|
-
| `chacha20` | ChaCha20, Poly1305, ChaCha20-Poly1305 AEAD, XChaCha20-Poly1305 AEAD, `XChaCha20Cipher` (CipherSuite for streaming AEAD) |
|
|
53
|
-
| `sha2` | SHA-256, SHA-384, SHA-512, HMAC-SHA256, HMAC-SHA384, HMAC-SHA512, HKDF-SHA256, HKDF-SHA512 |
|
|
54
|
-
| `sha3` / `keccak` | SHA3-224, SHA3-256, SHA3-384, SHA3-512, SHAKE128, SHAKE256 (XOFs, multi-squeeze). `'keccak'` is an alias for `'sha3'`; same binary, same instance slot. |
|
|
55
|
-
| `kyber` | `MlKem512`, `MlKem768`, `MlKem1024`. Requires `sha3` for Keccak sponge operations. |
|
|
56
|
-
| `stream` | `SealStream`, `OpenStream` (cipher-agnostic STREAM construction), `SealStreamPool` (worker-based parallelism) |
|
|
57
|
-
|
|
58
|
-
Pure TypeScript utilities (encoding helpers, random generation, format converters)
|
|
59
|
-
ship alongside the WASM-backed primitives with no `init()` dependency.
|
|
60
|
-
|
|
61
|
-
### Auxiliary tier (not part of `Module` union)
|
|
62
|
-
|
|
63
|
-
- **`Fortuna`:** CSPRNG requiring two core modules (`serpent` + `sha2`).
|
|
64
|
-
|
|
65
|
-
---
|
|
66
|
-
|
|
67
|
-
## Repository Structure
|
|
68
|
-
|
|
69
|
-
```text
|
|
70
|
-
leviathan-crypto/
|
|
71
|
-
├── .github/
|
|
72
|
-
│ └── workflows/ ← CI: build, test-suite, e2e, publish, release, wiki
|
|
73
|
-
├── src/
|
|
74
|
-
│ ├── asm/ ← AssemblyScript (compiles to .wasm)
|
|
75
|
-
│ │ ├── serpent/
|
|
76
|
-
│ │ │ ├── index.ts ← asc entry point → serpent.wasm
|
|
77
|
-
│ │ │ ├── serpent.ts ← block function + key schedule
|
|
78
|
-
│ │ │ ├── serpent_unrolled.ts ← unrolled S-boxes and round functions
|
|
79
|
-
│ │ │ ├── serpent_simd.ts ← SIMD bitsliced block operations
|
|
80
|
-
│ │ │ ├── cbc.ts ← CBC mode
|
|
81
|
-
│ │ │ ├── cbc_simd.ts ← SIMD CBC decrypt
|
|
82
|
-
│ │ │ ├── ctr.ts ← CTR mode
|
|
83
|
-
│ │ │ ├── ctr_simd.ts ← SIMD CTR 4-wide inter-block
|
|
84
|
-
│ │ │ └── buffers.ts ← static buffer layout + offset getters
|
|
85
|
-
│ │ ├── chacha20/
|
|
86
|
-
│ │ │ ├── index.ts ← asc entry point → chacha20.wasm
|
|
87
|
-
│ │ │ ├── chacha20.ts
|
|
88
|
-
│ │ │ ├── chacha20_simd_4x.ts ← SIMD 4-wide inter-block ChaCha20
|
|
89
|
-
│ │ │ ├── poly1305.ts
|
|
90
|
-
│ │ │ ├── wipe.ts
|
|
91
|
-
│ │ │ └── buffers.ts
|
|
92
|
-
│ │ ├── sha2/
|
|
93
|
-
│ │ │ ├── index.ts ← asc entry point → sha2.wasm
|
|
94
|
-
│ │ │ ├── sha256.ts
|
|
95
|
-
│ │ │ ├── sha512.ts
|
|
96
|
-
│ │ │ ├── hmac.ts
|
|
97
|
-
│ │ │ ├── hmac512.ts
|
|
98
|
-
│ │ │ └── buffers.ts
|
|
99
|
-
│ │ ├── sha3/
|
|
100
|
-
│ │ ├── index.ts ← asc entry point → sha3.wasm
|
|
101
|
-
│ │ ├── keccak.ts
|
|
102
|
-
│ │ └── buffers.ts
|
|
103
|
-
│ │ ├── ct/
|
|
104
|
-
│ │ │ └── index.ts ← asc entry point → ct.wasm (SIMD constant-time compare)
|
|
105
|
-
│ │ └── kyber/
|
|
106
|
-
│ │ ├── index.ts ← asc entry point → kyber.wasm
|
|
107
|
-
│ │ ├── ntt.ts ← NTT/invNTT (scalar reference + zetas table)
|
|
108
|
-
│ │ ├── ntt_simd.ts ← SIMD NTT/invNTT (v128 butterflies, fqmul_8x, barrett_reduce_8x)
|
|
109
|
-
│ │ ├── reduce.ts ← Montgomery/Barrett reduction, fqmul
|
|
110
|
-
│ │ ├── poly.ts ← polynomial serialization, compression, arithmetic, basemul
|
|
111
|
-
│ │ ├── poly_simd.ts ← SIMD poly add/sub/reduce/ntt wrappers
|
|
112
|
-
│ │ ├── polyvec.ts ← k-wide polyvec operations
|
|
113
|
-
│ │ ├── cbd.ts ← centered binomial distribution (η=2, η=3)
|
|
114
|
-
│ │ ├── sampling.ts ← uniform rejection sampling
|
|
115
|
-
│ │ ├── verify.ts ← constant-time compare and conditional move
|
|
116
|
-
│ │ ├── params.ts ← Q, QINV, MONT, Barrett/compression constants
|
|
117
|
-
│ │ └── buffers.ts ← static buffer layout + offset getters
|
|
118
|
-
│ └── ts/ ← TypeScript (public API)
|
|
119
|
-
│ ├── init.ts ← initModule() : WASM loading and module cache
|
|
120
|
-
│ ├── loader.ts ← loadWasm() / compileWasm() : polymorphic WasmSource dispatch
|
|
121
|
-
│ ├── wasm-source.ts ← WasmSource union type
|
|
122
|
-
│ ├── errors.ts ← AuthenticationError
|
|
123
|
-
│ ├── types.ts ← Hash, KeyedHash, Blockcipher, Streamcipher, AEAD
|
|
124
|
-
│ ├── utils.ts ← encoding, wipe, xor, concat, randomBytes
|
|
125
|
-
│ ├── fortuna.ts ← Fortuna CSPRNG (requires serpent + sha2)
|
|
126
|
-
│ ├── embedded/ ← generated gzip+base64 blobs (build artifact, gitignored)
|
|
127
|
-
│ │ ├── serpent.ts
|
|
128
|
-
│ │ ├── chacha20.ts
|
|
129
|
-
│ │ ├── sha2.ts
|
|
130
|
-
│ │ └── sha3.ts
|
|
131
|
-
│ ├── serpent/
|
|
132
|
-
│ │ ├── index.ts ← serpentInit() + Serpent, SerpentCtr, SerpentCbc
|
|
133
|
-
│ │ ├── cipher-suite.ts ← SerpentCipher (CipherSuite for STREAM construction)
|
|
134
|
-
│ │ ├── pool-worker.ts ← Web Worker for SealStreamPool with SerpentCipher
|
|
135
|
-
│ │ ├── embedded.ts ← re-exports gzip+base64 blob as named export
|
|
136
|
-
│ │ └── types.ts
|
|
137
|
-
│ ├── chacha20/
|
|
138
|
-
│ │ ├── index.ts ← chacha20Init() + ChaCha20, Poly1305, ChaCha20Poly1305, XChaCha20Poly1305, XChaCha20Cipher
|
|
139
|
-
│ │ ├── ops.ts ← raw AEAD functions shared by classes and pool worker
|
|
140
|
-
│ │ ├── cipher-suite.ts ← XChaCha20Cipher (CipherSuite for STREAM construction)
|
|
141
|
-
│ │ ├── pool-worker.ts ← Web Worker for SealStreamPool with XChaCha20Cipher
|
|
142
|
-
│ │ ├── embedded.ts ← re-exports gzip+base64 blob as named export
|
|
143
|
-
│ │ └── types.ts
|
|
144
|
-
│ ├── sha2/
|
|
145
|
-
│ │ ├── index.ts ← sha2Init() + SHA256, SHA512, SHA384, HMAC, HKDF
|
|
146
|
-
│ │ ├── hkdf.ts ← HKDF_SHA256, HKDF_SHA512 (pure TS over HMAC)
|
|
147
|
-
│ │ ├── embedded.ts ← re-exports gzip+base64 blob as named export
|
|
148
|
-
│ │ └── types.ts
|
|
149
|
-
│ ├── sha3/
|
|
150
|
-
│ │ ├── index.ts ← sha3Init() + SHA3_224–512, SHAKE128, SHAKE256
|
|
151
|
-
│ │ ├── embedded.ts ← re-exports gzip+base64 blob as named export
|
|
152
|
-
│ │ └── types.ts
|
|
153
|
-
│ ├── kyber/
|
|
154
|
-
│ │ ├── index.ts ← kyberInit() + MlKem512, MlKem768, MlKem1024, KyberSuite
|
|
155
|
-
│ │ ├── kem.ts ← Fujisaki-Okamoto transform (keygen, encaps, decaps)
|
|
156
|
-
│ │ ├── suite.ts ← KyberSuite factory (hybrid KEM+AEAD CipherSuite)
|
|
157
|
-
│ │ ├── indcpa.ts ← IND-CPA encrypt/decrypt + matrix generation
|
|
158
|
-
│ │ ├── validate.ts ← key validation (FIPS 203 §7.2, §7.3)
|
|
159
|
-
│ │ ├── params.ts ← parameter sets (MLKEM512, MLKEM768, MLKEM1024)
|
|
160
|
-
│ │ ├── types.ts ← KyberExports, Sha3Exports, KEM API types
|
|
161
|
-
│ │ └── embedded.ts ← re-exports gzip+base64 blob as kyberWasm
|
|
162
|
-
│ ├── stream/
|
|
163
|
-
│ │ ├── index.ts ← barrel: Seal, SealStream, OpenStream, SealStreamPool, constants
|
|
164
|
-
│ │ ├── seal.ts ← Seal (static one-shot AEAD)
|
|
165
|
-
│ │ ├── seal-stream.ts ← SealStream (cipher-agnostic streaming encryption)
|
|
166
|
-
│ │ ├── open-stream.ts ← OpenStream (cipher-agnostic streaming decryption)
|
|
167
|
-
│ │ ├── seal-stream-pool.ts ← SealStreamPool (worker-based parallel batch)
|
|
168
|
-
│ │ ├── header.ts ← wire format header encode/decode, counter nonce
|
|
169
|
-
│ │ ├── constants.ts ← HEADER_SIZE, CHUNK_MIN/MAX, TAG_DATA/FINAL, FLAG_FRAMED
|
|
170
|
-
│ │ └── types.ts ← CipherSuite, DerivedKeys, SealStreamOpts
|
|
171
|
-
│ └── index.ts ← root barrel : dispatching init() + re-exports everything
|
|
172
|
-
├── test/
|
|
173
|
-
│ ├── unit/ ← Vitest (JS target, fast iteration)
|
|
174
|
-
│ │ ├── serpent/
|
|
175
|
-
│ │ ├── chacha20/
|
|
176
|
-
│ │ ├── sha2/
|
|
177
|
-
│ │ ├── sha3/
|
|
178
|
-
│ │ ├── stream/ ← SealStream, OpenStream, SealStreamPool tests
|
|
179
|
-
│ │ ├── loader/ ← WasmSource loading tests
|
|
180
|
-
│ │ ├── init.test.ts
|
|
181
|
-
│ │ ├── errors.test.ts
|
|
182
|
-
│ │ ├── fortuna.test.ts
|
|
183
|
-
│ │ └── utils.test.ts
|
|
184
|
-
│ ├── e2e/ ← Playwright (WASM target, cross-browser)
|
|
185
|
-
│ └── vectors/ ← test vector files (read-only reference data)
|
|
186
|
-
├── scripts/
|
|
187
|
-
│ ├── build-asm.js ← orchestrates AssemblyScript compilation
|
|
188
|
-
│ ├── embed-wasm.ts ← reads build/*.wasm, generates src/ts/embedded/*.ts
|
|
189
|
-
│ ├── gen-seal-vectors.ts ← generates KAT vectors for Seal
|
|
190
|
-
│ ├── gen-sealstream-vectors.ts ← generates KAT vectors for SealStream
|
|
191
|
-
│ ├── generate_simd.ts ← generates SIMD assembly variants
|
|
192
|
-
│ ├── gen-changelog.ts ← changelog generation
|
|
193
|
-
│ ├── copy-docs.ts ← copies docs subset to dist/
|
|
194
|
-
│ └── pin-actions.ts ← pins GitHub Actions to SHA hashes
|
|
195
|
-
├── docs/ ← project documentation + wiki source
|
|
196
|
-
├── package.json
|
|
197
|
-
├── asconfig.json ← four AssemblyScript entry points
|
|
198
|
-
├── tsconfig.json
|
|
199
|
-
├── vitest.config.ts
|
|
200
|
-
├── playwright.config.ts
|
|
201
|
-
├── AGENTS.md ← ai agent contract
|
|
202
|
-
└── SECURITY.md
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
---
|
|
206
|
-
|
|
207
|
-
## Architecture: TypeScript over WASM
|
|
208
|
-
|
|
209
|
-
The TypeScript layer never implements cryptographic algorithms. It manages the boundary between JavaScript and WebAssembly by writing inputs into WASM linear memory, calling exported functions, and reading back outputs. All algorithm logic resides within AssemblyScript.
|
|
210
|
-
|
|
211
|
-
Higher-level classes like `Seal`, `SealStream`, and `SealStreamPool` are pure TypeScript, but they compose WASM-backed primitives (Serpent-CBC, HMAC-SHA256, ChaCha20-Poly1305, and HKDF-SHA256) rather than implementing new cryptographic logic. TypeScript orchestrates, while WASM computes. Pool workers instantiate their own WASM modules and directly call primitives, bypassing the main-thread module cache.
|
|
212
|
-
|
|
213
|
-
---
|
|
214
|
-
|
|
215
|
-
## Five Independent WASM Modules
|
|
216
|
-
|
|
217
|
-
Each primitive family compiles to its own `.wasm` binary. Modules are fully
|
|
218
|
-
independent, separate linear memories, separate buffer layouts, no shared state.
|
|
219
|
-
|
|
220
|
-
| Module | Binary | Primitives |
|
|
221
|
-
|--------|--------|------------|
|
|
222
|
-
| `serpent` | `serpent.wasm` | Serpent-256 block cipher: ECB, CTR mode, CBC mode |
|
|
223
|
-
| `chacha20` | `chacha20.wasm` | ChaCha20, Poly1305, ChaCha20-Poly1305 AEAD, XChaCha20-Poly1305 AEAD |
|
|
224
|
-
| `sha2` | `sha2.wasm` | SHA-256, SHA-384, SHA-512, HMAC-SHA256, HMAC-SHA384, HMAC-SHA512 |
|
|
225
|
-
| `sha3` | `sha3.wasm` | SHA3-224, SHA3-256, SHA3-384, SHA3-512, SHAKE128, SHAKE256 |
|
|
226
|
-
| `kyber` | `kyber.wasm` | ML-KEM polynomial arithmetic: SIMD NTT/invNTT (v128 butterflies with scalar tail), basemul, Montgomery/Barrett, CBD, compress, CT verify/cmov |
|
|
227
|
-
|
|
228
|
-
**Size.** Consumers who only use Serpent don't load the SHA-3 binary.
|
|
229
|
-
|
|
230
|
-
**Isolation.** Key material in `serpent.wasm` memory cannot bleed into `sha3.wasm` memory even in theory.
|
|
231
|
-
|
|
232
|
-
Each module's buffer layout starts at offset 0 and is defined in its own
|
|
233
|
-
`buffers.ts`. Buffer layouts are fully independent across modules.
|
|
234
|
-
|
|
235
|
-
### Module contents
|
|
236
|
-
|
|
237
|
-
**`serpent.wasm`**
|
|
238
|
-
Serpent-256 block cipher. Key schedule, block encrypt, block decrypt. CTR mode
|
|
239
|
-
chunked streaming encrypt/decrypt. CBC mode chunked encrypt/decrypt. SIMD
|
|
240
|
-
variants for CTR 4-wide inter-block and CBC decrypt parallelism.
|
|
241
|
-
Source: `src/asm/serpent/`
|
|
242
|
-
|
|
243
|
-
The serpent TypeScript module includes `SerpentCipher` (CipherSuite implementation
|
|
244
|
-
for the STREAM construction: Serpent-CBC + HMAC-SHA256 with HKDF key derivation).
|
|
245
|
-
Requires `serpent` and `sha2` to be initialized.
|
|
246
|
-
|
|
247
|
-
**`chacha20.wasm`**
|
|
248
|
-
ChaCha20 stream cipher (RFC 8439). Poly1305 MAC (RFC 8439 §2.5). ChaCha20-Poly1305
|
|
249
|
-
AEAD (RFC 8439 §2.8). XChaCha20-Poly1305 AEAD (draft-irtf-cfrg-xchacha).
|
|
250
|
-
HChaCha20 subkey derivation. SIMD 4-wide inter-block parallelism.
|
|
251
|
-
Source: `src/asm/chacha20/`
|
|
252
|
-
|
|
253
|
-
The chacha20 TypeScript module includes `XChaCha20Cipher` (CipherSuite implementation
|
|
254
|
-
for the STREAM construction: XChaCha20-Poly1305 with HKDF key derivation).
|
|
255
|
-
Pool workers are internal, loaded by `SealStreamPool` at runtime, not registered in the package exports map.
|
|
256
|
-
|
|
257
|
-
**`sha2.wasm`**
|
|
258
|
-
SHA-256 and SHA-512 (FIPS 180-4). SHA-384 (SHA-512 with different IVs, truncated
|
|
259
|
-
output, shares all SHA-512 buffers and compress function). HMAC-SHA256,
|
|
260
|
-
HMAC-SHA512, HMAC-SHA384 (RFC 2104). HKDF-SHA256 and HKDF-SHA512 (RFC 5869)
|
|
261
|
-
are pure TypeScript compositions over HMAC, with no new WASM logic.
|
|
262
|
-
Source: `src/asm/sha2/`
|
|
263
|
-
|
|
264
|
-
**`sha3.wasm`**
|
|
265
|
-
Keccak-f[1600] permutation (FIPS 202). SHA3-224, SHA3-256, SHA3-384, SHA3-512.
|
|
266
|
-
SHAKE128, SHAKE256 (XOFs, multi-squeeze capable, unbounded output length).
|
|
267
|
-
All six variants share one permutation, differing only in rate, domain
|
|
268
|
-
separation byte, and output length.
|
|
269
|
-
Source: `src/asm/sha3/`
|
|
270
|
-
|
|
271
|
-
**`kyber.wasm`**
|
|
272
|
-
ML-KEM (FIPS 203) polynomial arithmetic. Montgomery and Barrett reduction,
|
|
273
|
-
7-layer NTT and inverse NTT, basemul in Z_q[X]/(X²-ζ), centered binomial
|
|
274
|
-
distribution sampling (η=2, η=3), division-free compression/decompression
|
|
275
|
-
(all 5 bit-width paths: 4, 5, 10, 11, 1-bit), rejection sampling for matrix
|
|
276
|
-
generation, constant-time byte comparison and conditional move. Requires
|
|
277
|
-
WebAssembly SIMD (`v128` instructions) for NTT and polynomial arithmetic.
|
|
278
|
-
3 pages (192 KB) linear memory with 10 poly slots, 8 polyvec slots, and
|
|
279
|
-
dedicated byte buffers for keys/ciphertexts.
|
|
280
|
-
Source: `src/asm/kyber/`
|
|
281
|
-
|
|
282
|
-
The kyber TypeScript module includes `MlKem512`, `MlKem768`, `MlKem1024`
|
|
283
|
-
(KEM classes implementing the Fujisaki-Okamoto transform). All require both
|
|
284
|
-
`kyber` and `sha3` to be initialized; the sha3 module provides the Keccak sponge (SHAKE128 for matrix gen, SHAKE256 for noise/J function, SHA3-256 for H, SHA3-512 for G).
|
|
285
|
-
|
|
286
|
-
---
|
|
287
|
-
|
|
288
|
-
## `init()` API
|
|
289
|
-
|
|
290
|
-
WASM instantiation is async. `init()` is the initialization gate, call it once before using any cryptographic class. The cost is explicit and the developer controls when it is paid.
|
|
291
|
-
|
|
292
|
-
### Signature
|
|
293
|
-
|
|
294
|
-
```typescript
|
|
295
|
-
type Module = 'serpent' | 'chacha20' | 'sha2' | 'sha3' | 'keccak' | 'kyber'
|
|
296
|
-
|
|
297
|
-
type WasmSource =
|
|
298
|
-
| string // gzip+base64 embedded blob
|
|
299
|
-
| URL // fetch + compileStreaming
|
|
300
|
-
| ArrayBuffer // compile from raw bytes
|
|
301
|
-
| Uint8Array // compile from raw bytes
|
|
302
|
-
| WebAssembly.Module // pre-compiled (edge runtimes)
|
|
303
|
-
| Response // instantiateStreaming
|
|
304
|
-
| Promise<Response> // deferred fetch
|
|
305
|
-
|
|
306
|
-
async function init(
|
|
307
|
-
sources: Partial<Record<Module, WasmSource>>,
|
|
308
|
-
): Promise<void>
|
|
309
|
-
```
|
|
310
|
-
|
|
311
|
-
The loading strategy is inferred from the source type, so there is no need
|
|
312
|
-
for a mode string. Each module also exports its own init function, such as
|
|
313
|
-
`serpentInit(source)`, `chacha20Init(source)`, `sha2Init(source)`,
|
|
314
|
-
`sha3Init(source)`, `keccakInit(source)`, and `kyberInit(source)`,
|
|
315
|
-
enabling tree-shakeable imports.
|
|
316
|
-
|
|
317
|
-
> [!NOTE]
|
|
318
|
-
> **`'keccak'` is an alias for `'sha3'`.** Both names are accepted by `init()`, `initModule()`, `getInstance()`, and `isInitialized()`. They share the same WASM binary and the same instance slot. The alias exists so Kyber/ML-KEM consumers can write `init({ keccak: keccakWasm })` using the semantically correct name for the underlying sponge primitive.
|
|
319
|
-
|
|
320
|
-
### Embedded subpath exports
|
|
321
|
-
|
|
322
|
-
Each module provides a `/embedded` subpath that exports the gzip+base64
|
|
323
|
-
blob as a ready-to-use `WasmSource`:
|
|
324
|
-
```typescript
|
|
325
|
-
import { init } from 'leviathan-crypto'
|
|
326
|
-
import { serpentWasm } from 'leviathan-crypto/serpent/embedded'
|
|
327
|
-
import { sha2Wasm } from 'leviathan-crypto/sha2/embedded'
|
|
328
|
-
|
|
329
|
-
await init({ serpent: serpentWasm, sha2: sha2Wasm })
|
|
330
|
-
```
|
|
331
|
-
|
|
332
|
-
### Behavioral contracts
|
|
333
|
-
|
|
334
|
-
**Idempotent initialization.** Calling `init()` on an already initialized
|
|
335
|
-
module is a no-op. It is safe to call `init()` from multiple locations
|
|
336
|
-
within the codebase.
|
|
337
|
-
|
|
338
|
-
**Module-scope cache.** Each `WebAssembly.Instance` is cached at module
|
|
339
|
-
scope after initial instantiation. All subsequent class constructions use
|
|
340
|
-
the cached instance with no recompilation.
|
|
341
|
-
|
|
342
|
-
**Error before initialization.** Invoking any cryptographic class before
|
|
343
|
-
calling `init()` throws a clear error prompting the developer to call
|
|
344
|
-
`init({ <module>: ... })` first.
|
|
345
|
-
|
|
346
|
-
**No implicit initialization.** Classes never call `init()` automatically
|
|
347
|
-
on first use. Explicit initialization is preferable to hidden costs.
|
|
348
|
-
|
|
349
|
-
**Thread safety.** The main thread uses a single WASM instance per module.
|
|
350
|
-
`SealStreamPool` provides worker-based parallelism. Each pool worker owns
|
|
351
|
-
its own WASM instances with isolated linear memory, bypassing the main-thread
|
|
352
|
-
cache entirely. For other primitives, create one instance per Worker if
|
|
353
|
-
Workers are used.
|
|
354
|
-
|
|
355
|
-
---
|
|
356
|
-
|
|
357
|
-
## Public API Classes
|
|
358
|
-
|
|
359
|
-
Names match conventional cryptographic notation.
|
|
360
|
-
|
|
361
|
-
| Module | Classes |
|
|
362
|
-
|--------|---------|
|
|
363
|
-
| `serpent` + `sha2` | `SerpentCipher` |
|
|
364
|
-
| `serpent` | `Serpent`, `SerpentCtr`, `SerpentCbc` |
|
|
365
|
-
| `chacha20` | `ChaCha20`, `Poly1305`, `ChaCha20Poly1305`, `XChaCha20Poly1305`, `XChaCha20Cipher` |
|
|
366
|
-
| `sha2` | `SHA256`, `SHA384`, `SHA512`, `HMAC_SHA256`, `HMAC_SHA384`, `HMAC_SHA512`, `HKDF_SHA256`, `HKDF_SHA512` |
|
|
367
|
-
| `sha3` | `SHA3_224`, `SHA3_256`, `SHA3_384`, `SHA3_512`, `SHAKE128`, `SHAKE256` |
|
|
368
|
-
| `kyber` + `sha3` | `MlKem512`, `MlKem768`, `MlKem1024` |
|
|
369
|
-
| `kyber` + `sha3` + inner cipher | `KyberSuite` (hybrid KEM+AEAD factory) |
|
|
370
|
-
| `stream` | `Seal`, `SealStream`, `OpenStream`, `SealStreamPool` |
|
|
371
|
-
| `serpent` + `sha2` | `Fortuna` |
|
|
372
|
-
|
|
373
|
-
HMAC names use underscore separator (`HMAC_SHA256`) matching RFC convention.
|
|
374
|
-
SHA-3 names use underscore separator (`SHA3_256`) for readability.
|
|
375
|
-
`SealStream`, `OpenStream`, and `SealStreamPool` are cipher-agnostic; you select the cipher by passing `XChaCha20Cipher` or `SerpentCipher` at construction.
|
|
376
|
-
|
|
377
|
-
**`Fortuna`** requires `await Fortuna.create()` rather than `new Fortuna()` due
|
|
378
|
-
to the async `init()` dependency on two modules.
|
|
379
|
-
|
|
380
|
-
### Usage pattern
|
|
381
|
-
|
|
382
|
-
All WASM-backed classes follow the same pattern:
|
|
383
|
-
```typescript
|
|
384
|
-
import { init, Seal, SerpentCipher, SHA3_256 } from 'leviathan-crypto'
|
|
385
|
-
import { serpentWasm } from 'leviathan-crypto/serpent/embedded'
|
|
386
|
-
import { sha2Wasm } from 'leviathan-crypto/sha2/embedded'
|
|
387
|
-
import { sha3Wasm } from 'leviathan-crypto/sha3/embedded'
|
|
388
|
-
|
|
389
|
-
await init({ serpent: serpentWasm, sha2: sha2Wasm, sha3: sha3Wasm })
|
|
390
|
-
|
|
391
|
-
const key = SerpentCipher.keygen()
|
|
392
|
-
const blob = Seal.encrypt(SerpentCipher, key, plaintext)
|
|
393
|
-
|
|
394
|
-
const hasher = new SHA3_256()
|
|
395
|
-
const digest = hasher.hash(message)
|
|
396
|
-
```
|
|
397
|
-
|
|
398
|
-
### Utility exports (no `init()` required)
|
|
399
|
-
|
|
400
|
-
Pure TypeScript utilities ship alongside the WASM-backed primitives:
|
|
401
|
-
|
|
402
|
-
| Category | Exports |
|
|
403
|
-
|----------|---------|
|
|
404
|
-
| Encoding | `hexToBytes`, `bytesToHex`, `utf8ToBytes`, `bytesToUtf8`, `base64ToBytes`, `bytesToBase64` |
|
|
405
|
-
| Security | `constantTimeEqual`, `wipe`, `xor` |
|
|
406
|
-
| Helpers | `concat`, `randomBytes` |
|
|
407
|
-
| Types | `Hash`, `KeyedHash`, `Blockcipher`, `Streamcipher`, `AEAD` |
|
|
408
|
-
|
|
409
|
-
---
|
|
410
|
-
|
|
411
|
-
## Build Pipeline
|
|
412
|
-
|
|
413
|
-
1. `npm run build:asm`: AssemblyScript compiler reads `src/asm/*/index.ts`, emits `build/*.wasm`
|
|
414
|
-
2. `npm run build:embed`: `scripts/embed-wasm.ts` reads each `.wasm`, gzip compresses, base64 encodes, writes to `src/ts/embedded/*.ts` and per-module `src/ts/*/embedded.ts`
|
|
415
|
-
3. `npm run build:ts`: TypeScript compiler emits `dist/`
|
|
416
|
-
4. `cp build/*.wasm dist/`: WASM binaries copied for URL-based consumers
|
|
417
|
-
5. At runtime (subpath): `serpentInit(serpentWasm)` → `initModule()` → `loadWasm(source)` → decode gzip+base64 → `WebAssembly.instantiate` → cache in `init.ts`
|
|
418
|
-
6. At runtime (root): `init({ serpent: serpentWasm, sha2: sha2Wasm })` → dispatches to each module's init function via `Promise.all` → same path as step 5 per module
|
|
419
|
-
|
|
420
|
-
`src/ts/embedded/` is gitignored; these files are build artifacts derived from the WASM binaries. There is one source of truth for each binary: the AssemblyScript source.
|
|
421
|
-
|
|
422
|
-
---
|
|
423
|
-
|
|
424
|
-
## Module Relationship Diagrams
|
|
425
|
-
|
|
426
|
-
### ASM layer: internal import graph
|
|
427
|
-
|
|
428
|
-
Each WASM module is fully independent. No cross-module imports exist.
|
|
429
|
-
|
|
430
|
-
**Serpent (`src/asm/serpent/`)**
|
|
431
|
-
```
|
|
432
|
-
buffers.ts
|
|
433
|
-
<- serpent.ts (offsets for key, block, subkey, work, CBC IV)
|
|
434
|
-
<- serpent_unrolled.ts (block offsets, subkey, work)
|
|
435
|
-
<- serpent_simd.ts (SIMD bitsliced block operations)
|
|
436
|
-
<- cbc.ts (IV, block, chunk offsets)
|
|
437
|
-
<- cbc_simd.ts (SIMD CBC decrypt)
|
|
438
|
-
<- ctr.ts (nonce, counter, block, chunk offsets)
|
|
439
|
-
<- ctr_simd.ts (SIMD CTR 4-wide inter-block)
|
|
440
|
-
|
|
441
|
-
serpent.ts
|
|
442
|
-
<- serpent_unrolled.ts (S-boxes sb0-sb7, si0-si7, lk, kl, keyXor)
|
|
443
|
-
|
|
444
|
-
serpent_unrolled.ts
|
|
445
|
-
<- cbc.ts (encryptBlock_unrolled, decryptBlock_unrolled)
|
|
446
|
-
<- ctr.ts (encryptBlock_unrolled)
|
|
447
|
-
|
|
448
|
-
serpent_simd.ts
|
|
449
|
-
<- cbc_simd.ts (SIMD block operations)
|
|
450
|
-
<- ctr_simd.ts (SIMD block operations)
|
|
451
|
-
|
|
452
|
-
index.ts
|
|
453
|
-
re-exports: buffers + serpent + serpent_unrolled + serpent_simd + cbc + cbc_simd + ctr + ctr_simd
|
|
454
|
-
```
|
|
455
|
-
|
|
456
|
-
**ChaCha (`src/asm/chacha20/`)**
|
|
457
|
-
```
|
|
458
|
-
buffers.ts
|
|
459
|
-
<- chacha20.ts (key, nonce, counter, block, state, poly key, xchacha offsets)
|
|
460
|
-
<- chacha20_simd_4x.ts (SIMD work buffer, chunk offsets)
|
|
461
|
-
<- poly1305.ts (poly key, msg, buf, tag, h, r, rs, s offsets)
|
|
462
|
-
<- wipe.ts (all buffer offsets, zeroes everything)
|
|
463
|
-
|
|
464
|
-
index.ts
|
|
465
|
-
re-exports: buffers + chacha20 + chacha20_simd_4x + poly1305 + wipe
|
|
466
|
-
```
|
|
467
|
-
|
|
468
|
-
**SHA-2 (`src/asm/sha2/`)**
|
|
469
|
-
|
|
470
|
-
```
|
|
471
|
-
buffers.ts
|
|
472
|
-
<- sha256.ts (H, block, W, out, input, partial, total offsets)
|
|
473
|
-
<- sha512.ts (H, block, W, out, input, partial, total offsets)
|
|
474
|
-
<- hmac.ts (SHA-256 input, out, ipad, opad, inner offsets)
|
|
475
|
-
<- hmac512.ts (SHA-512 input, out, ipad, opad, inner offsets)
|
|
476
|
-
|
|
477
|
-
sha256.ts
|
|
478
|
-
<- hmac.ts (sha256Init, sha256Update, sha256Final)
|
|
479
|
-
|
|
480
|
-
sha512.ts
|
|
481
|
-
<- hmac512.ts (sha512Init, sha384Init, sha512Update, sha512Final, sha384Final)
|
|
482
|
-
|
|
483
|
-
index.ts
|
|
484
|
-
re-exports: buffers + sha256 + sha512 + hmac + hmac512
|
|
485
|
-
defines: wipeBuffers() inline
|
|
486
|
-
```
|
|
487
|
-
|
|
488
|
-
**SHA-3 (`src/asm/sha3/`)**
|
|
489
|
-
|
|
490
|
-
```
|
|
491
|
-
buffers.ts
|
|
492
|
-
<- keccak.ts (state, rate, absorbed, dsbyte, input, out offsets)
|
|
493
|
-
|
|
494
|
-
index.ts
|
|
495
|
-
re-exports: buffers + keccak
|
|
496
|
-
```
|
|
497
|
-
|
|
498
|
-
**Kyber (`src/asm/kyber/`)**
|
|
499
|
-
|
|
500
|
-
```
|
|
501
|
-
params.ts
|
|
502
|
-
<- reduce.ts (Q, QINV, BARRETT_V, BARRETT_SHIFT)
|
|
503
|
-
<- poly.ts (Q, POLY_BYTES, HALF_Q, compression constants)
|
|
504
|
-
<- polyvec.ts (Q, POLY_BYTES, compression constants)
|
|
505
|
-
<- sampling.ts (Q)
|
|
506
|
-
|
|
507
|
-
buffers.ts
|
|
508
|
-
<- polyvec.ts (POLY_ACC_OFFSET)
|
|
509
|
-
|
|
510
|
-
reduce.ts
|
|
511
|
-
<- ntt.ts (fqmul, barrett_reduce)
|
|
512
|
-
<- ntt_simd.ts (fqmul, barrett_reduce — scalar tail)
|
|
513
|
-
<- poly.ts (montgomery_reduce, barrett_reduce, fqmul)
|
|
514
|
-
|
|
515
|
-
ntt.ts
|
|
516
|
-
<- ntt_simd.ts (getZetasOffset — zetas table pointer)
|
|
517
|
-
<- poly.ts (ntt, invntt, basemul, getZeta)
|
|
518
|
-
|
|
519
|
-
ntt_simd.ts
|
|
520
|
-
<- poly_simd.ts (ntt_simd, invntt_simd, barrett_reduce_8x)
|
|
521
|
-
|
|
522
|
-
poly.ts
|
|
523
|
-
<- polyvec.ts (poly_tobytes, poly_frombytes, poly_basemul_montgomery)
|
|
524
|
-
|
|
525
|
-
poly_simd.ts
|
|
526
|
-
<- polyvec.ts (poly_add_simd, poly_reduce_simd, poly_ntt_simd, poly_invntt_simd)
|
|
527
|
-
|
|
528
|
-
cbd.ts
|
|
529
|
-
<- poly.ts (cbd2, cbd3)
|
|
530
|
-
|
|
531
|
-
index.ts
|
|
532
|
-
re-exports: buffers + ntt (scalar aliases) + ntt_simd (as ntt/invntt) +
|
|
533
|
-
reduce + poly (scalar serialization/compression/basemul) +
|
|
534
|
-
poly_simd (as poly_add/sub/reduce/ntt/invntt) +
|
|
535
|
-
polyvec + sampling + verify
|
|
536
|
-
```
|
|
537
|
-
|
|
538
|
-
---
|
|
539
|
-
|
|
540
|
-
### TS layer: internal import graph
|
|
541
|
-
|
|
542
|
-
```
|
|
543
|
-
+---------------------+
|
|
544
|
-
| index.ts | <- barrel: dispatching init()
|
|
545
|
-
| (public API root) | + re-exports everything
|
|
546
|
-
+--+--+--+--+--+--+--+
|
|
547
|
-
| | | | | |
|
|
548
|
-
+-------------------------+ | | | | +----------------------+
|
|
549
|
-
| +----------------+ | | +----------+ |
|
|
550
|
-
v v v v v v
|
|
551
|
-
serpent/ chacha20/ sha2/ sha3/ fortuna.ts stream/
|
|
552
|
-
index.ts index.ts index.ts index.ts index.ts
|
|
553
|
-
| | | | | | |
|
|
554
|
-
| | +-> ops.ts | | +-> init.ts |
|
|
555
|
-
| | | | +-> serpent/ |
|
|
556
|
-
| +-> cipher- | | +-> sha2/ +-> seal-stream.ts
|
|
557
|
-
| suite.ts | | +-> utils.ts +-> open-stream.ts
|
|
558
|
-
+-> cipher- | | | +-> seal-stream-pool.ts
|
|
559
|
-
suite.ts +-> pool- +-> hkdf.ts +-> header.ts
|
|
560
|
-
| worker.ts +-> constants.ts
|
|
561
|
-
+-> pool- | +-> types.ts
|
|
562
|
-
worker.ts |
|
|
563
|
-
|
|
|
564
|
-
All module index.ts files ──────────────────────────> init.ts <── getInstance()
|
|
565
|
-
initModule()
|
|
566
|
-
All */embedded.ts files ──────────────────────────> embedded/*.ts (gzip+base64 blobs)
|
|
567
|
-
```
|
|
568
|
-
|
|
569
|
-
Each module's init function (`serpentInit`, `chacha20Init`, `sha2Init`,
|
|
570
|
-
`sha3Init`, `kyberInit`) calls `initModule()` from `init.ts`, passing a `WasmSource`.
|
|
571
|
-
`initModule()` delegates to `loadWasm(source)` in `loader.ts`. The loader
|
|
572
|
-
infers the loading strategy from the source type, with no mode string and no knowledge of module names or embedded file paths.
|
|
573
|
-
|
|
574
|
-
Pool workers (`serpent/pool-worker.ts`, `chacha20/pool-worker.ts`) instantiate
|
|
575
|
-
their own WASM modules from pre-compiled `WebAssembly.Module` objects passed
|
|
576
|
-
via `postMessage`. They do not use `initModule()` or the main-thread cache.
|
|
577
|
-
|
|
578
|
-
---
|
|
579
|
-
|
|
580
|
-
### TS-to-WASM mapping
|
|
581
|
-
|
|
582
|
-
Each TS wrapper class maps to one WASM module and specific exported functions.
|
|
583
|
-
Tier 2 composition classes are pure TypeScript; they call Tier 1 classes rather than WASM functions directly.
|
|
584
|
-
|
|
585
|
-
**serpent/index.ts → asm/serpent/ (Tier 1: direct WASM callers)**
|
|
586
|
-
|
|
587
|
-
| TS Class | WASM functions called |
|
|
588
|
-
|----------|---------------------|
|
|
589
|
-
| `Serpent` | `loadKey`, `encryptBlock`, `decryptBlock`, `wipeBuffers` + buffer getters |
|
|
590
|
-
| `SerpentCtr` | `loadKey`, `resetCounter`, `setCounter`, `encryptChunk`, `encryptChunk_simd`, `wipeBuffers` + buffer getters |
|
|
591
|
-
| `SerpentCbc` | `loadKey`, `cbcEncryptChunk`, `cbcDecryptChunk`, `cbcDecryptChunk_simd`, `wipeBuffers` + buffer getters |
|
|
592
|
-
|
|
593
|
-
**chacha20/index.ts → asm/chacha20/ (Tier 1: direct WASM callers)**
|
|
594
|
-
|
|
595
|
-
| TS Class | WASM functions called |
|
|
596
|
-
|----------|---------------------|
|
|
597
|
-
| `ChaCha20` | `chachaLoadKey`, `chachaSetCounter`, `chachaEncryptChunk`, `chachaEncryptChunk_simd`, `wipeBuffers` + buffer getters |
|
|
598
|
-
| `Poly1305` | `polyInit`, `polyUpdate`, `polyFinal`, `wipeBuffers` + buffer getters |
|
|
599
|
-
| `ChaCha20Poly1305` | `chachaLoadKey`, `chachaSetCounter`, `chachaGenPolyKey`, `chachaEncryptChunk`, `polyInit`, `polyUpdate`, `polyFinal`, `wipeBuffers` + buffer getters (via `ops.ts`) |
|
|
600
|
-
| `XChaCha20Poly1305` | All of `ChaCha20Poly1305` + `hchacha20` + xchacha buffer getters (via `ops.ts`) |
|
|
601
|
-
|
|
602
|
-
**sha2/index.ts → asm/sha2/ (Tier 1: direct WASM callers)**
|
|
603
|
-
|
|
604
|
-
| TS Class | WASM functions called |
|
|
605
|
-
|----------|---------------------|
|
|
606
|
-
| `SHA256` | `sha256Init`, `sha256Update`, `sha256Final`, `wipeBuffers` + buffer getters |
|
|
607
|
-
| `SHA512` | `sha512Init`, `sha512Update`, `sha512Final`, `wipeBuffers` + buffer getters |
|
|
608
|
-
| `SHA384` | `sha384Init`, `sha512Update`, `sha384Final`, `wipeBuffers` + buffer getters |
|
|
609
|
-
| `HMAC_SHA256` | `hmac256Init`, `hmac256Update`, `hmac256Final`, `sha256Init`, `sha256Update`, `sha256Final`, `wipeBuffers` + buffer getters |
|
|
610
|
-
| `HMAC_SHA512` | `hmac512Init`, `hmac512Update`, `hmac512Final`, `sha512Init`, `sha512Update`, `sha512Final`, `wipeBuffers` + buffer getters |
|
|
611
|
-
| `HMAC_SHA384` | `hmac384Init`, `hmac384Update`, `hmac384Final`, `sha384Init`, `sha512Update`, `sha384Final`, `wipeBuffers` + buffer getters |
|
|
612
|
-
|
|
613
|
-
**sha3/index.ts → asm/sha3/ (Tier 1: direct WASM callers)**
|
|
614
|
-
|
|
615
|
-
| TS Class | WASM functions called |
|
|
616
|
-
|----------|---------------------|
|
|
617
|
-
| `SHA3_224` | `sha3_224Init`, `keccakAbsorb`, `sha3_224Final`, `wipeBuffers` + buffer getters |
|
|
618
|
-
| `SHA3_256` | `sha3_256Init`, `keccakAbsorb`, `sha3_256Final`, `wipeBuffers` + buffer getters |
|
|
619
|
-
| `SHA3_384` | `sha3_384Init`, `keccakAbsorb`, `sha3_384Final`, `wipeBuffers` + buffer getters |
|
|
620
|
-
| `SHA3_512` | `sha3_512Init`, `keccakAbsorb`, `sha3_512Final`, `wipeBuffers` + buffer getters |
|
|
621
|
-
| `SHAKE128` | `shake128Init`, `keccakAbsorb`, `shakePad`, `shakeSqueezeBlock`, `wipeBuffers` + buffer getters |
|
|
622
|
-
| `SHAKE256` | `shake256Init`, `keccakAbsorb`, `shakePad`, `shakeSqueezeBlock`, `wipeBuffers` + buffer getters |
|
|
623
|
-
|
|
624
|
-
**kyber/index.ts + kyber/kem.ts + kyber/indcpa.ts → asm/kyber/ (Tier 1)**
|
|
625
|
-
|
|
626
|
-
| TS Class | WASM functions called |
|
|
627
|
-
|----------|---------------------|
|
|
628
|
-
| `MlKem512`, `MlKem768`, `MlKem1024` | `polyvec_ntt`, `polyvec_invntt`, `polyvec_basemul_acc_montgomery`, `polyvec_add`, `polyvec_reduce`, `polyvec_tobytes`, `polyvec_frombytes`, `polyvec_compress`, `polyvec_decompress`, `poly_ntt`, `poly_invntt`, `poly_tomont`, `poly_add`, `poly_sub`, `poly_reduce`, `poly_basemul_montgomery`, `poly_frommsg`, `poly_tomsg`, `poly_compress`, `poly_decompress`, `poly_getnoise`, `rej_uniform`, `ct_verify`, `ct_cmov`, `wipeBuffers` + buffer getters |
|
|
629
|
-
|
|
630
|
-
All MlKem classes also call sha3 WASM via `indcpa.ts`: `sha3_256Init`, `sha3_512Init`, `shake128Init`, `shake256Init`, `keccakAbsorb`, `sha3_256Final`, `sha3_512Final`, `shakeFinal`, `shakePad`, `shakeSqueezeBlock`.
|
|
631
|
-
|
|
632
|
-
**Tier 2: pure TS composition**
|
|
633
|
-
|
|
634
|
-
| TS Class / Object | Composes |
|
|
635
|
-
|--------------------|----------|
|
|
636
|
-
| `SerpentCipher` | `SerpentCbc` + `HMAC_SHA256` + `HKDF_SHA256` |
|
|
637
|
-
| `XChaCha20Cipher` | `ChaCha20Poly1305` (via `ops.ts`) + `HKDF_SHA256` |
|
|
638
|
-
| `Seal` | `SealStream` + `OpenStream` (degenerate single-chunk case) |
|
|
639
|
-
| `SealStream` | `CipherSuite` (generic — caller provides cipher) |
|
|
640
|
-
| `OpenStream` | `CipherSuite` (generic — caller provides cipher) |
|
|
641
|
-
| `SealStreamPool` | `CipherSuite` + `compileWasm()` + Web Workers |
|
|
642
|
-
| `HKDF_SHA256` | `HMAC_SHA256` (extract + expand per RFC 5869) |
|
|
643
|
-
| `HKDF_SHA512` | `HMAC_SHA512` (extract + expand per RFC 5869) |
|
|
644
|
-
| `Fortuna` | `Serpent` + `SHA256` |
|
|
645
|
-
|
|
646
|
-
---
|
|
647
|
-
|
|
648
|
-
### Cross-module dependencies
|
|
649
|
-
|
|
650
|
-
| Relationship | Notes |
|
|
651
|
-
|-------------|-------|
|
|
652
|
-
| `SerpentCipher` → `serpent` + `sha2` | Tier 2 composition: Serpent-CBC + HMAC-SHA256 + HKDF-SHA256. |
|
|
653
|
-
| `XChaCha20Cipher` → `chacha20` + `sha2` | HKDF-SHA256 for key derivation + HChaCha20 + ChaCha20-Poly1305 for per-chunk AEAD. |
|
|
654
|
-
| `KyberSuite` → `kyber` + `sha3` + inner cipher | KEM encaps/decaps + HKDF with kemCt binding + inner CipherSuite. |
|
|
655
|
-
| `SealStream`, `OpenStream` → depends on cipher | Cipher-agnostic. Module requirements are determined by the `CipherSuite` passed at construction. |
|
|
656
|
-
| `SealStreamPool` → depends on cipher | Same module requirements as the cipher, plus `WasmSource` in pool opts for worker compilation. |
|
|
657
|
-
| `Fortuna` → `serpent` + `sha2` | Uses `Fortuna.create()` static factory instead of `new`. |
|
|
658
|
-
| `MlKem512`, `MlKem768`, `MlKem1024` → `kyber` + `sha3` | Kyber module handles polynomial arithmetic; sha3 provides SHAKE128/256, SHA3-256/512 for G/H/J/matrix gen. |
|
|
659
|
-
| `HKDF_SHA256`, `HKDF_SHA512` → `sha2` | Pure TS composition — extract and expand steps per RFC 5869. |
|
|
660
|
-
| All other classes | Each depends on exactly **one** WASM module. |
|
|
661
|
-
|
|
662
|
-
---
|
|
663
|
-
|
|
664
|
-
### Public API barrel (`src/ts/index.ts`)
|
|
665
|
-
|
|
666
|
-
The root barrel defines and exports the dispatching `init()` function.
|
|
667
|
-
It is the only file that imports all four module-scoped init functions.
|
|
668
|
-
|
|
669
|
-
| Source | Exports |
|
|
670
|
-
|--------|------------|
|
|
671
|
-
| *(barrel itself)* | `init` (dispatching function — calls per-module init functions via `Promise.all`) |
|
|
672
|
-
| `init.ts` | `Module`, `WasmSource`, `isInitialized`, `_resetForTesting` |
|
|
673
|
-
| `errors.ts` | `AuthenticationError` |
|
|
674
|
-
| `serpent/index.ts` | `Serpent`, `SerpentCtr`, `SerpentCbc`, `SerpentCipher`, `_serpentReady` |
|
|
675
|
-
| `chacha20/index.ts` | `ChaCha20`, `Poly1305`, `ChaCha20Poly1305`, `XChaCha20Poly1305`, `XChaCha20Cipher`, `_chachaReady` |
|
|
676
|
-
| `sha2/index.ts` | `SHA256`, `SHA512`, `SHA384`, `HMAC_SHA256`, `HMAC_SHA512`, `HMAC_SHA384`, `HKDF_SHA256`, `HKDF_SHA512`, `_sha2Ready` |
|
|
677
|
-
| `sha3/index.ts` | `SHA3_224`, `SHA3_256`, `SHA3_384`, `SHA3_512`, `SHAKE128`, `SHAKE256`, `_sha3Ready` |
|
|
678
|
-
| `keccak/index.ts` | `keccakInit` + re-exports all sha3 classes (alias subpath) |
|
|
679
|
-
| `kyber/index.ts` | `kyberInit`, `KyberSuite`, `MlKem512`, `MlKem768`, `MlKem1024`, `KyberKeyPair`, `KyberEncapsulation`, `KyberParams`, `MLKEM512`, `MLKEM768`, `MLKEM1024` |
|
|
680
|
-
| `stream/index.ts` | `Seal`, `SealStream`, `OpenStream`, `SealStreamPool`, `CipherSuite`, `DerivedKeys`, `SealStreamOpts`, `PoolOpts`, `FLAG_FRAMED`, `TAG_DATA`, `TAG_FINAL`, `HEADER_SIZE`, `CHUNK_MIN`, `CHUNK_MAX` |
|
|
681
|
-
| `fortuna.ts` | `Fortuna` |
|
|
682
|
-
| `types.ts` | `Hash`, `KeyedHash`, `Blockcipher`, `Streamcipher`, `AEAD` |
|
|
683
|
-
| `utils.ts` | `hexToBytes`, `bytesToHex`, `utf8ToBytes`, `bytesToUtf8`, `base64ToBytes`, `bytesToBase64`, `constantTimeEqual`, `wipe`, `xor`, `concat`, `randomBytes` |
|
|
684
|
-
|
|
685
|
-
Each subpath export also exports its own module-specific init function for
|
|
686
|
-
tree-shakeable loading: `serpentInit(source)`, `chacha20Init(source)`,
|
|
687
|
-
`sha2Init(source)`, `sha3Init(source)`, `keccakInit(source)`.
|
|
688
|
-
|
|
689
|
-
---
|
|
690
|
-
|
|
691
|
-
## npm Package
|
|
692
|
-
|
|
693
|
-
**Subpath exports:**
|
|
694
|
-
```json
|
|
695
|
-
{
|
|
696
|
-
"exports": {
|
|
697
|
-
".": "./dist/index.js",
|
|
698
|
-
"./stream": "./dist/stream/index.js",
|
|
699
|
-
"./serpent": "./dist/serpent/index.js",
|
|
700
|
-
"./serpent/embedded": "./dist/serpent/embedded.js",
|
|
701
|
-
"./chacha20": "./dist/chacha20/index.js",
|
|
702
|
-
"./chacha20/embedded": "./dist/chacha20/embedded.js",
|
|
703
|
-
"./sha2": "./dist/sha2/index.js",
|
|
704
|
-
"./sha2/embedded": "./dist/sha2/embedded.js",
|
|
705
|
-
"./sha3": "./dist/sha3/index.js",
|
|
706
|
-
"./sha3/embedded": "./dist/sha3/embedded.js",
|
|
707
|
-
"./keccak": "./dist/keccak/index.js",
|
|
708
|
-
"./keccak/embedded": "./dist/keccak/embedded.js",
|
|
709
|
-
"./kyber": "./dist/kyber/index.js",
|
|
710
|
-
"./kyber/embedded": "./dist/kyber/embedded.js"
|
|
711
|
-
}
|
|
712
|
-
}
|
|
713
|
-
```
|
|
714
|
-
|
|
715
|
-
> [!NOTE]
|
|
716
|
-
> Pool worker files (`dist/serpent/pool-worker.js`, `dist/chacha20/pool-worker.js`)
|
|
717
|
-
> ship in the package but are not in the `exports` map. They are internal Web
|
|
718
|
-
> Worker entry points loaded by `SealStreamPool` at runtime via
|
|
719
|
-
> `new URL('./pool-worker.js', import.meta.url)`. Do not import them as named
|
|
720
|
-
> subpaths.
|
|
721
|
-
|
|
722
|
-
The root `.` export re-exports everything. Subpath exports allow bundlers to tree-shake at the module level; a consumer importing only `./sha3` does not include the Serpent wrapper classes or their embedded WASM binaries in their bundle.
|
|
723
|
-
|
|
724
|
-
The `/embedded` subpaths provide gzip+base64 WASM blobs for zero-config usage. Consumers using URL-based or pre-compiled loading can skip the `/embedded` imports entirely, keeping them out of the bundle.
|
|
725
|
-
|
|
726
|
-
**Tree-shaking:** `"sideEffects": false` is set in `package.json`. Bundlers that support tree-shaking (webpack, Rollup, esbuild) can eliminate unused modules and their embedded WASM binaries from the final bundle.
|
|
727
|
-
|
|
728
|
-
**Published.** The npm package includes:
|
|
729
|
-
|
|
730
|
-
- `dist/`: compiled JS, TypeScript declarations, WASM binaries, pool worker scripts, and a subset of consumer-facing API docs for offline use.
|
|
731
|
-
- `CLAUDE.md`: agent-facing project context.
|
|
732
|
-
- `SECURITY.md`: vulnerability disclosure policy.
|
|
733
|
-
|
|
734
|
-
**Not published.** `src/`, `test/`, `build/`, `scripts/`, `docs/`, `.github/`, editor configs.
|
|
735
|
-
|
|
736
|
-
---
|
|
737
|
-
|
|
738
|
-
## Buffer Layouts
|
|
739
|
-
|
|
740
|
-
All offsets start at 0 per module. Independent linear memory. No offsets are
|
|
741
|
-
shared or coordinated across modules.
|
|
742
|
-
|
|
743
|
-
### Serpent module (3 pages, 192 KB)
|
|
744
|
-
|
|
745
|
-
Source: `src/asm/serpent/buffers.ts`
|
|
746
|
-
|
|
747
|
-
| Offset | Size | Name |
|
|
748
|
-
|--------|------|------|
|
|
749
|
-
| 0 | 32 | `KEY_BUFFER` — key input (padded to 32 bytes for all key sizes) |
|
|
750
|
-
| 32 | 16 | `BLOCK_PT_BUFFER` — single block plaintext |
|
|
751
|
-
| 48 | 16 | `BLOCK_CT_BUFFER` — single block ciphertext |
|
|
752
|
-
| 64 | 16 | `NONCE_BUFFER` — CTR mode nonce |
|
|
753
|
-
| 80 | 16 | `COUNTER_BUFFER` — 128-bit little-endian counter |
|
|
754
|
-
| 96 | 528 | `SUBKEY_BUFFER` — key schedule output (33 rounds × 4 × 4 bytes) |
|
|
755
|
-
| 624 | 65552 | `CHUNK_PT_BUFFER` — streaming plaintext (CTR/CBC); +16 from 65536 to fit PKCS7 max overhead |
|
|
756
|
-
| 66176 | 65552 | `CHUNK_CT_BUFFER` — streaming ciphertext (CTR/CBC) |
|
|
757
|
-
| 131728 | 20 | `WORK_BUFFER` — 5 × i32 scratch registers (key schedule + S-box/LT rounds) |
|
|
758
|
-
| 131748 | 16 | `CBC_IV_BUFFER` — CBC initialization vector / chaining value |
|
|
759
|
-
| 131856 | — | END |
|
|
760
|
-
|
|
761
|
-
`wipeBuffers()` zeroes all 10 buffers (key, block pt/ct, nonce, counter, subkeys, work, chunk pt/ct, CBC IV).
|
|
762
|
-
|
|
763
|
-
### ChaCha20 module (3 pages, 192 KB)
|
|
764
|
-
|
|
765
|
-
Source: `src/asm/chacha20/buffers.ts`
|
|
766
|
-
|
|
767
|
-
| Offset | Size | Name |
|
|
768
|
-
|--------|------|------|
|
|
769
|
-
| 0 | 32 | `KEY_BUFFER` — ChaCha20 256-bit key |
|
|
770
|
-
| 32 | 12 | `CHACHA_NONCE_BUFFER` — 96-bit nonce (3 × u32, LE) |
|
|
771
|
-
| 44 | 4 | `CHACHA_CTR_BUFFER` — u32 block counter |
|
|
772
|
-
| 48 | 64 | `CHACHA_BLOCK_BUFFER` — 64-byte keystream block output |
|
|
773
|
-
| 112 | 64 | `CHACHA_STATE_BUFFER` — 16 × u32 initial state |
|
|
774
|
-
| 176 | 65536 | `CHUNK_PT_BUFFER` — streaming plaintext |
|
|
775
|
-
| 65712 | 65536 | `CHUNK_CT_BUFFER` — streaming ciphertext |
|
|
776
|
-
| 131248 | 32 | `POLY_KEY_BUFFER` — one-time key r‖s |
|
|
777
|
-
| 131280 | 64 | `POLY_MSG_BUFFER` — message staging (≤ 64 bytes per polyUpdate) |
|
|
778
|
-
| 131344 | 16 | `POLY_BUF_BUFFER` — partial block accumulator |
|
|
779
|
-
| 131360 | 4 | `POLY_BUF_LEN_BUFFER` — u32 bytes in partial block |
|
|
780
|
-
| 131364 | 16 | `POLY_TAG_BUFFER` — 16-byte output MAC tag |
|
|
781
|
-
| 131380 | 40 | `POLY_H_BUFFER` — accumulator h: 5 × u64 |
|
|
782
|
-
| 131420 | 40 | `POLY_R_BUFFER` — clamped r: 5 × u64 |
|
|
783
|
-
| 131460 | 32 | `POLY_RS_BUFFER` — precomputed 5×r[1..4]: 4 × u64 |
|
|
784
|
-
| 131492 | 16 | `POLY_S_BUFFER` — s pad: 4 × u32 |
|
|
785
|
-
| 131508 | 24 | `XCHACHA_NONCE_BUFFER` — full 24-byte XChaCha20 nonce |
|
|
786
|
-
| 131532 | 32 | `XCHACHA_SUBKEY_BUFFER` — HChaCha20 output (key material) |
|
|
787
|
-
| 131564 | 4 | *(padding for 16-byte SIMD alignment)* |
|
|
788
|
-
| 131568 | 256 | `CHACHA_SIMD_WORK_BUFFER` — 4-wide inter-block keystream (4 × 64 bytes) |
|
|
789
|
-
| 131824 | — | END |
|
|
790
|
-
|
|
791
|
-
`wipeBuffers()` zeroes all 15 buffer regions (key, chacha nonce/ctr/block/state, chunk pt/ct, poly key/msg/buf/tag/h/r/rs/s, xchacha nonce/subkey, SIMD work).
|
|
792
|
-
|
|
793
|
-
### SHA-2 module (3 pages, 192 KB)
|
|
794
|
-
|
|
795
|
-
Source: `src/asm/sha2/buffers.ts`
|
|
796
|
-
|
|
797
|
-
| Offset | Size | Name |
|
|
798
|
-
|--------|------|------|
|
|
799
|
-
| 0 | 32 | `SHA256_H` — SHA-256 hash state H0..H7 (8 × u32) |
|
|
800
|
-
| 32 | 64 | `SHA256_BLOCK` — SHA-256 block accumulator |
|
|
801
|
-
| 96 | 256 | `SHA256_W` — SHA-256 message schedule W[0..63] (64 × u32) |
|
|
802
|
-
| 352 | 32 | `SHA256_OUT` — SHA-256 digest output |
|
|
803
|
-
| 384 | 64 | `SHA256_INPUT` — SHA-256 user input staging (one block) |
|
|
804
|
-
| 448 | 4 | `SHA256_PARTIAL` — u32 partial block length |
|
|
805
|
-
| 452 | 8 | `SHA256_TOTAL` — u64 total bytes hashed |
|
|
806
|
-
| 460 | 64 | `HMAC256_IPAD` — HMAC-SHA256 K' XOR ipad |
|
|
807
|
-
| 524 | 64 | `HMAC256_OPAD` — HMAC-SHA256 K' XOR opad |
|
|
808
|
-
| 588 | 32 | `HMAC256_INNER` — HMAC-SHA256 inner hash |
|
|
809
|
-
| 620 | 64 | `SHA512_H` — SHA-512 hash state H0..H7 (8 × u64) |
|
|
810
|
-
| 684 | 128 | `SHA512_BLOCK` — SHA-512 block accumulator |
|
|
811
|
-
| 812 | 640 | `SHA512_W` — SHA-512 message schedule W[0..79] (80 × u64) |
|
|
812
|
-
| 1452 | 64 | `SHA512_OUT` — SHA-512 digest output (SHA-384 uses first 48 bytes) |
|
|
813
|
-
| 1516 | 128 | `SHA512_INPUT` — SHA-512 user input staging (one block) |
|
|
814
|
-
| 1644 | 4 | `SHA512_PARTIAL` — u32 partial block length |
|
|
815
|
-
| 1648 | 8 | `SHA512_TOTAL` — u64 total bytes hashed |
|
|
816
|
-
| 1656 | 128 | `HMAC512_IPAD` — HMAC-SHA512 K' XOR ipad (128-byte block size) |
|
|
817
|
-
| 1784 | 128 | `HMAC512_OPAD` — HMAC-SHA512 K' XOR opad |
|
|
818
|
-
| 1912 | 64 | `HMAC512_INNER` — HMAC-SHA512 inner hash |
|
|
819
|
-
| 1976 | — | END |
|
|
820
|
-
|
|
821
|
-
`wipeBuffers()` zeroes all 20 buffer regions (SHA-256 state/block/W/out/input/partial/total, HMAC-256 ipad/opad/inner, SHA-512 state/block/W/out/input/partial/total, HMAC-512 ipad/opad/inner).
|
|
822
|
-
|
|
823
|
-
### SHA-3 module (3 pages, 192 KB)
|
|
824
|
-
|
|
825
|
-
Source: `src/asm/sha3/buffers.ts`
|
|
826
|
-
|
|
827
|
-
| Offset | Size | Name |
|
|
828
|
-
|--------|------|------|
|
|
829
|
-
| 0 | 200 | `KECCAK_STATE` — 25 × u64 Keccak-f[1600] lane matrix (5×5, row-major x+5y) |
|
|
830
|
-
| 200 | 4 | `KECCAK_RATE` — u32 rate in bytes (variant-specific: 72–168) |
|
|
831
|
-
| 204 | 4 | `KECCAK_ABSORBED` — u32 bytes absorbed into current block |
|
|
832
|
-
| 208 | 1 | `KECCAK_DSBYTE` — u8 domain separation byte (0x06 for SHA-3, 0x1f for SHAKE) |
|
|
833
|
-
| 209 | 168 | `KECCAK_INPUT` — input staging buffer (max rate = SHAKE128 at 168 bytes) |
|
|
834
|
-
| 377 | 168 | `KECCAK_OUT` — output buffer (one SHAKE128 squeeze block) |
|
|
835
|
-
| 545 | — | END |
|
|
836
|
-
|
|
837
|
-
`wipeBuffers()` zeroes all 6 buffer regions (state, rate, absorbed, dsbyte, input, output).
|
|
838
|
-
|
|
839
|
-
### Kyber module (3 pages, 192 KB)
|
|
840
|
-
|
|
841
|
-
Source: `src/asm/kyber/`
|
|
842
|
-
|
|
843
|
-
| Region | Offset | Size | Purpose |
|
|
844
|
-
|--------|--------|------|---------|
|
|
845
|
-
| AS data segment | 0 | 4096 | Zetas table (128 × i16, bit-reversed Montgomery domain) |
|
|
846
|
-
| Poly slots | 4096 | 5120 | 10 × 512B scratch polynomials (256 × i16 each) |
|
|
847
|
-
| Polyvec slots | 9216 | 16384 | 8 × 2048B scratch polyvecs (k=4 max: 4 × 512B) |
|
|
848
|
-
| SEED buffer | 25600 | 32 | Seed ρ/σ |
|
|
849
|
-
| MSG buffer | 25632 | 32 | Message / shared secret |
|
|
850
|
-
| PK buffer | 25664 | 1568 | Encapsulation key (max k=4) |
|
|
851
|
-
| SK buffer | 27232 | 1536 | IND-CPA secret key (max k=4) |
|
|
852
|
-
| CT buffer | 28768 | 1568 | Ciphertext (max k=4) |
|
|
853
|
-
| CT_PRIME buffer | 30336 | 1568 | Decaps re-encrypt comparison (max k=4) |
|
|
854
|
-
| XOF/PRF buffer | 31904 | 1024 | SHAKE squeeze output for rej_uniform / CBD |
|
|
855
|
-
| Poly accumulator | 32928 | 512 | Internal scratch for polyvec_basemul_acc |
|
|
856
|
-
|
|
857
|
-
Total mutable: 29344 bytes (4096–33440). End = 33440 < 192 KB.
|
|
858
|
-
|
|
859
|
-
`wipeBuffers()` zeroes all mutable regions (poly slots, polyvec slots, SEED, MSG, PK, SK, CT, CT_PRIME, XOF/PRF, accumulator). The zetas data segment is read-only and is not wiped.
|
|
860
|
-
|
|
861
|
-
---
|
|
862
|
-
|
|
863
|
-
## Test Suite
|
|
864
|
-
|
|
865
|
-
### Structure
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
For the full testing methodology and vector corpus, see: [test-suite.md](./test-suite.md)
|
|
869
|
-
|
|
870
|
-
### Gate discipline
|
|
871
|
-
|
|
872
|
-
Each primitive family has a gate test: the simplest authoritative vector for that primitive. The gate must pass before any other tests in that family are written or run. Gate tests are annotated with a `// GATE` comment.
|
|
873
|
-
|
|
874
|
-
### `init.test.ts` contracts
|
|
875
|
-
|
|
876
|
-
- `init()` with each `WasmSource` type loads and caches the module correctly
|
|
877
|
-
- Idempotency: second `init()` call for same module is a no-op
|
|
878
|
-
- Error before init: clear error thrown for each class before its module is loaded
|
|
879
|
-
- Partial init: loading `{ serpent: ... }` does not make `sha3` classes available
|
|
880
|
-
|
|
881
|
-
---
|
|
882
|
-
|
|
883
|
-
## Correctness Contract
|
|
884
|
-
|
|
885
|
-
leviathan-crypto must produce byte-identical output to the authoritative
|
|
886
|
-
specification for every known test vector. Cross-checks against the leviathan
|
|
887
|
-
TypeScript reference and external tools (OpenSSL, Python hashlib, Node.js crypto)
|
|
888
|
-
provide additional verification layers.
|
|
889
|
-
|
|
890
|
-
The test vector corpus in `test/vectors/` is read-only. Integrity is verified via
|
|
891
|
-
`SHA256SUMS`, expected values are sourced directly from authoritative references.
|
|
892
|
-
They are the immutable truth, and must never be modified to make tests pass.
|
|
893
|
-
|
|
894
|
-
---
|
|
895
|
-
|
|
896
|
-
## Known Limitations
|
|
897
|
-
|
|
898
|
-
- **`SerpentCbc` is unauthenticated**: use `Seal` with `SerpentCipher` for
|
|
899
|
-
authenticated Serpent encryption, or pair `SerpentCbc` with `HMAC_SHA256`
|
|
900
|
-
(Encrypt-then-MAC) if direct CBC access is required.
|
|
901
|
-
- **Single-threaded WASM per instance**: one WASM instance per binary per thread.
|
|
902
|
-
`SealStreamPool` provides Worker-based parallelism for both cipher families;
|
|
903
|
-
other primitives remain single-threaded.
|
|
904
|
-
- **Max input per WASM call**: CTR accepts at most 65536 bytes per call; CBC
|
|
905
|
-
accepts at most 65552 bytes (65536 + 16 bytes PKCS7 maximum overhead).
|
|
906
|
-
Wrappers handle splitting automatically for larger inputs.
|
|
907
|
-
- **WASM side-channel posture**: WebAssembly implementations offer the best
|
|
908
|
-
available side-channel resistance (branchless, table-free), but lack
|
|
909
|
-
hardware-level constant-time guarantees. For applications where timing
|
|
910
|
-
side channels are a primary threat, a native cryptographic library with
|
|
911
|
-
verified constant-time guarantees will be more appropriate than any
|
|
912
|
-
WASM-based implementation.
|
|
913
|
-
|
|
914
|
-
---
|
|
915
|
-
|
|
916
|
-
> ## Cross-References
|
|
917
|
-
>
|
|
918
|
-
> - [index](./README.md) — Project Documentation index
|
|
919
|
-
> - [lexicon](./lexicon.md) — Glossary of cryptographic terms
|
|
920
|
-
> - [test-suite](./test-suite.md) — testing methodology, vector corpus, and gate discipline
|
|
921
|
-
> - [init](./init.md) — `init()` API, `WasmSource`, and idempotent behavior
|
|
922
|
-
> - [loader](./loader.md) — internal WASM binary loading strategies
|
|
923
|
-
> - [wasm](./wasm.md) — WebAssembly primer: modules, instances, memory, and the init gate
|
|
924
|
-
> - [types](./types.md) — public TypeScript interfaces and `CipherSuite`
|
|
925
|
-
> - [utils](./utils.md) — encoding helpers, `constantTimeEqual`, `wipe`, `randomBytes`
|
|
926
|
-
> - [authenticated encryption](./aead.md) — SealStream, OpenStream, SealStreamPool, wire format
|
|
927
|
-
> - [serpent](./serpent.md) — Serpent-256 TypeScript API, SerpentCipher
|
|
928
|
-
> - [chacha20](./chacha20.md) — ChaCha20/Poly1305 TypeScript API, XChaCha20Cipher
|
|
929
|
-
> - [sha2](./sha2.md) — SHA-2 hashes, HMAC, and HKDF TypeScript API
|
|
930
|
-
> - [sha3](./sha3.md) — SHA-3 hashes and SHAKE XOFs TypeScript API
|
|
931
|
-
> - [fortuna](./fortuna.md) — Fortuna CSPRNG with forward secrecy and entropy pooling
|
|
932
|
-
> - [argon2id](./argon2id.md) — Argon2id password hashing and key derivation
|