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.
Files changed (312) hide show
  1. package/CLAUDE.md +88 -281
  2. package/LICENSE +4 -0
  3. package/README.md +275 -87
  4. package/dist/aes/aes-cbc.d.ts +40 -0
  5. package/dist/aes/aes-cbc.js +158 -0
  6. package/dist/aes/aes-ctr.d.ts +50 -0
  7. package/dist/aes/aes-ctr.js +141 -0
  8. package/dist/aes/aes-gcm-siv.d.ts +67 -0
  9. package/dist/aes/aes-gcm-siv.js +217 -0
  10. package/dist/aes/aes-gcm.d.ts +61 -0
  11. package/dist/aes/aes-gcm.js +226 -0
  12. package/dist/aes/cipher-suite.d.ts +21 -0
  13. package/dist/aes/cipher-suite.js +179 -0
  14. package/dist/aes/embedded.d.ts +1 -0
  15. package/dist/aes/embedded.js +26 -0
  16. package/dist/aes/generator.d.ts +14 -0
  17. package/dist/aes/generator.js +103 -0
  18. package/dist/aes/index.d.ts +58 -0
  19. package/dist/aes/index.js +125 -0
  20. package/dist/aes/ops.d.ts +60 -0
  21. package/dist/aes/ops.js +164 -0
  22. package/dist/aes/pool-worker.d.ts +1 -0
  23. package/dist/aes/pool-worker.js +92 -0
  24. package/dist/aes/types.d.ts +1 -0
  25. package/dist/aes/types.js +23 -0
  26. package/dist/aes.wasm +0 -0
  27. package/dist/blake3/embedded.d.ts +1 -0
  28. package/dist/blake3/embedded.js +26 -0
  29. package/dist/blake3/index.d.ts +143 -0
  30. package/dist/blake3/index.js +620 -0
  31. package/dist/blake3/types.d.ts +102 -0
  32. package/dist/blake3/types.js +31 -0
  33. package/dist/blake3/validate.d.ts +29 -0
  34. package/dist/blake3/validate.js +80 -0
  35. package/dist/blake3.wasm +0 -0
  36. package/dist/chacha20/cipher-suite.d.ts +10 -0
  37. package/dist/chacha20/cipher-suite.js +98 -13
  38. package/dist/chacha20/generator.d.ts +12 -0
  39. package/dist/chacha20/generator.js +91 -0
  40. package/dist/chacha20/index.d.ts +100 -3
  41. package/dist/chacha20/index.js +169 -35
  42. package/dist/chacha20/ops.d.ts +57 -6
  43. package/dist/chacha20/ops.js +107 -27
  44. package/dist/chacha20/pool-worker.js +14 -0
  45. package/dist/chacha20/types.d.ts +1 -32
  46. package/dist/cte-wasm.d.ts +1 -0
  47. package/dist/cte-wasm.js +3 -0
  48. package/dist/cte.wasm +0 -0
  49. package/dist/curve25519.wasm +0 -0
  50. package/dist/ecdsa/der.d.ts +23 -0
  51. package/dist/ecdsa/der.js +192 -0
  52. package/dist/ecdsa/ecprivatekey-der.d.ts +32 -0
  53. package/dist/ecdsa/ecprivatekey-der.js +230 -0
  54. package/dist/ecdsa/embedded.d.ts +1 -0
  55. package/dist/ecdsa/embedded.js +25 -0
  56. package/dist/ecdsa/index.d.ts +124 -0
  57. package/dist/ecdsa/index.js +366 -0
  58. package/dist/ecdsa/types.d.ts +31 -0
  59. package/dist/ecdsa/types.js +28 -0
  60. package/dist/ecdsa/validate.d.ts +18 -0
  61. package/dist/ecdsa/validate.js +92 -0
  62. package/dist/ed25519/embedded.d.ts +1 -0
  63. package/dist/ed25519/embedded.js +31 -0
  64. package/dist/ed25519/index.d.ts +70 -0
  65. package/dist/ed25519/index.js +308 -0
  66. package/dist/ed25519/types.d.ts +27 -0
  67. package/dist/ed25519/types.js +27 -0
  68. package/dist/ed25519/validate.d.ts +7 -0
  69. package/dist/ed25519/validate.js +77 -0
  70. package/dist/embedded/aes-pool-worker.d.ts +1 -0
  71. package/dist/embedded/aes-pool-worker.js +5 -0
  72. package/dist/embedded/aes.d.ts +1 -0
  73. package/dist/embedded/aes.js +3 -0
  74. package/dist/embedded/blake3.d.ts +1 -0
  75. package/dist/embedded/blake3.js +3 -0
  76. package/dist/embedded/chacha20-pool-worker.d.ts +1 -0
  77. package/dist/embedded/chacha20-pool-worker.js +5 -0
  78. package/dist/embedded/chacha20.d.ts +1 -1
  79. package/dist/embedded/chacha20.js +2 -2
  80. package/dist/embedded/curve25519.d.ts +1 -0
  81. package/dist/embedded/curve25519.js +3 -0
  82. package/dist/embedded/mldsa.d.ts +1 -0
  83. package/dist/embedded/mldsa.js +3 -0
  84. package/dist/embedded/mlkem.d.ts +1 -0
  85. package/dist/embedded/mlkem.js +3 -0
  86. package/dist/embedded/p256.d.ts +1 -0
  87. package/dist/embedded/p256.js +3 -0
  88. package/dist/embedded/serpent-pool-worker.d.ts +1 -0
  89. package/dist/embedded/serpent-pool-worker.js +5 -0
  90. package/dist/embedded/serpent.d.ts +1 -1
  91. package/dist/embedded/serpent.js +2 -2
  92. package/dist/embedded/sha2.d.ts +1 -1
  93. package/dist/embedded/sha2.js +2 -2
  94. package/dist/embedded/sha3.d.ts +1 -1
  95. package/dist/embedded/sha3.js +2 -2
  96. package/dist/embedded/slhdsa.d.ts +1 -0
  97. package/dist/embedded/slhdsa.js +3 -0
  98. package/dist/errors.d.ts +92 -1
  99. package/dist/errors.js +111 -1
  100. package/dist/fortuna.d.ts +18 -12
  101. package/dist/fortuna.js +166 -99
  102. package/dist/index.d.ts +42 -11
  103. package/dist/index.js +65 -20
  104. package/dist/init.d.ts +1 -3
  105. package/dist/init.js +73 -7
  106. package/dist/keccak/embedded.js +1 -1
  107. package/dist/keccak/index.d.ts +2 -0
  108. package/dist/keccak/index.js +4 -2
  109. package/dist/loader.d.ts +1 -19
  110. package/dist/loader.js +26 -32
  111. package/dist/merkle/blake3-tree.d.ts +35 -0
  112. package/dist/merkle/blake3-tree.js +187 -0
  113. package/dist/merkle/checkpoint.d.ts +58 -0
  114. package/dist/merkle/checkpoint.js +217 -0
  115. package/dist/merkle/index.d.ts +19 -0
  116. package/dist/merkle/index.js +37 -0
  117. package/dist/merkle/merkle-log.d.ts +130 -0
  118. package/dist/merkle/merkle-log.js +207 -0
  119. package/dist/merkle/merkle-verifier.d.ts +126 -0
  120. package/dist/merkle/merkle-verifier.js +296 -0
  121. package/dist/merkle/proof.d.ts +70 -0
  122. package/dist/merkle/proof.js +300 -0
  123. package/dist/merkle/sha256-tree.d.ts +33 -0
  124. package/dist/merkle/sha256-tree.js +145 -0
  125. package/dist/merkle/signed-log.d.ts +156 -0
  126. package/dist/merkle/signed-log.js +356 -0
  127. package/dist/merkle/signed-note.d.ts +309 -0
  128. package/dist/merkle/signed-note.js +648 -0
  129. package/dist/merkle/sth.d.ts +31 -0
  130. package/dist/merkle/sth.js +31 -0
  131. package/dist/merkle/storage.d.ts +40 -0
  132. package/dist/merkle/storage.js +71 -0
  133. package/dist/merkle/tree.d.ts +68 -0
  134. package/dist/merkle/tree.js +94 -0
  135. package/dist/mldsa/embedded.d.ts +1 -0
  136. package/dist/{kyber → mldsa}/embedded.js +5 -5
  137. package/dist/mldsa/expand.d.ts +53 -0
  138. package/dist/mldsa/expand.js +188 -0
  139. package/dist/mldsa/format.d.ts +16 -0
  140. package/dist/mldsa/format.js +68 -0
  141. package/dist/mldsa/hashvariant.d.ts +32 -0
  142. package/dist/mldsa/hashvariant.js +248 -0
  143. package/dist/mldsa/index.d.ts +142 -0
  144. package/dist/mldsa/index.js +463 -0
  145. package/dist/mldsa/keygen.d.ts +16 -0
  146. package/dist/mldsa/keygen.js +232 -0
  147. package/dist/mldsa/params.d.ts +21 -0
  148. package/dist/mldsa/params.js +55 -0
  149. package/dist/mldsa/sha3-helpers.d.ts +30 -0
  150. package/dist/mldsa/sha3-helpers.js +124 -0
  151. package/dist/mldsa/sign.d.ts +36 -0
  152. package/dist/mldsa/sign.js +380 -0
  153. package/dist/mldsa/types.d.ts +91 -0
  154. package/dist/mldsa/types.js +25 -0
  155. package/dist/mldsa/validate.d.ts +55 -0
  156. package/dist/mldsa/validate.js +125 -0
  157. package/dist/mldsa/verify.d.ts +29 -0
  158. package/dist/mldsa/verify.js +269 -0
  159. package/dist/mldsa.wasm +0 -0
  160. package/dist/mlkem/embedded.d.ts +1 -0
  161. package/dist/mlkem/embedded.js +27 -0
  162. package/dist/mlkem/indcpa.d.ts +49 -0
  163. package/dist/{kyber → mlkem}/indcpa.js +48 -48
  164. package/dist/mlkem/index.d.ts +37 -0
  165. package/dist/{kyber → mlkem}/index.js +41 -31
  166. package/dist/mlkem/kem.d.ts +21 -0
  167. package/dist/{kyber → mlkem}/kem.js +48 -13
  168. package/dist/{kyber → mlkem}/params.d.ts +4 -4
  169. package/dist/{kyber → mlkem}/params.js +2 -2
  170. package/dist/mlkem/suite.d.ts +12 -0
  171. package/dist/{kyber → mlkem}/suite.js +17 -12
  172. package/dist/{kyber → mlkem}/types.d.ts +4 -3
  173. package/dist/{kyber → mlkem}/types.js +1 -1
  174. package/dist/mlkem/validate.d.ts +23 -0
  175. package/dist/{kyber → mlkem}/validate.js +24 -20
  176. package/dist/{kyber.wasm → mlkem.wasm} +0 -0
  177. package/dist/p256.wasm +0 -0
  178. package/dist/ratchet/index.d.ts +8 -0
  179. package/dist/ratchet/index.js +38 -0
  180. package/dist/ratchet/kdf-chain.d.ts +13 -0
  181. package/dist/ratchet/kdf-chain.js +85 -0
  182. package/dist/ratchet/ratchet-keypair.d.ts +9 -0
  183. package/dist/ratchet/ratchet-keypair.js +61 -0
  184. package/dist/ratchet/root-kdf.d.ts +4 -0
  185. package/dist/ratchet/root-kdf.js +124 -0
  186. package/dist/ratchet/skipped-key-store.d.ts +14 -0
  187. package/dist/ratchet/skipped-key-store.js +154 -0
  188. package/dist/ratchet/types.d.ts +36 -0
  189. package/dist/ratchet/types.js +26 -0
  190. package/dist/serpent/cipher-suite.d.ts +10 -0
  191. package/dist/serpent/cipher-suite.js +144 -56
  192. package/dist/serpent/generator.d.ts +12 -0
  193. package/dist/serpent/generator.js +97 -0
  194. package/dist/serpent/index.d.ts +62 -1
  195. package/dist/serpent/index.js +97 -21
  196. package/dist/serpent/pool-worker.js +28 -102
  197. package/dist/serpent/serpent-cbc.d.ts +16 -6
  198. package/dist/serpent/serpent-cbc.js +58 -37
  199. package/dist/serpent/shared-ops.d.ts +63 -0
  200. package/dist/serpent/shared-ops.js +178 -0
  201. package/dist/serpent/types.d.ts +1 -5
  202. package/dist/serpent.wasm +0 -0
  203. package/dist/sha2/hash.d.ts +2 -0
  204. package/dist/sha2/hash.js +53 -0
  205. package/dist/sha2/hkdf.js +5 -5
  206. package/dist/sha2/index.d.ts +22 -1
  207. package/dist/sha2/index.js +80 -11
  208. package/dist/sha2/types.d.ts +41 -2
  209. package/dist/sha2.wasm +0 -0
  210. package/dist/sha3/hash.d.ts +2 -0
  211. package/dist/sha3/hash.js +53 -0
  212. package/dist/sha3/index.d.ts +87 -3
  213. package/dist/sha3/index.js +317 -19
  214. package/dist/sha3/kmac.d.ts +121 -0
  215. package/dist/sha3/kmac.js +800 -0
  216. package/dist/sha3.wasm +0 -0
  217. package/dist/shared/pkcs7.d.ts +22 -0
  218. package/dist/shared/pkcs7.js +84 -0
  219. package/dist/sign/ctx.d.ts +41 -0
  220. package/dist/sign/ctx.js +102 -0
  221. package/dist/sign/envelope.d.ts +45 -0
  222. package/dist/sign/envelope.js +152 -0
  223. package/dist/sign/hasher.d.ts +9 -0
  224. package/dist/sign/hasher.js +132 -0
  225. package/dist/sign/index.d.ts +11 -0
  226. package/dist/sign/index.js +34 -0
  227. package/dist/sign/sign-stream.d.ts +25 -0
  228. package/dist/sign/sign-stream.js +112 -0
  229. package/dist/sign/suites/ecdsa-p256.d.ts +2 -0
  230. package/dist/sign/suites/ecdsa-p256.js +120 -0
  231. package/dist/sign/suites/ed25519.d.ts +3 -0
  232. package/dist/sign/suites/ed25519.js +165 -0
  233. package/dist/sign/suites/hybrid-classical.d.ts +23 -0
  234. package/dist/sign/suites/hybrid-classical.js +526 -0
  235. package/dist/sign/suites/hybrid-pq.d.ts +4 -0
  236. package/dist/sign/suites/hybrid-pq.js +234 -0
  237. package/dist/sign/suites/mldsa.d.ts +7 -0
  238. package/dist/sign/suites/mldsa.js +161 -0
  239. package/dist/sign/suites/slhdsa.d.ts +7 -0
  240. package/dist/sign/suites/slhdsa.js +176 -0
  241. package/dist/sign/types.d.ts +106 -0
  242. package/dist/sign/types.js +28 -0
  243. package/dist/sign/verify-stream.d.ts +30 -0
  244. package/dist/sign/verify-stream.js +227 -0
  245. package/dist/slhdsa/embedded.d.ts +1 -0
  246. package/dist/slhdsa/embedded.js +26 -0
  247. package/dist/slhdsa/index.d.ts +149 -0
  248. package/dist/slhdsa/index.js +493 -0
  249. package/dist/slhdsa/params.d.ts +26 -0
  250. package/dist/slhdsa/params.js +70 -0
  251. package/dist/slhdsa/prehash.d.ts +68 -0
  252. package/dist/slhdsa/prehash.js +307 -0
  253. package/dist/slhdsa/sign.d.ts +39 -0
  254. package/dist/slhdsa/sign.js +116 -0
  255. package/dist/slhdsa/types.d.ts +129 -0
  256. package/dist/slhdsa/types.js +27 -0
  257. package/dist/slhdsa/validate.d.ts +60 -0
  258. package/dist/slhdsa/validate.js +127 -0
  259. package/dist/slhdsa/verify.d.ts +32 -0
  260. package/dist/slhdsa/verify.js +107 -0
  261. package/dist/slhdsa.wasm +0 -0
  262. package/dist/stream/header.js +8 -8
  263. package/dist/stream/index.d.ts +1 -0
  264. package/dist/stream/index.js +1 -0
  265. package/dist/stream/open-stream.js +65 -22
  266. package/dist/stream/seal-stream-pool.d.ts +2 -0
  267. package/dist/stream/seal-stream-pool.js +100 -33
  268. package/dist/stream/seal-stream.d.ts +1 -1
  269. package/dist/stream/seal-stream.js +48 -19
  270. package/dist/stream/seal.js +6 -6
  271. package/dist/stream/types.d.ts +3 -1
  272. package/dist/stream/types.js +1 -1
  273. package/dist/types.d.ts +22 -1
  274. package/dist/types.js +1 -1
  275. package/dist/utils.d.ts +9 -10
  276. package/dist/utils.js +84 -59
  277. package/dist/wasm-source.d.ts +9 -8
  278. package/dist/wasm-source.js +1 -1
  279. package/dist/x25519/embedded.d.ts +1 -0
  280. package/dist/x25519/embedded.js +31 -0
  281. package/dist/x25519/index.d.ts +43 -0
  282. package/dist/x25519/index.js +159 -0
  283. package/dist/x25519/types.d.ts +25 -0
  284. package/dist/x25519/types.js +27 -0
  285. package/dist/x25519/validate.d.ts +2 -0
  286. package/dist/x25519/validate.js +39 -0
  287. package/package.json +123 -64
  288. package/SECURITY.md +0 -276
  289. package/dist/ct-wasm.d.ts +0 -1
  290. package/dist/ct-wasm.js +0 -3
  291. package/dist/ct.wasm +0 -0
  292. package/dist/docs/aead.md +0 -323
  293. package/dist/docs/architecture.md +0 -932
  294. package/dist/docs/argon2id.md +0 -302
  295. package/dist/docs/chacha20.md +0 -674
  296. package/dist/docs/exports.md +0 -241
  297. package/dist/docs/fortuna.md +0 -313
  298. package/dist/docs/init.md +0 -302
  299. package/dist/docs/loader.md +0 -161
  300. package/dist/docs/serpent.md +0 -519
  301. package/dist/docs/sha2.md +0 -613
  302. package/dist/docs/sha3.md +0 -546
  303. package/dist/docs/types.md +0 -276
  304. package/dist/docs/utils.md +0 -367
  305. package/dist/embedded/kyber.d.ts +0 -1
  306. package/dist/embedded/kyber.js +0 -3
  307. package/dist/kyber/embedded.d.ts +0 -1
  308. package/dist/kyber/indcpa.d.ts +0 -49
  309. package/dist/kyber/index.d.ts +0 -38
  310. package/dist/kyber/kem.d.ts +0 -21
  311. package/dist/kyber/suite.d.ts +0 -13
  312. package/dist/kyber/validate.d.ts +0 -19
@@ -1,241 +0,0 @@
1
- # All Exports
2
-
3
- > [!NOTE]
4
- > Complete reference for every public export in leviathan-crypto, grouped by module. Follow the module links for deeper documentation on each class.
5
-
6
- > ### Table of Contents
7
- > - [Initialization](#initialization)
8
- > - [Serpent-256](#serpent-256)
9
- > - [Stream](#stream)
10
- > - [Errors](#errors)
11
- > - [XChaCha20 / Poly1305](#xchacha20--poly1305)
12
- > - [SHA-2](#sha-2)
13
- > - [SHA-3](#sha-3)
14
- > - [Keccak (alias for SHA-3)](#keccak-alias-for-sha-3)
15
- > - [ML-KEM (Post-quantum KEM)](#ml-kem-post-quantum-kem)
16
- > - [Fortuna CSPRNG](#fortuna-csprng)
17
- > - [Types](#types)
18
- > - [Utilities](#utilities)
19
-
20
- ---
21
-
22
- ## Initialization
23
-
24
- Root barrel `leviathan-crypto`. No module required.
25
-
26
- | Export | Kind | Description |
27
- |--------|------|-------------|
28
- | `init` | function | Load and cache WASM modules. `init(sources: Partial<Record<Module, WasmSource>>)`. |
29
- | `isInitialized` | function | `isInitialized(mod: Module): boolean`. Returns `true` if the given module has been loaded. Useful for diagnostic checks. |
30
- | `Module` | type | `'serpent' \| 'chacha20' \| 'sha2' \| 'sha3' \| 'keccak' \| 'kyber'` |
31
- | `WasmSource` | type | Union of all accepted WASM loading strategies. See below. |
32
-
33
- **`WasmSource`** accepted by every init function:
34
-
35
- | Value | Strategy |
36
- |-------|----------|
37
- | `string` | Decode gzip+base64 embedded blob |
38
- | `URL` | `fetch` + `instantiateStreaming` |
39
- | `ArrayBuffer` | Compile from raw WASM bytes |
40
- | `Uint8Array` | Compile from raw WASM bytes |
41
- | `WebAssembly.Module` | Instantiate pre-compiled module |
42
- | `Response` | `instantiateStreaming` from fetch response |
43
- | `Promise<Response>` | `instantiateStreaming` from deferred fetch |
44
-
45
- See [init.md](./init.md) for full loading documentation.
46
-
47
- ---
48
-
49
- ## Serpent-256
50
-
51
- Requires `init({ serpent: serpentWasm, sha2: sha2Wasm })` for authenticated classes, `init({ serpent: serpentWasm })` for raw modes.
52
- Subpath: `leviathan-crypto/serpent`. See [serpent.md](./serpent.md).
53
-
54
- | Export | Kind | Description |
55
- |--------|------|-------------|
56
- | `serpentInit` | function | Module-scoped init. `serpentInit(source: WasmSource)` loads only serpent. |
57
- | `SerpentCipher` | const | `CipherSuite` for Serpent-256 CBC+HMAC-SHA-256. `keygen()` → 32-byte key. `formatEnum: 0x02`, `keySize: 32`, `tagSize: 32`, `padded: true`. Used with `Seal`, `SealStream`, `OpenStream`. |
58
- | `Serpent` | class | Serpent-256 ECB block cipher. `loadKey()`, `encryptBlock()`, `decryptBlock()`. Unauthenticated. |
59
- | `SerpentCtr` | class | Serpent-256 CTR mode. `beginEncrypt()`, `encryptChunk()`, `beginDecrypt()`, `decryptChunk()`. Unauthenticated. |
60
- | `SerpentCbc` | class | Serpent-256 CBC mode with PKCS7 padding. `encrypt(key, iv, plaintext)`, `decrypt(key, iv, ciphertext)`. Unauthenticated. |
61
-
62
- ---
63
-
64
- ## Stream
65
-
66
- Cipher-agnostic streaming encryption using the STREAM construction.
67
- Subpath: `leviathan-crypto/stream`. See [aead.md](./aead.md).
68
-
69
- | Export | Kind | Description |
70
- |--------|------|-------------|
71
- | `Seal` | class (static) | One-shot AEAD. `Seal.encrypt(suite, key, plaintext)` / `Seal.decrypt(suite, key, blob)`. Works with any `CipherSuite` including `KyberSuite`. Never instantiated. |
72
- | `SealStream` | class | Cipher-agnostic streaming encryption (STREAM construction). `push(chunk)`, `finalize(chunk)`, `toTransformStream()`. |
73
- | `OpenStream` | class | Cipher-agnostic streaming decryption. `pull(chunk)`, `finalize(chunk)`, `seek(index)`, `toTransformStream()`. |
74
- | `SealStreamPool` | class | Parallel batch seal/open via Web Workers. `SealStreamPool.create(cipher, key, opts)` static factory. |
75
- | `CipherSuite` | interface | Cipher-specific logic injected into SealStream/OpenStream. Implementations: `XChaCha20Cipher`, `SerpentCipher`, `KyberSuite`. See [ciphersuite.md](./ciphersuite.md). |
76
- | `DerivedKeys` | interface | Opaque key material returned by `CipherSuite.deriveKeys()`. |
77
- | `SealStreamOpts` | type | Options for SealStream: `chunkSize?`, `framed?`. |
78
- | `PoolOpts` | type | Options for SealStreamPool: `wasm`, `workers?`, `chunkSize?`, `framed?`, `jobTimeout?`. |
79
- | `HEADER_SIZE` | const | Stream header size in bytes (20). |
80
- | `CHUNK_MIN` | const | Minimum chunk size (1024). |
81
- | `CHUNK_MAX` | const | Maximum chunk size (16777215, u24 max). |
82
- | `FLAG_FRAMED` | const | Header byte 0 framed flag (0x80). |
83
- | `TAG_DATA` | const | Counter nonce final flag for data chunks (0x00). |
84
- | `TAG_FINAL` | const | Counter nonce final flag for final chunk (0x01). |
85
-
86
- ---
87
-
88
- ## Errors
89
-
90
- | Export | Kind | Description |
91
- |--------|------|-------------|
92
- | `AuthenticationError` | class | Thrown on AEAD auth failure. Extends `Error`. Constructor takes cipher name string. |
93
-
94
- ---
95
-
96
- ## XChaCha20 / Poly1305
97
-
98
- Requires `init({ chacha20: chacha20Wasm })` or subpath `chacha20Init()`.
99
- Subpath: `leviathan-crypto/chacha20`. See [chacha20.md](./chacha20.md).
100
-
101
- | Export | Kind | Description |
102
- |--------|------|-------------|
103
- | `chacha20Init` | function | Module-scoped init. `chacha20Init(source: WasmSource)` loads only chacha20. |
104
- | `XChaCha20Poly1305` | class | XChaCha20-Poly1305 AEAD. 24-byte nonce. `encrypt()` returns single `Uint8Array` (ct‖tag), `decrypt()` accepts same format. Single-use encrypt guard. |
105
- | `XChaCha20Cipher` | const | `CipherSuite` for XChaCha20-Poly1305. `keygen()` → 32-byte key. `formatEnum: 0x01`, `keySize: 32`, `tagSize: 16`, `padded: false`. Used with `Seal`, `SealStream`, `OpenStream`. |
106
- | `ChaCha20Poly1305` | class | ChaCha20-Poly1305 AEAD (RFC 8439). 12-byte nonce. `encrypt()` returns single `Uint8Array` (ct‖tag), `decrypt()` accepts same format. Single-use encrypt guard. |
107
- | `ChaCha20` | class | ChaCha20 stream cipher (RFC 8439). `beginEncrypt()`, `encryptChunk()`. Unauthenticated. |
108
- | `Poly1305` | class | Poly1305 one-time MAC (RFC 8439). `mac(key, msg)`. |
109
-
110
- ---
111
-
112
- ## SHA-2
113
-
114
- Requires `init({ sha2: sha2Wasm })` or subpath `sha2Init(source)`.
115
- Subpath: `leviathan-crypto/sha2`. See [sha2.md](./sha2.md).
116
-
117
- | Export | Kind | Description |
118
- |--------|------|-------------|
119
- | `sha2Init` | function | Module-scoped init. `sha2Init(source: WasmSource)` loads only sha2. |
120
- | `SHA256` | class | SHA-256 hash (FIPS 180-4). `hash(msg)` returns 32 bytes. |
121
- | `SHA384` | class | SHA-384 hash (FIPS 180-4). `hash(msg)` returns 48 bytes. |
122
- | `SHA512` | class | SHA-512 hash (FIPS 180-4). `hash(msg)` returns 64 bytes. |
123
- | `HMAC_SHA256` | class | HMAC-SHA256 (RFC 2104). `hash(key, msg)` returns 32 bytes. |
124
- | `HMAC_SHA384` | class | HMAC-SHA384 (RFC 2104). `hash(key, msg)` returns 48 bytes. |
125
- | `HMAC_SHA512` | class | HMAC-SHA512 (RFC 2104). `hash(key, msg)` returns 64 bytes. |
126
- | `HKDF_SHA256` | class | HKDF with HMAC-SHA256 (RFC 5869). `derive(ikm, salt, info, length)`. |
127
- | `HKDF_SHA512` | class | HKDF with HMAC-SHA512 (RFC 5869). `derive(ikm, salt, info, length)`. |
128
-
129
- ---
130
-
131
- ## SHA-3
132
-
133
- Requires `init({ sha3: sha3Wasm })` or subpath `sha3Init(source)`.
134
- Subpath: `leviathan-crypto/sha3`. See [sha3.md](./sha3.md).
135
-
136
- | Export | Kind | Description |
137
- |--------|------|-------------|
138
- | `sha3Init` | function | Module-scoped init. `sha3Init(source: WasmSource)` loads only sha3. |
139
- | `SHA3_224` | class | SHA3-224 hash (FIPS 202). `hash(msg)` returns 28 bytes. |
140
- | `SHA3_256` | class | SHA3-256 hash (FIPS 202). `hash(msg)` returns 32 bytes. |
141
- | `SHA3_384` | class | SHA3-384 hash (FIPS 202). `hash(msg)` returns 48 bytes. |
142
- | `SHA3_512` | class | SHA3-512 hash (FIPS 202). `hash(msg)` returns 64 bytes. |
143
- | `SHAKE128` | class | SHAKE128 XOF (FIPS 202). Unbounded output. `hash(msg, outputLength)`, `absorb(msg)`, `squeeze(n)`, `reset()`. |
144
- | `SHAKE256` | class | SHAKE256 XOF (FIPS 202). Unbounded output. `hash(msg, outputLength)`, `absorb(msg)`, `squeeze(n)`, `reset()`. |
145
-
146
- ---
147
-
148
- ## Keccak (alias for SHA-3)
149
-
150
- `'keccak'` is an alias for `'sha3'`. Same WASM binary, same instance slot.
151
- Both `init({ sha3: sha3Wasm })` and `init({ keccak: keccakWasm })` load the same module.
152
- Provided so Kyber/ML-KEM consumers can use the semantically correct primitive name.
153
- Subpath: `leviathan-crypto/keccak`.
154
-
155
- | Export | Kind | Description |
156
- |--------|------|-------------|
157
- | `keccakInit` | function | Alias init. `keccakInit(source: WasmSource)` loads the sha3 WASM slot via the keccak alias. |
158
- | `SHA3_224` | class | Re-exported from `leviathan-crypto/sha3`. |
159
- | `SHA3_256` | class | Re-exported from `leviathan-crypto/sha3`. |
160
- | `SHA3_384` | class | Re-exported from `leviathan-crypto/sha3`. |
161
- | `SHA3_512` | class | Re-exported from `leviathan-crypto/sha3`. |
162
- | `SHAKE128` | class | Re-exported from `leviathan-crypto/sha3`. |
163
- | `SHAKE256` | class | Re-exported from `leviathan-crypto/sha3`. |
164
-
165
- ---
166
-
167
- ## ML-KEM (Post-quantum KEM)
168
-
169
- Requires `init({ kyber: kyberWasm, sha3: sha3Wasm })`.
170
- Subpath: `leviathan-crypto/kyber`. See [kyber.md](./kyber.md).
171
-
172
- | Export | Kind | Description |
173
- |--------|------|-------------|
174
- | `kyberInit` | function | Module-scoped init. `kyberInit(source: WasmSource)` loads only kyber WASM. |
175
- | `MlKemBase` | class | Abstract base class for all ML-KEM variants. Holds `params: KyberParams`. Not normally instantiated directly. Use `MlKem512`, `MlKem768`, or `MlKem1024`. |
176
- | `MlKem512` | class | ML-KEM-512. k=2, η₁=3. `keygen()`, `encapsulate(ek)`, `decapsulate(dk, c)`, `checkEncapsulationKey(ek)`, `checkDecapsulationKey(dk)`. |
177
- | `MlKem768` | class | ML-KEM-768. k=3, η₁=2. Recommended default. Same API as MlKem512. |
178
- | `MlKem1024` | class | ML-KEM-1024. k=4, η₁=2. Same API as MlKem512. |
179
- | `KyberSuite` | function | Factory. `KyberSuite(kem, innerCipher)` → `CipherSuite & { keygen(): KyberKeyPair }`. Wraps `MlKemBase` + `CipherSuite` into a hybrid KEM+AEAD suite for use with `Seal`, `SealStream`, `OpenStream`. |
180
- | `KyberKeyPair` | type | `{ encapsulationKey: Uint8Array, decapsulationKey: Uint8Array }` |
181
- | `KyberEncapsulation` | type | `{ ciphertext: Uint8Array, sharedSecret: Uint8Array }` |
182
- | `KyberParams` | type | Parameter set configuration (k, η₁, η₂, dᵤ, dᵥ, byte sizes). |
183
- | `MLKEM512` | const | Parameter set for ML-KEM-512. |
184
- | `MLKEM768` | const | Parameter set for ML-KEM-768. |
185
- | `MLKEM1024` | const | Parameter set for ML-KEM-1024. |
186
-
187
- > [!NOTE]
188
- > `ntt_scalar` and `invntt_scalar` are scalar NTT references exported for SIMD gate tests. They are not part of the public API.
189
-
190
- ---
191
-
192
- ## Fortuna CSPRNG
193
-
194
- Requires `init({ serpent: serpentWasm, sha2: sha2Wasm })`. See [fortuna.md](./fortuna.md).
195
-
196
- | Export | Kind | Description |
197
- |--------|------|-------------|
198
- | `Fortuna` | class | Fortuna CSPRNG (Ferguson & Schneier). `Fortuna.create()` static factory, `get(n)`, `addEntropy()`, `stop()`. |
199
-
200
- ---
201
-
202
- ## Types
203
-
204
- No `init()` required. See [types.md](./types.md).
205
-
206
- | Export | Kind | Description |
207
- |--------|------|-------------|
208
- | `Hash` | interface | `hash(msg): Uint8Array`, `dispose()` |
209
- | `KeyedHash` | interface | `hash(key, msg): Uint8Array`, `dispose()` |
210
- | `Blockcipher` | interface | `encrypt(block): Uint8Array`, `decrypt(block): Uint8Array`, `dispose()` |
211
- | `Streamcipher` | interface | `encrypt(msg): Uint8Array`, `decrypt(msg): Uint8Array`, `dispose()` |
212
- | `AEAD` | interface | `encrypt(msg, aad?): Uint8Array`, `decrypt(ciphertext, aad?): Uint8Array`, `dispose()` |
213
-
214
- ---
215
-
216
- ## Utilities
217
-
218
- No `init()` required. See [utils.md](./utils.md).
219
-
220
- | Export | Kind | Description |
221
- |--------|------|-------------|
222
- | `hexToBytes` | function | Hex string to `Uint8Array`. Accepts `0x` prefix, uppercase/lowercase. Throws `RangeError` on odd-length input. |
223
- | `bytesToHex` | function | `Uint8Array` to lowercase hex string. |
224
- | `utf8ToBytes` | function | UTF-8 string to `Uint8Array`. |
225
- | `bytesToUtf8` | function | `Uint8Array` to UTF-8 string. |
226
- | `base64ToBytes` | function | Base64/base64url string to `Uint8Array`. Returns `undefined` on invalid input. |
227
- | `bytesToBase64` | function | `Uint8Array` to base64 string. Pass `url=true` for base64url. |
228
- | `constantTimeEqual` | function | Best-available constant-time byte-array equality. Uses WASM SIMD when available to eliminate JIT timing leaks; falls back to XOR-accumulate in JS. Returns `false` immediately on length mismatch. Throws `RangeError` if either input exceeds `CT_MAX_BYTES`. |
229
- | `CT_MAX_BYTES` | const | Maximum input size for `constantTimeEqual` per side (32768 bytes, one 64 KiB WASM page split between two buffers). |
230
- | `wipe` | function | Zero a typed array in place. |
231
- | `xor` | function | XOR two equal-length `Uint8Array`s, returns new array. |
232
- | `concat` | function | Concatenate one or more `Uint8Array`s into a new array. Variadic. |
233
- | `randomBytes` | function | Cryptographically secure random bytes via Web Crypto API. |
234
- | `hasSIMD` | function | Returns `true` if the runtime supports WebAssembly SIMD. Cached after first call. Used internally for CTR/CBC-decrypt and ChaCha20 dispatch. Exported for informational use. |
235
-
236
- ---
237
-
238
- > ## Cross-References
239
- >
240
- > - [index](./README.md) — Project Documentation index
241
- > - [architecture](./architecture.md) — architecture overview, module relationships, buffer layouts, and build pipeline
@@ -1,313 +0,0 @@
1
- # Fortuna CSPRNG
2
-
3
- > [!NOTE]
4
- > A CSPRNG that continuously collects entropy from the environment and generates
5
- > cryptographically secure random bytes, backed by WASM Serpent-256 and SHA-256.
6
-
7
- > ### Table of Contents
8
- > - [Overview](#overview)
9
- > - [Security Notes](#security-notes)
10
- > - [API Reference](#api-reference)
11
- > - [Usage Examples](#usage-examples)
12
- > - [Error Conditions](#error-conditions)
13
- > - [How It Works (Simplified)](#how-it-works-simplified)
14
-
15
- ---
16
-
17
- ## Overview
18
-
19
- A cryptographically secure pseudorandom number generator (CSPRNG) produces random
20
- bytes that are indistinguishable from true randomness to any observer, even one
21
- with significant computational resources. This matters because many security
22
- operations require unpredictable randomness: generating encryption keys, initialization vectors, nonces, and tokens. If an attacker can predict
23
- the output of your random number generator, they can predict your keys, and your
24
- encryption provides no protection.
25
-
26
- Fortuna is a CSPRNG designed by Bruce Schneier and Niels Ferguson, published in
27
- *Practical Cryptography* (2003). It continuously collects entropy from multiple
28
- sources (mouse movements, keyboard events, system timers, OS randomness) and
29
- feeds that entropy into 32 independent pools. When you request random bytes,
30
- Fortuna combines pool contents and uses them to reseed an internal generator
31
- built on Serpent-256 (block cipher) and SHA-256 (hash function). Both primitives
32
- run entirely in WebAssembly.
33
-
34
- Fortuna adds two properties on top of `crypto.getRandomValues()`. First, **forward secrecy**: after every call to `get()`, the
35
- internal generation key is replaced, so compromising the current state does not
36
- reveal any past outputs. Second, **defense-in-depth entropy pooling**: Fortuna
37
- collects entropy from many independent sources and distributes it across 32 pools
38
- with exponentially increasing reseed intervals, making it resilient to entropy
39
- estimation attacks and individual source failures.
40
-
41
- Fortuna is the only class in leviathan-crypto that requires two WASM modules.
42
- You must initialize both `serpent` and `sha2` before creating an instance, and
43
- you must use the `Fortuna.create()` static factory rather than `new Fortuna()`.
44
-
45
- ---
46
-
47
- ## Security Notes
48
-
49
- **Forward secrecy.** The generation key is replaced after every call to `get()`. If an attacker compromises the internal state at time T, they cannot reconstruct any output produced before time T.
50
-
51
- **32 entropy pools.** Entropy is distributed across 32 independent pools using round-robin assignment. Pool 0 is used on every reseed, pool 1 on every second reseed, pool 2 on every fourth, and so on. This exponential schedule means that even if an attacker can observe or influence some entropy sources, higher-numbered pools accumulate enough entropy over time to produce a strong reseed eventually.
52
-
53
- **Immediate usability.** Fortuna seeds itself from `crypto.getRandomValues()` (browser) or `crypto.randomBytes()` (Node.js) during creation. You do not need to wait for entropy to accumulate before calling `get()`.
54
-
55
- **Browser entropy sources.** Mouse movements, keyboard events, click events, scroll position, touch events, device motion and orientation, `performance.now()` timing, DOM content hash, and periodic `crypto.getRandomValues()`.
56
-
57
- **Node.js entropy sources.** `crypto.randomBytes()`, `process.hrtime` (nanosecond timing jitter), `process.cpuUsage()`, `process.memoryUsage()`, `os.loadavg()`, `os.freemem()`.
58
-
59
- **Wipe state when done.** Call `stop()` when you are finished with the instance. This wipes the generation key and counter from memory and stops all background entropy collectors. Key material should not persist longer than necessary.
60
-
61
- **Output quality depends on entropy.** The initial seed from the OS random source is strong. Over time the additional entropy collectors improve the state further. In environments with limited user interaction (headless servers, automated tests), fewer entropy sources contribute, but the OS random seed still provides a solid baseline.
62
-
63
- ---
64
-
65
- ## API Reference
66
-
67
- ### `Fortuna.create(opts?)`
68
-
69
- Static async factory. Returns a `Promise<Fortuna>`. The returned instance is
70
- guaranteed to be seeded. `create()` forces an initial reseed before resolving,
71
- so `get()` is immediately usable.
72
-
73
- ```typescript
74
- static async create(opts?: {
75
- msPerReseed?: number;
76
- entropy?: Uint8Array;
77
- }): Promise<Fortuna>
78
- ```
79
-
80
- | Parameter | Type | Default | Description |
81
- |-----------|------|---------|-------------|
82
- | `opts.msPerReseed` | `number` | `100` | Minimum milliseconds between reseeds. |
83
- | `opts.entropy` | `Uint8Array` | | Optional extra entropy to mix in during creation. |
84
-
85
- Throws if `init({ serpent: serpentWasm, sha2: sha2Wasm })` has not been called.
86
-
87
- Direct construction with `new Fortuna()` is not possible. The constructor is private. Always use `Fortuna.create()`.
88
-
89
- ---
90
-
91
- ### `get(length)`
92
-
93
- Generate `length` random bytes.
94
-
95
- ```typescript
96
- get(length: number): Uint8Array
97
- ```
98
-
99
- Returns a `Uint8Array` of the requested length. The instance is always seeded
100
- after `create()` resolves, so this method is guaranteed to return data.
101
-
102
- After producing the output, the generation key is replaced with fresh
103
- pseudorandom material. This is the forward secrecy mechanism. The key used to
104
- produce this output no longer exists.
105
-
106
- ---
107
-
108
- ### `addEntropy(entropy)`
109
-
110
- Manually add entropy to the pools.
111
-
112
- ```typescript
113
- addEntropy(entropy: Uint8Array): void
114
- ```
115
-
116
- Use this to feed application-specific randomness into the generator. The entropy
117
- is distributed across pools using round-robin assignment. Each call advances to
118
- the next pool.
119
-
120
- ---
121
-
122
- ### `getEntropy()`
123
-
124
- Get the estimated available entropy in bytes.
125
-
126
- ```typescript
127
- getEntropy(): number
128
- ```
129
-
130
- Returns the estimated total entropy accumulated across all pools, in bytes. This
131
- is an estimate, not a guarantee. It reflects the sum of entropy credits assigned by each collector.
132
-
133
- ---
134
-
135
- ### `stop()`
136
-
137
- Permanently dispose this Fortuna instance.
138
-
139
- ```typescript
140
- stop(): void
141
- ```
142
-
143
- > [!WARNING]
144
- > Do not attempt to reuse a stopped instance. `stop()` is a permanent dispose
145
- > operation. If a new Fortuna instance is needed, call `Fortuna.create()`.
146
-
147
- Call this when you are done with the Fortuna instance. `stop()`:
148
- - Removes all browser event listeners
149
- - Clears all background timers (Node.js stats collection, periodic crypto random)
150
- - Zeroes the generation key and counter
151
- - Resets the reseed counter to 0
152
- - Marks the instance as disposed
153
-
154
- All subsequent method calls (`get()`, `addEntropy()`, `getEntropy()`, `stop()`)
155
- on a disposed instance throw immediately:
156
- ```
157
- Error: Fortuna instance has been disposed
158
- ```
159
-
160
- There is no `start()` or restart capability.
161
-
162
- ---
163
-
164
- ## Usage Examples
165
-
166
- ### Basic usage
167
-
168
- ```typescript
169
- import { init, Fortuna } from 'leviathan-crypto'
170
- import { serpentWasm } from 'leviathan-crypto/serpent/embedded'
171
- import { sha2Wasm } from 'leviathan-crypto/sha2/embedded'
172
-
173
- // Initialize both WASM modules that Fortuna depends on
174
- await init({ serpent: serpentWasm, sha2: sha2Wasm })
175
-
176
- // Create the CSPRNG
177
- const rng = await Fortuna.create()
178
-
179
- // Generate 32 random bytes (e.g., for an encryption key)
180
- const key = rng.get(32)
181
-
182
- // Generate 12 random bytes (e.g., for a nonce)
183
- const nonce = rng.get(12)
184
-
185
- // Clean up when done, wipes key material from memory
186
- rng.stop()
187
- ```
188
-
189
- ### Adding custom entropy
190
-
191
- ```typescript
192
- import { init, Fortuna, utf8ToBytes } from 'leviathan-crypto'
193
- import { serpentWasm } from 'leviathan-crypto/serpent/embedded'
194
- import { sha2Wasm } from 'leviathan-crypto/sha2/embedded'
195
-
196
- await init({ serpent: serpentWasm, sha2: sha2Wasm })
197
- const rng = await Fortuna.create()
198
-
199
- // Feed application-specific data as additional entropy.
200
- // This supplements (never replaces) the automatic entropy collection.
201
- const userData = utf8ToBytes(crypto.randomUUID())
202
- rng.addEntropy(userData)
203
-
204
- // Server-side: feed in request-specific data
205
- const requestEntropy = new Uint8Array(16)
206
- crypto.getRandomValues(requestEntropy)
207
- rng.addEntropy(requestEntropy)
208
-
209
- const token = rng.get(32)
210
- rng.stop()
211
- ```
212
-
213
- ### Browser with automatic entropy collection
214
-
215
- ```typescript
216
- import { init, Fortuna } from 'leviathan-crypto'
217
- import { serpentWasm } from 'leviathan-crypto/serpent/embedded'
218
- import { sha2Wasm } from 'leviathan-crypto/sha2/embedded'
219
-
220
- await init({ serpent: serpentWasm, sha2: sha2Wasm })
221
-
222
- // Fortuna automatically registers browser event listeners on creation:
223
- // - mousemove (throttled to 50ms)
224
- // - keydown
225
- // - click
226
- // - scroll
227
- // - touchstart, touchmove, touchend
228
- // - devicemotion, deviceorientation, orientationchange
229
- //
230
- // Every user interaction feeds entropy into the pools.
231
- // No manual setup is needed, it starts collecting immediately.
232
-
233
- const rng = await Fortuna.create()
234
-
235
- // The longer the user interacts with the page before you generate,
236
- // the more entropy has been accumulated. But the initial OS seed
237
- // is strong enough for immediate use.
238
- document.querySelector('#generate')?.addEventListener('click', () => {
239
- const bytes = rng.get(32)
240
- console.log('Generated:', bytes)
241
- })
242
-
243
- // When the page unloads or the component unmounts, stop the collectors
244
- window.addEventListener('beforeunload', () => rng.stop())
245
- ```
246
-
247
- ### Providing initial entropy at creation
248
-
249
- ```typescript
250
- import { init, Fortuna } from 'leviathan-crypto'
251
- import { serpentWasm } from 'leviathan-crypto/serpent/embedded'
252
- import { sha2Wasm } from 'leviathan-crypto/sha2/embedded'
253
-
254
- await init({ serpent: serpentWasm, sha2: sha2Wasm })
255
-
256
- // You can pass extra entropy at creation time.
257
- // This is mixed into the pools during initialization, before the
258
- // generator is first seeded.
259
- const extraSeed = new Uint8Array(64)
260
- crypto.getRandomValues(extraSeed)
261
-
262
- const rng = await Fortuna.create({ entropy: extraSeed })
263
- const bytes = rng.get(32)
264
- rng.stop()
265
- ```
266
-
267
- ---
268
-
269
- ## Error Conditions
270
-
271
- | Condition | What happens |
272
- |-----------|-------------|
273
- | `init()` not called | `Fortuna.create()` throws: `leviathan-crypto: call init({ serpent: ..., sha2: ... }) before using Fortuna` |
274
- | Only one module initialized | Same error. Both `serpent` and `sha2` must be initialized. |
275
- | `new Fortuna()` | Compile-time error. The constructor is private. TypeScript will not allow it. |
276
- | Any method after `stop()` | Throws: `Fortuna instance has been disposed`. The instance is permanently disposed. |
277
-
278
- ---
279
-
280
- ## How It Works (Simplified)
281
-
282
- For readers who want to understand what Fortuna does internally, without needing
283
- to read the spec:
284
-
285
- 1. **Entropy collection.** Background listeners and timers capture small,
286
- unpredictable measurements (mouse coordinates, nanosecond timings, memory
287
- usage) and feed them into 32 separate pools via SHA-256 hash chaining.
288
-
289
- 2. **Reseed.** When pool 0 has accumulated enough entropy and enough time has
290
- passed since the last reseed, Fortuna combines the contents of eligible pools
291
- (determined by the reseed counter) into a seed, and derives a new generation
292
- key: `genKey = SHA-256(genKey || seed)`.
293
-
294
- 3. **Generation.** To produce output, the generator encrypts an incrementing
295
- counter with Serpent-256 in ECB mode using the current generation key. The
296
- output is the concatenation of encrypted counter blocks, truncated to the
297
- requested length.
298
-
299
- 4. **Key replacement.** Immediately after producing output, the generation key
300
- is replaced with fresh pseudorandom blocks. The old key is gone. This is what
301
- provides forward secrecy.
302
-
303
- ---
304
-
305
- > ## Cross-References
306
- >
307
- > - [index](./README.md) — Project Documentation index
308
- > - [architecture](./architecture.md) — architecture overview, module relationships, buffer layouts, and build pipeline
309
- > - [serpent](./serpent.md) — Serpent-256 TypeScript API (Fortuna uses Serpent ECB internally)
310
- > - [sha2](./sha2.md) — SHA-256 TypeScript API (Fortuna uses SHA-256 for entropy accumulation)
311
- > - [asm_serpent](./asm_serpent.md) — Serpent-256 WASM implementation details
312
- > - [asm_sha2](./asm_sha2.md) — SHA-256 WASM implementation details
313
- > - [utils](./utils.md) — `randomBytes()` for simpler random generation needs