leviathan-crypto 2.1.0 → 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 (296) hide show
  1. package/CLAUDE.md +86 -443
  2. package/README.md +198 -65
  3. package/dist/aes/aes-cbc.d.ts +40 -0
  4. package/dist/aes/aes-cbc.js +158 -0
  5. package/dist/aes/aes-ctr.d.ts +50 -0
  6. package/dist/aes/aes-ctr.js +141 -0
  7. package/dist/aes/aes-gcm-siv.d.ts +67 -0
  8. package/dist/aes/aes-gcm-siv.js +217 -0
  9. package/dist/aes/aes-gcm.d.ts +61 -0
  10. package/dist/aes/aes-gcm.js +226 -0
  11. package/dist/aes/cipher-suite.d.ts +21 -0
  12. package/dist/aes/cipher-suite.js +179 -0
  13. package/dist/aes/embedded.d.ts +1 -0
  14. package/dist/aes/embedded.js +26 -0
  15. package/dist/aes/generator.d.ts +14 -0
  16. package/dist/aes/generator.js +103 -0
  17. package/dist/aes/index.d.ts +58 -0
  18. package/dist/aes/index.js +125 -0
  19. package/dist/aes/ops.d.ts +60 -0
  20. package/dist/aes/ops.js +164 -0
  21. package/dist/aes/pool-worker.d.ts +1 -0
  22. package/dist/aes/pool-worker.js +92 -0
  23. package/dist/aes/types.d.ts +1 -0
  24. package/dist/aes/types.js +23 -0
  25. package/dist/aes.wasm +0 -0
  26. package/dist/blake3/embedded.d.ts +1 -0
  27. package/dist/blake3/embedded.js +26 -0
  28. package/dist/blake3/index.d.ts +143 -0
  29. package/dist/blake3/index.js +620 -0
  30. package/dist/blake3/types.d.ts +102 -0
  31. package/dist/blake3/types.js +31 -0
  32. package/dist/blake3/validate.d.ts +29 -0
  33. package/dist/blake3/validate.js +80 -0
  34. package/dist/blake3.wasm +0 -0
  35. package/dist/chacha20/cipher-suite.js +47 -25
  36. package/dist/chacha20/generator.d.ts +2 -2
  37. package/dist/chacha20/generator.js +4 -4
  38. package/dist/chacha20/index.d.ts +16 -15
  39. package/dist/chacha20/index.js +52 -46
  40. package/dist/chacha20/ops.d.ts +7 -7
  41. package/dist/chacha20/ops.js +34 -34
  42. package/dist/chacha20/pool-worker.js +5 -3
  43. package/dist/cte-wasm.d.ts +1 -0
  44. package/dist/cte-wasm.js +3 -0
  45. package/dist/curve25519.wasm +0 -0
  46. package/dist/ecdsa/der.d.ts +23 -0
  47. package/dist/ecdsa/der.js +192 -0
  48. package/dist/ecdsa/ecprivatekey-der.d.ts +32 -0
  49. package/dist/ecdsa/ecprivatekey-der.js +230 -0
  50. package/dist/ecdsa/embedded.d.ts +1 -0
  51. package/dist/ecdsa/embedded.js +25 -0
  52. package/dist/ecdsa/index.d.ts +124 -0
  53. package/dist/ecdsa/index.js +366 -0
  54. package/dist/ecdsa/types.d.ts +31 -0
  55. package/dist/ecdsa/types.js +28 -0
  56. package/dist/ecdsa/validate.d.ts +18 -0
  57. package/dist/ecdsa/validate.js +92 -0
  58. package/dist/ed25519/embedded.d.ts +1 -0
  59. package/dist/ed25519/embedded.js +31 -0
  60. package/dist/ed25519/index.d.ts +70 -0
  61. package/dist/ed25519/index.js +308 -0
  62. package/dist/ed25519/types.d.ts +27 -0
  63. package/dist/ed25519/types.js +27 -0
  64. package/dist/ed25519/validate.d.ts +7 -0
  65. package/dist/ed25519/validate.js +77 -0
  66. package/dist/embedded/aes-pool-worker.d.ts +1 -0
  67. package/dist/embedded/aes-pool-worker.js +5 -0
  68. package/dist/embedded/aes.d.ts +1 -0
  69. package/dist/embedded/aes.js +3 -0
  70. package/dist/embedded/blake3.d.ts +1 -0
  71. package/dist/embedded/blake3.js +3 -0
  72. package/dist/embedded/chacha20-pool-worker.d.ts +1 -1
  73. package/dist/embedded/chacha20-pool-worker.js +2 -2
  74. package/dist/embedded/chacha20.d.ts +1 -1
  75. package/dist/embedded/chacha20.js +2 -2
  76. package/dist/embedded/curve25519.d.ts +1 -0
  77. package/dist/embedded/curve25519.js +3 -0
  78. package/dist/embedded/mldsa.d.ts +1 -0
  79. package/dist/embedded/mldsa.js +3 -0
  80. package/dist/embedded/mlkem.d.ts +1 -0
  81. package/dist/embedded/mlkem.js +3 -0
  82. package/dist/embedded/p256.d.ts +1 -0
  83. package/dist/embedded/p256.js +3 -0
  84. package/dist/embedded/serpent-pool-worker.d.ts +1 -1
  85. package/dist/embedded/serpent-pool-worker.js +2 -2
  86. package/dist/embedded/serpent.d.ts +1 -1
  87. package/dist/embedded/serpent.js +2 -2
  88. package/dist/embedded/sha2.d.ts +1 -1
  89. package/dist/embedded/sha2.js +2 -2
  90. package/dist/embedded/sha3.d.ts +1 -1
  91. package/dist/embedded/sha3.js +2 -2
  92. package/dist/embedded/slhdsa.d.ts +1 -0
  93. package/dist/embedded/slhdsa.js +3 -0
  94. package/dist/errors.d.ts +92 -1
  95. package/dist/errors.js +111 -1
  96. package/dist/fortuna.d.ts +5 -5
  97. package/dist/fortuna.js +37 -64
  98. package/dist/index.d.ts +38 -9
  99. package/dist/index.js +63 -19
  100. package/dist/init.d.ts +1 -1
  101. package/dist/init.js +11 -25
  102. package/dist/keccak/embedded.js +1 -1
  103. package/dist/keccak/index.d.ts +2 -0
  104. package/dist/keccak/index.js +4 -2
  105. package/dist/loader.d.ts +1 -24
  106. package/dist/loader.js +13 -16
  107. package/dist/merkle/blake3-tree.d.ts +35 -0
  108. package/dist/merkle/blake3-tree.js +187 -0
  109. package/dist/merkle/checkpoint.d.ts +58 -0
  110. package/dist/merkle/checkpoint.js +217 -0
  111. package/dist/merkle/index.d.ts +19 -0
  112. package/dist/merkle/index.js +37 -0
  113. package/dist/merkle/merkle-log.d.ts +130 -0
  114. package/dist/merkle/merkle-log.js +207 -0
  115. package/dist/merkle/merkle-verifier.d.ts +126 -0
  116. package/dist/merkle/merkle-verifier.js +296 -0
  117. package/dist/merkle/proof.d.ts +70 -0
  118. package/dist/merkle/proof.js +300 -0
  119. package/dist/merkle/sha256-tree.d.ts +33 -0
  120. package/dist/merkle/sha256-tree.js +145 -0
  121. package/dist/merkle/signed-log.d.ts +156 -0
  122. package/dist/merkle/signed-log.js +356 -0
  123. package/dist/merkle/signed-note.d.ts +309 -0
  124. package/dist/merkle/signed-note.js +648 -0
  125. package/dist/merkle/sth.d.ts +31 -0
  126. package/dist/merkle/sth.js +31 -0
  127. package/dist/merkle/storage.d.ts +40 -0
  128. package/dist/merkle/storage.js +71 -0
  129. package/dist/merkle/tree.d.ts +68 -0
  130. package/dist/merkle/tree.js +94 -0
  131. package/dist/mldsa/embedded.d.ts +1 -0
  132. package/dist/{kyber → mldsa}/embedded.js +5 -5
  133. package/dist/mldsa/expand.d.ts +53 -0
  134. package/dist/mldsa/expand.js +188 -0
  135. package/dist/mldsa/format.d.ts +16 -0
  136. package/dist/mldsa/format.js +68 -0
  137. package/dist/mldsa/hashvariant.d.ts +32 -0
  138. package/dist/mldsa/hashvariant.js +248 -0
  139. package/dist/mldsa/index.d.ts +142 -0
  140. package/dist/mldsa/index.js +463 -0
  141. package/dist/mldsa/keygen.d.ts +16 -0
  142. package/dist/mldsa/keygen.js +232 -0
  143. package/dist/mldsa/params.d.ts +21 -0
  144. package/dist/mldsa/params.js +55 -0
  145. package/dist/mldsa/sha3-helpers.d.ts +30 -0
  146. package/dist/mldsa/sha3-helpers.js +124 -0
  147. package/dist/mldsa/sign.d.ts +36 -0
  148. package/dist/mldsa/sign.js +380 -0
  149. package/dist/mldsa/types.d.ts +91 -0
  150. package/dist/mldsa/types.js +25 -0
  151. package/dist/mldsa/validate.d.ts +55 -0
  152. package/dist/mldsa/validate.js +125 -0
  153. package/dist/mldsa/verify.d.ts +29 -0
  154. package/dist/mldsa/verify.js +269 -0
  155. package/dist/mldsa.wasm +0 -0
  156. package/dist/mlkem/embedded.d.ts +1 -0
  157. package/dist/mlkem/embedded.js +27 -0
  158. package/dist/mlkem/indcpa.d.ts +49 -0
  159. package/dist/{kyber → mlkem}/indcpa.js +44 -44
  160. package/dist/mlkem/index.d.ts +37 -0
  161. package/dist/{kyber → mlkem}/index.js +24 -34
  162. package/dist/mlkem/kem.d.ts +21 -0
  163. package/dist/{kyber → mlkem}/kem.js +44 -64
  164. package/dist/{kyber → mlkem}/params.d.ts +4 -4
  165. package/dist/{kyber → mlkem}/params.js +2 -2
  166. package/dist/mlkem/suite.d.ts +12 -0
  167. package/dist/{kyber → mlkem}/suite.js +17 -12
  168. package/dist/{kyber → mlkem}/types.d.ts +3 -3
  169. package/dist/{kyber → mlkem}/types.js +1 -1
  170. package/dist/{kyber → mlkem}/validate.d.ts +7 -7
  171. package/dist/{kyber → mlkem}/validate.js +7 -7
  172. package/dist/{kyber.wasm → mlkem.wasm} +0 -0
  173. package/dist/p256.wasm +0 -0
  174. package/dist/ratchet/index.d.ts +2 -0
  175. package/dist/ratchet/index.js +1 -0
  176. package/dist/ratchet/kdf-chain.js +3 -3
  177. package/dist/ratchet/ratchet-keypair.js +2 -2
  178. package/dist/ratchet/root-kdf.js +7 -7
  179. package/dist/ratchet/skipped-key-store.js +4 -4
  180. package/dist/ratchet/types.d.ts +1 -1
  181. package/dist/serpent/cipher-suite.js +20 -17
  182. package/dist/serpent/generator.d.ts +1 -1
  183. package/dist/serpent/generator.js +2 -2
  184. package/dist/serpent/index.d.ts +8 -7
  185. package/dist/serpent/index.js +18 -27
  186. package/dist/serpent/pool-worker.js +7 -5
  187. package/dist/serpent/serpent-cbc.d.ts +4 -4
  188. package/dist/serpent/serpent-cbc.js +11 -8
  189. package/dist/serpent/shared-ops.d.ts +3 -23
  190. package/dist/serpent/shared-ops.js +50 -85
  191. package/dist/serpent.wasm +0 -0
  192. package/dist/sha2/hkdf.js +5 -5
  193. package/dist/sha2/index.d.ts +21 -1
  194. package/dist/sha2/index.js +65 -10
  195. package/dist/sha2/types.d.ts +41 -2
  196. package/dist/sha2.wasm +0 -0
  197. package/dist/sha3/index.d.ts +72 -3
  198. package/dist/sha3/index.js +240 -14
  199. package/dist/sha3/kmac.d.ts +121 -0
  200. package/dist/sha3/kmac.js +800 -0
  201. package/dist/sha3.wasm +0 -0
  202. package/dist/shared/pkcs7.d.ts +22 -0
  203. package/dist/shared/pkcs7.js +84 -0
  204. package/dist/sign/ctx.d.ts +41 -0
  205. package/dist/sign/ctx.js +102 -0
  206. package/dist/sign/envelope.d.ts +45 -0
  207. package/dist/sign/envelope.js +152 -0
  208. package/dist/sign/hasher.d.ts +9 -0
  209. package/dist/sign/hasher.js +132 -0
  210. package/dist/sign/index.d.ts +11 -0
  211. package/dist/sign/index.js +34 -0
  212. package/dist/sign/sign-stream.d.ts +25 -0
  213. package/dist/sign/sign-stream.js +112 -0
  214. package/dist/sign/suites/ecdsa-p256.d.ts +2 -0
  215. package/dist/sign/suites/ecdsa-p256.js +120 -0
  216. package/dist/sign/suites/ed25519.d.ts +3 -0
  217. package/dist/sign/suites/ed25519.js +165 -0
  218. package/dist/sign/suites/hybrid-classical.d.ts +23 -0
  219. package/dist/sign/suites/hybrid-classical.js +526 -0
  220. package/dist/sign/suites/hybrid-pq.d.ts +4 -0
  221. package/dist/sign/suites/hybrid-pq.js +234 -0
  222. package/dist/sign/suites/mldsa.d.ts +7 -0
  223. package/dist/sign/suites/mldsa.js +161 -0
  224. package/dist/sign/suites/slhdsa.d.ts +7 -0
  225. package/dist/sign/suites/slhdsa.js +176 -0
  226. package/dist/sign/types.d.ts +106 -0
  227. package/dist/sign/types.js +28 -0
  228. package/dist/sign/verify-stream.d.ts +30 -0
  229. package/dist/sign/verify-stream.js +227 -0
  230. package/dist/slhdsa/embedded.d.ts +1 -0
  231. package/dist/slhdsa/embedded.js +26 -0
  232. package/dist/slhdsa/index.d.ts +149 -0
  233. package/dist/slhdsa/index.js +493 -0
  234. package/dist/slhdsa/params.d.ts +26 -0
  235. package/dist/slhdsa/params.js +70 -0
  236. package/dist/slhdsa/prehash.d.ts +68 -0
  237. package/dist/slhdsa/prehash.js +307 -0
  238. package/dist/slhdsa/sign.d.ts +39 -0
  239. package/dist/slhdsa/sign.js +116 -0
  240. package/dist/slhdsa/types.d.ts +129 -0
  241. package/dist/slhdsa/types.js +27 -0
  242. package/dist/slhdsa/validate.d.ts +60 -0
  243. package/dist/slhdsa/validate.js +127 -0
  244. package/dist/slhdsa/verify.d.ts +32 -0
  245. package/dist/slhdsa/verify.js +107 -0
  246. package/dist/slhdsa.wasm +0 -0
  247. package/dist/stream/header.js +3 -3
  248. package/dist/stream/index.d.ts +1 -0
  249. package/dist/stream/index.js +1 -0
  250. package/dist/stream/open-stream.js +31 -10
  251. package/dist/stream/seal-stream-pool.d.ts +1 -0
  252. package/dist/stream/seal-stream-pool.js +63 -26
  253. package/dist/stream/seal-stream.d.ts +1 -1
  254. package/dist/stream/seal-stream.js +20 -9
  255. package/dist/stream/seal.js +6 -6
  256. package/dist/stream/types.d.ts +3 -1
  257. package/dist/stream/types.js +1 -1
  258. package/dist/types.d.ts +1 -1
  259. package/dist/types.js +1 -1
  260. package/dist/utils.d.ts +3 -3
  261. package/dist/utils.js +46 -54
  262. package/dist/wasm-source.d.ts +7 -7
  263. package/dist/wasm-source.js +1 -1
  264. package/dist/x25519/embedded.d.ts +1 -0
  265. package/dist/x25519/embedded.js +31 -0
  266. package/dist/x25519/index.d.ts +43 -0
  267. package/dist/x25519/index.js +159 -0
  268. package/dist/x25519/types.d.ts +25 -0
  269. package/dist/x25519/types.js +27 -0
  270. package/dist/x25519/validate.d.ts +2 -0
  271. package/dist/x25519/validate.js +39 -0
  272. package/package.json +70 -26
  273. package/SECURITY.md +0 -163
  274. package/dist/ct-wasm.d.ts +0 -1
  275. package/dist/ct-wasm.js +0 -3
  276. package/dist/docs/aead.md +0 -363
  277. package/dist/docs/architecture.md +0 -1011
  278. package/dist/docs/argon2id.md +0 -305
  279. package/dist/docs/chacha20.md +0 -781
  280. package/dist/docs/exports.md +0 -277
  281. package/dist/docs/fortuna.md +0 -530
  282. package/dist/docs/init.md +0 -301
  283. package/dist/docs/loader.md +0 -256
  284. package/dist/docs/serpent.md +0 -617
  285. package/dist/docs/sha2.md +0 -671
  286. package/dist/docs/sha3.md +0 -612
  287. package/dist/docs/types.md +0 -416
  288. package/dist/docs/utils.md +0 -457
  289. package/dist/embedded/kyber.d.ts +0 -1
  290. package/dist/embedded/kyber.js +0 -3
  291. package/dist/kyber/embedded.d.ts +0 -1
  292. package/dist/kyber/indcpa.d.ts +0 -49
  293. package/dist/kyber/index.d.ts +0 -38
  294. package/dist/kyber/kem.d.ts +0 -21
  295. package/dist/kyber/suite.d.ts +0 -12
  296. /package/dist/{ct.wasm → cte.wasm} +0 -0
@@ -0,0 +1,125 @@
1
+ // ▄▄▄▄▄▄▄▄▄▄
2
+ // ▄████████████████████▄▄ ▒ ▄▀▀ ▒ ▒ █ ▄▀▄ ▀█▀ █ ▒ ▄▀▄ █▀▄
3
+ // ▄██████████████████████ ▀████▄ ▓ ▓▀ ▓ ▓ ▓ ▓▄▓ ▓ ▓▀▓ ▓▄▓ ▓ ▓
4
+ // ▄█████████▀▀▀ ▀███████▄▄███████▌ ▀▄ ▀▄▄ ▀▄▀ ▒ ▒ ▒ ▒ ▒ █ ▒ ▒ ▒ █
5
+ // ▐████████▀ ▄▄▄▄ ▀████████▀██▀█▌
6
+ // ████████ ███▀▀ ████▀ █▀ █▀ Leviathan Crypto Library
7
+ // ███████▌ ▀██▀ ███
8
+ // ███████ ▀███ ▀██ ▀█▄ Repository & Mirror:
9
+ // ▀██████ ▄▄██ ▀▀ ██▄ github.com/xero/leviathan-crypto
10
+ // ▀█████▄ ▄██▄ ▄▀▄▀ unpkg.com/leviathan-crypto
11
+ // ▀████▄ ▄██▄
12
+ // ▐████ ▐███ Author: xero (https://x-e.ro)
13
+ // ▄▄██████████ ▐███ ▄▄ License: MIT
14
+ // ▄██▀▀▀▀▀▀▀▀▀▀ ▄████ ▄██▀
15
+ // ▄▀ ▄▄█████████▄▄ ▀▀▀▀▀ ▄███ This file is provided completely
16
+ // ▄██████▀▀▀▀▀▀██████▄ ▀▄▄▄▄████▀ free, "as is", and without
17
+ // ████▀ ▄▄▄▄▄▄▄ ▀████▄ ▀█████▀ ▄▄▄▄ warranty of any kind. The author
18
+ // █████▄▄█████▀▀▀▀▀▀▄ ▀███▄ ▄████ assumes absolutely no liability
19
+ // ▀██████▀ ▀████▄▄▄████▀ for its {ab,mis,}use.
20
+ // ▀█████▀▀
21
+ //
22
+ // src/ts/aes/index.ts
23
+ //
24
+ // Public API classes for the AES WASM module.
25
+ // AES-128/192/256 supported.
26
+ import { getInstance, initModule, _assertNotOwned } from '../init.js';
27
+ /**
28
+ * Load and initialise the AES WASM module from `source`.
29
+ * Must be called before constructing any AES class.
30
+ * @param source WASM binary, gzip+base64 string, URL, ArrayBuffer, Uint8Array,
31
+ * pre-compiled WebAssembly.Module, Response, or Promise<Response>
32
+ */
33
+ export async function aesInit(source) {
34
+ return initModule('aes', source);
35
+ }
36
+ export { isInitialized } from '../init.js';
37
+ /** Returns the raw AES WASM export object. @internal */
38
+ function getExports() {
39
+ return getInstance('aes').exports;
40
+ }
41
+ // ── AES ─────────────────────────────────────────────────────────────────────
42
+ /**
43
+ * Low-level AES block cipher, raw ECB encrypt + decrypt.
44
+ *
45
+ * AES-128/192/256 supported. `loadKey` accepts 16, 24, or 32 byte keys;
46
+ * Nr (10, 12, or 14) is derived and persisted in WASM memory between
47
+ * `loadKey` and the cipher calls.
48
+ *
49
+ * Decrypt uses the FIPS 197 §5.3.5 Equivalent Inverse Cipher: the round
50
+ * loop mirrors encrypt, and round keys 1..Nr-1 are pre-transformed by
51
+ * InvMixColumns inside `loadKey`.
52
+ *
53
+ * Atomic (stateless): each method call is independent. Does not hold
54
+ * exclusive module access. Call `dispose()` after use to wipe WASM key
55
+ * material.
56
+ */
57
+ export class AES {
58
+ x;
59
+ constructor() {
60
+ this.x = getExports();
61
+ }
62
+ /**
63
+ * Expand `key` into the WASM key schedule (forward + EqInvCipher
64
+ * inverse round keys). Must be called before `encryptBlock` or
65
+ * `decryptBlock`.
66
+ * @param key 16, 24, or 32 bytes (AES-128 / 192 / 256)
67
+ */
68
+ loadKey(key) {
69
+ _assertNotOwned('aes');
70
+ if (key.length !== 16 && key.length !== 24 && key.length !== 32)
71
+ throw new RangeError(`AES.loadKey: key must be 16, 24, or 32 bytes (got ${key.length})`);
72
+ const mem = new Uint8Array(this.x.memory.buffer);
73
+ mem.set(key, this.x.getKeyOffset());
74
+ if (this.x.loadKey(key.length) !== 0) {
75
+ this.x.wipeBuffers();
76
+ throw new Error('loadKey failed');
77
+ }
78
+ }
79
+ /**
80
+ * Encrypt one 128-bit block with the previously loaded key schedule.
81
+ * FIPS 197 §5.1 Algorithm 1, Nr ∈ {10, 12, 14}.
82
+ * @param plaintext 16-byte plaintext block
83
+ * @returns 16-byte ciphertext block
84
+ */
85
+ encryptBlock(plaintext) {
86
+ _assertNotOwned('aes');
87
+ if (plaintext.length !== 16)
88
+ throw new RangeError(`block must be 16 bytes (got ${plaintext.length})`);
89
+ const mem = new Uint8Array(this.x.memory.buffer);
90
+ const ptOff = this.x.getBlockPtOffset();
91
+ const ctOff = this.x.getBlockCtOffset();
92
+ mem.set(plaintext, ptOff);
93
+ this.x.encryptBlock();
94
+ return mem.slice(ctOff, ctOff + 16);
95
+ }
96
+ /**
97
+ * Decrypt one 128-bit block with the previously loaded key schedule.
98
+ * FIPS 197 §5.3.5 Equivalent Inverse Cipher, Nr ∈ {10, 12, 14}.
99
+ * @param ciphertext 16-byte ciphertext block
100
+ * @returns 16-byte plaintext block
101
+ */
102
+ decryptBlock(ciphertext) {
103
+ _assertNotOwned('aes');
104
+ if (ciphertext.length !== 16)
105
+ throw new RangeError(`block must be 16 bytes (got ${ciphertext.length})`);
106
+ const mem = new Uint8Array(this.x.memory.buffer);
107
+ const ptOff = this.x.getBlockPtOffset();
108
+ const ctOff = this.x.getBlockCtOffset();
109
+ mem.set(ciphertext, ptOff);
110
+ this.x.decryptBlock();
111
+ return mem.slice(ctOff, ctOff + 16);
112
+ }
113
+ /** Wipe WASM key material and intermediate buffers. */
114
+ dispose() {
115
+ _assertNotOwned('aes');
116
+ this.x.wipeBuffers();
117
+ }
118
+ }
119
+ // ── CBC + CTR + GCM mode wrappers ───────────────────────────────────────────
120
+ export { AESCbc } from './aes-cbc.js';
121
+ export { AESCtr } from './aes-ctr.js';
122
+ export { AESGCM } from './aes-gcm.js';
123
+ export { AESGCMSIV } from './aes-gcm-siv.js';
124
+ export { AESGenerator } from './generator.js';
125
+ export { AESGCMSIVCipher } from './cipher-suite.js';
@@ -0,0 +1,60 @@
1
+ import type { AesExports } from './types.js';
2
+ /**
3
+ * AES-256-GCM-SIV AEAD encrypt (RFC 8452). Single-shot per call; the
4
+ * plaintext is bounded by the AES module's WASM CHUNK_SIZE.
5
+ *
6
+ * Stage: write KGK at KEY_OFFSET, expand round keys, write nonce/AAD/PT
7
+ * into their slots, run `sivDeriveKeys(NONCE_OFFSET)`, then `sivSeal`.
8
+ * `sivSeal` overwrites CHUNK_PT with the ciphertext in place; the tag
9
+ * lands at TAG_OFFSET.
10
+ *
11
+ * @note AES-256 only, the key MUST be 32 bytes. The standalone
12
+ * `AESGCMSIV` class accepts both 16-byte (AES-128) and 32-byte
13
+ * (AES-256) keys per RFC 8452 §6, but this `ops.ts` path is the
14
+ * internal helper for `AESGCMSIVCipher` and the AES pool worker,
15
+ * both of which fix the cipher suite at AES-256 to keep the wire
16
+ * format uniform across deployments. A 16-byte key here throws
17
+ * `RangeError('AES-GCM-SIV: key must be 32 bytes (got 16)')`. Use
18
+ * the `AESGCMSIV` class directly if you need AES-128.
19
+ *
20
+ * @param x AES WASM exports
21
+ * @param key 32-byte AES-256 key (KGK in RFC 8452 terminology)
22
+ * @param nonce 12-byte nonce, must be unique per `(key, message)`
23
+ * under the standard nonce-respecting model; reuse is
24
+ * tolerated by the SIV construction but reduces IND-CPA
25
+ * to message-equality leakage
26
+ * @param plaintext Data to encrypt; must be ≤ `x.getChunkSize()`
27
+ * @param aad Additional authenticated data; must be ≤ 64 KiB
28
+ * @returns `{ ciphertext, tag }`, tag is 16 bytes
29
+ */
30
+ export declare function sivAeadEncrypt(x: AesExports, key: Uint8Array, nonce: Uint8Array, plaintext: Uint8Array, aad: Uint8Array): {
31
+ ciphertext: Uint8Array;
32
+ tag: Uint8Array;
33
+ };
34
+ /**
35
+ * AES-256-GCM-SIV AEAD decrypt (RFC 8452). Verify-after-decrypt, the
36
+ * tag is a function of the plaintext, so SIV reconstructs the plaintext
37
+ * before recomputing and comparing the tag in constant time.
38
+ *
39
+ * On mismatch, `sivWipeOnFail()` zeroes the unauthenticated plaintext at
40
+ * CHUNK_PT_OFFSET before this function throws. Subsequent reads of
41
+ * the WASM memory cannot recover plaintext from a forged ciphertext.
42
+ *
43
+ * @note AES-256 only, the key MUST be 32 bytes (matching
44
+ * `sivAeadEncrypt`). The standalone `AESGCMSIV` class supports
45
+ * both AES-128 and AES-256, but this `ops.ts` helper is the
46
+ * internal path used by `AESGCMSIVCipher` and the AES pool
47
+ * worker, both of which fix the cipher suite at AES-256. A
48
+ * 16-byte key here throws
49
+ * `RangeError('AES-GCM-SIV: key must be 32 bytes (got 16)')`.
50
+ *
51
+ * @param x AES WASM exports
52
+ * @param key 32-byte AES-256 key
53
+ * @param nonce 12-byte nonce, must match the value used to encrypt
54
+ * @param ciphertext Ciphertext bytes (must be ≤ `x.getChunkSize()`)
55
+ * @param tag 16-byte SIV tag
56
+ * @param aad Additional authenticated data
57
+ * @param cipherName Error label for `AuthenticationError` (default 'aes-gcm-siv')
58
+ * @returns Plaintext
59
+ */
60
+ export declare function sivAeadDecrypt(x: AesExports, key: Uint8Array, nonce: Uint8Array, ciphertext: Uint8Array, tag: Uint8Array, aad: Uint8Array, cipherName?: string): Uint8Array;
@@ -0,0 +1,164 @@
1
+ // ▄▄▄▄▄▄▄▄▄▄
2
+ // ▄████████████████████▄▄ ▒ ▄▀▀ ▒ ▒ █ ▄▀▄ ▀█▀ █ ▒ ▄▀▄ █▀▄
3
+ // ▄██████████████████████ ▀████▄ ▓ ▓▀ ▓ ▓ ▓ ▓▄▓ ▓ ▓▀▓ ▓▄▓ ▓ ▓
4
+ // ▄█████████▀▀▀ ▀███████▄▄███████▌ ▀▄ ▀▄▄ ▀▄▀ ▒ ▒ ▒ ▒ ▒ █ ▒ ▒ ▒ █
5
+ // ▐████████▀ ▄▄▄▄ ▀████████▀██▀█▌
6
+ // ████████ ███▀▀ ████▀ █▀ █▀ Leviathan Crypto Library
7
+ // ███████▌ ▀██▀ ███
8
+ // ███████ ▀███ ▀██ ▀█▄ Repository & Mirror:
9
+ // ▀██████ ▄▄██ ▀▀ ██▄ github.com/xero/leviathan-crypto
10
+ // ▀█████▄ ▄██▄ ▄▀▄▀ unpkg.com/leviathan-crypto
11
+ // ▀████▄ ▄██▄
12
+ // ▐████ ▐███ Author: xero (https://x-e.ro)
13
+ // ▄▄██████████ ▐███ ▄▄ License: MIT
14
+ // ▄██▀▀▀▀▀▀▀▀▀▀ ▄████ ▄██▀
15
+ // ▄▀ ▄▄█████████▄▄ ▀▀▀▀▀ ▄███ This file is provided completely
16
+ // ▄██████▀▀▀▀▀▀██████▄ ▀▄▄▄▄████▀ free, "as is", and without
17
+ // ████▀ ▄▄▄▄▄▄▄ ▀████▄ ▀█████▀ ▄▄▄▄ warranty of any kind. The author
18
+ // █████▄▄█████▀▀▀▀▀▀▄ ▀███▄ ▄████ assumes absolutely no liability
19
+ // ▀██████▀ ▀████▄▄▄████▀ for its {ab,mis,}use.
20
+ // ▀█████▀▀
21
+ //
22
+ // src/ts/aes/ops.ts
23
+ //
24
+ // Raw AES-GCM-SIV operations, standalone functions that take AesExports
25
+ // explicitly. Used by both `AESGCMSIVCipher` (cipher-suite.ts) and the
26
+ // pool worker (pool-worker.ts), eliminating duplication.
27
+ //
28
+ // This file MUST NOT import from `../init.js`. Pool workers have their
29
+ // own WASM instances; importing init in shared ops would couple them.
30
+ // The cipher suite obtains exports via getInstance at the call site and
31
+ // passes them down.
32
+ import { constantTimeEqual, wipe } from '../utils.js';
33
+ import { AuthenticationError } from '../errors.js';
34
+ const KEY_LEN_256 = 32;
35
+ const NONCE_LEN = 12;
36
+ const TAG_LEN = 16;
37
+ const MAX_AAD = 65536;
38
+ /**
39
+ * AES-256-GCM-SIV AEAD encrypt (RFC 8452). Single-shot per call; the
40
+ * plaintext is bounded by the AES module's WASM CHUNK_SIZE.
41
+ *
42
+ * Stage: write KGK at KEY_OFFSET, expand round keys, write nonce/AAD/PT
43
+ * into their slots, run `sivDeriveKeys(NONCE_OFFSET)`, then `sivSeal`.
44
+ * `sivSeal` overwrites CHUNK_PT with the ciphertext in place; the tag
45
+ * lands at TAG_OFFSET.
46
+ *
47
+ * @note AES-256 only, the key MUST be 32 bytes. The standalone
48
+ * `AESGCMSIV` class accepts both 16-byte (AES-128) and 32-byte
49
+ * (AES-256) keys per RFC 8452 §6, but this `ops.ts` path is the
50
+ * internal helper for `AESGCMSIVCipher` and the AES pool worker,
51
+ * both of which fix the cipher suite at AES-256 to keep the wire
52
+ * format uniform across deployments. A 16-byte key here throws
53
+ * `RangeError('AES-GCM-SIV: key must be 32 bytes (got 16)')`. Use
54
+ * the `AESGCMSIV` class directly if you need AES-128.
55
+ *
56
+ * @param x AES WASM exports
57
+ * @param key 32-byte AES-256 key (KGK in RFC 8452 terminology)
58
+ * @param nonce 12-byte nonce, must be unique per `(key, message)`
59
+ * under the standard nonce-respecting model; reuse is
60
+ * tolerated by the SIV construction but reduces IND-CPA
61
+ * to message-equality leakage
62
+ * @param plaintext Data to encrypt; must be ≤ `x.getChunkSize()`
63
+ * @param aad Additional authenticated data; must be ≤ 64 KiB
64
+ * @returns `{ ciphertext, tag }`, tag is 16 bytes
65
+ */
66
+ export function sivAeadEncrypt(x, key, nonce, plaintext, aad) {
67
+ if (key.length !== KEY_LEN_256)
68
+ throw new RangeError(`AES-GCM-SIV: key must be ${KEY_LEN_256} bytes (got ${key.length})`);
69
+ if (nonce.length !== NONCE_LEN)
70
+ throw new RangeError(`AES-GCM-SIV: nonce must be ${NONCE_LEN} bytes (got ${nonce.length})`);
71
+ const maxChunk = x.getChunkSize();
72
+ if (plaintext.length > maxChunk)
73
+ throw new RangeError(`AES-GCM-SIV: plaintext exceeds ${maxChunk} bytes, split into smaller chunks`);
74
+ if (aad.length > MAX_AAD)
75
+ throw new RangeError(`AES-GCM-SIV: AAD must be ≤ ${MAX_AAD} bytes (got ${aad.length})`);
76
+ const mem = new Uint8Array(x.memory.buffer);
77
+ mem.set(key, x.getKeyOffset());
78
+ if (x.loadKey(KEY_LEN_256) !== 0) {
79
+ x.wipeBuffers();
80
+ throw new Error('AES-GCM-SIV: loadKey failed');
81
+ }
82
+ mem.set(nonce, x.getNonceOffset());
83
+ if (aad.length > 0)
84
+ mem.set(aad, x.getAadOffset());
85
+ mem.set(plaintext, x.getChunkPtOffset());
86
+ x.sivDeriveKeys(x.getNonceOffset());
87
+ x.sivSeal(aad.length, plaintext.length);
88
+ // sivSeal writes the ciphertext in place at CHUNK_PT_OFFSET.
89
+ const ctOff = x.getChunkPtOffset();
90
+ const tagOff = x.getTagOffset();
91
+ const memView = new Uint8Array(x.memory.buffer);
92
+ const ciphertext = memView.slice(ctOff, ctOff + plaintext.length);
93
+ const tag = memView.slice(tagOff, tagOff + TAG_LEN);
94
+ return { ciphertext, tag };
95
+ }
96
+ /**
97
+ * AES-256-GCM-SIV AEAD decrypt (RFC 8452). Verify-after-decrypt, the
98
+ * tag is a function of the plaintext, so SIV reconstructs the plaintext
99
+ * before recomputing and comparing the tag in constant time.
100
+ *
101
+ * On mismatch, `sivWipeOnFail()` zeroes the unauthenticated plaintext at
102
+ * CHUNK_PT_OFFSET before this function throws. Subsequent reads of
103
+ * the WASM memory cannot recover plaintext from a forged ciphertext.
104
+ *
105
+ * @note AES-256 only, the key MUST be 32 bytes (matching
106
+ * `sivAeadEncrypt`). The standalone `AESGCMSIV` class supports
107
+ * both AES-128 and AES-256, but this `ops.ts` helper is the
108
+ * internal path used by `AESGCMSIVCipher` and the AES pool
109
+ * worker, both of which fix the cipher suite at AES-256. A
110
+ * 16-byte key here throws
111
+ * `RangeError('AES-GCM-SIV: key must be 32 bytes (got 16)')`.
112
+ *
113
+ * @param x AES WASM exports
114
+ * @param key 32-byte AES-256 key
115
+ * @param nonce 12-byte nonce, must match the value used to encrypt
116
+ * @param ciphertext Ciphertext bytes (must be ≤ `x.getChunkSize()`)
117
+ * @param tag 16-byte SIV tag
118
+ * @param aad Additional authenticated data
119
+ * @param cipherName Error label for `AuthenticationError` (default 'aes-gcm-siv')
120
+ * @returns Plaintext
121
+ */
122
+ export function sivAeadDecrypt(x, key, nonce, ciphertext, tag, aad, cipherName = 'aes-gcm-siv') {
123
+ if (key.length !== KEY_LEN_256)
124
+ throw new RangeError(`AES-GCM-SIV: key must be ${KEY_LEN_256} bytes (got ${key.length})`);
125
+ if (nonce.length !== NONCE_LEN)
126
+ throw new RangeError(`AES-GCM-SIV: nonce must be ${NONCE_LEN} bytes (got ${nonce.length})`);
127
+ if (tag.length !== TAG_LEN)
128
+ throw new RangeError(`AES-GCM-SIV: tag must be ${TAG_LEN} bytes (got ${tag.length})`);
129
+ const maxChunk = x.getChunkSize();
130
+ if (ciphertext.length > maxChunk)
131
+ throw new RangeError(`AES-GCM-SIV: ciphertext exceeds ${maxChunk} bytes, split into smaller chunks`);
132
+ if (aad.length > MAX_AAD)
133
+ throw new RangeError(`AES-GCM-SIV: AAD must be ≤ ${MAX_AAD} bytes (got ${aad.length})`);
134
+ const mem = new Uint8Array(x.memory.buffer);
135
+ mem.set(key, x.getKeyOffset());
136
+ if (x.loadKey(KEY_LEN_256) !== 0) {
137
+ x.wipeBuffers();
138
+ throw new Error('AES-GCM-SIV: loadKey failed');
139
+ }
140
+ mem.set(nonce, x.getNonceOffset());
141
+ if (aad.length > 0)
142
+ mem.set(aad, x.getAadOffset());
143
+ mem.set(ciphertext, x.getChunkCtOffset());
144
+ // sivOpen reads the provided tag from SIV_IC_OFFSET (the CTR initial
145
+ // counter slot, RFC 8452 §4, where the tag drives the CTR start).
146
+ mem.set(tag, x.getSivIcOffset());
147
+ x.sivDeriveKeys(x.getNonceOffset());
148
+ x.sivOpen(aad.length, ciphertext.length);
149
+ // Read the recomputed expected tag from TAG_OFFSET. slice() so the
150
+ // buffer survives any subsequent WASM memory growth.
151
+ const memView = new Uint8Array(x.memory.buffer);
152
+ const expectedTag = memView.slice(x.getTagOffset(), x.getTagOffset() + TAG_LEN);
153
+ // Defensive copy of the provided tag for the constant-time compare,
154
+ // callers may pass a view over a mutable buffer.
155
+ const providedTagCopy = new Uint8Array(tag);
156
+ if (!constantTimeEqual(expectedTag, providedTagCopy)) {
157
+ x.sivWipeOnFail();
158
+ wipe(expectedTag);
159
+ wipe(providedTagCopy);
160
+ throw new AuthenticationError(cipherName);
161
+ }
162
+ const ptOff = x.getChunkPtOffset();
163
+ return memView.slice(ptOff, ptOff + ciphertext.length);
164
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,92 @@
1
+ // / <reference lib="webworker" />
2
+ // src/ts/aes/pool-worker.ts
3
+ //
4
+ // Worker for SealStreamPool with AESGCMSIVCipher.
5
+ // Holds derived AES-256-GCM-SIV key and the AES WASM instance for the
6
+ // pool's lifetime. Per-job: AES-GCM-SIV AEAD with 12-byte counter nonce.
7
+ import { sivAeadEncrypt, sivAeadDecrypt } from './ops.js';
8
+ import { AuthenticationError } from '../errors.js';
9
+ let x;
10
+ let derivedKey;
11
+ /**
12
+ * Message handler for the AES pool worker.
13
+ *
14
+ * Accepts three message types:
15
+ * - `'init'` , instantiate the aes WASM module and store the derived AES key
16
+ * - `'wipe'` , zero key and WASM buffers, then post `{ type: 'wiped' }`
17
+ * - `{ op: 'seal' | 'open', ... }`, encrypt or decrypt one chunk
18
+ *
19
+ * Replies with `{ type: 'result', id, data }` on success or
20
+ * `{ type: 'error', id, message, isAuthError }` on failure.
21
+ */
22
+ self.onmessage = async (e) => {
23
+ const msg = e.data;
24
+ if (msg.type === 'init') {
25
+ try {
26
+ // AES module is 4 pages = 256 KiB; matches src/asm/aes/buffers.ts.
27
+ const mem = new WebAssembly.Memory({ initial: 4, maximum: 4 });
28
+ const mod = msg.modules.aes;
29
+ const inst = await WebAssembly.instantiate(mod, { env: { memory: mem } });
30
+ x = inst.exports;
31
+ derivedKey = new Uint8Array(msg.derivedKeyBytes);
32
+ if (derivedKey.length !== 32)
33
+ throw new Error(`expected 32 derived key bytes (got ${derivedKey.length})`);
34
+ msg.derivedKeyBytes.fill(0);
35
+ self.postMessage({ type: 'ready' });
36
+ }
37
+ catch (err) {
38
+ if (msg.derivedKeyBytes)
39
+ msg.derivedKeyBytes.fill(0);
40
+ self.postMessage({ type: 'error', id: -1, message: err.message, isAuthError: false });
41
+ }
42
+ return;
43
+ }
44
+ if (msg.type === 'wipe') {
45
+ if (derivedKey)
46
+ derivedKey.fill(0);
47
+ derivedKey = undefined;
48
+ if (x)
49
+ x.wipeBuffers();
50
+ x = undefined;
51
+ self.postMessage({ type: 'wiped' });
52
+ return;
53
+ }
54
+ if (!x || !derivedKey) {
55
+ self.postMessage({ type: 'error', id: msg.id, message: 'worker not initialized', isAuthError: false });
56
+ return;
57
+ }
58
+ try {
59
+ const { id, op, counterNonce, data, aad } = msg;
60
+ const aadBytes = aad ?? new Uint8Array(0);
61
+ const jobKey = msg.derivedKeyBytes ?? derivedKey;
62
+ let result;
63
+ if (op === 'seal') {
64
+ const { ciphertext, tag } = sivAeadEncrypt(x, jobKey, counterNonce, data, aadBytes);
65
+ result = new Uint8Array(ciphertext.length + 16);
66
+ result.set(ciphertext);
67
+ result.set(tag, ciphertext.length);
68
+ }
69
+ else {
70
+ const ct = data.subarray(0, data.length - 16);
71
+ const tag = data.subarray(data.length - 16);
72
+ result = sivAeadDecrypt(x, jobKey, counterNonce, ct, tag, aadBytes, 'aes-gcm-siv');
73
+ }
74
+ const transfer = result.buffer instanceof ArrayBuffer ? [result.buffer] : [];
75
+ self.postMessage({ type: 'result', id, data: result }, { transfer });
76
+ }
77
+ catch (err) {
78
+ const isAuth = err instanceof AuthenticationError;
79
+ self.postMessage({
80
+ type: 'error', id: msg.id,
81
+ message: err.message,
82
+ cipher: isAuth ? 'aes-gcm-siv' : undefined,
83
+ isAuthError: isAuth,
84
+ });
85
+ }
86
+ finally {
87
+ if (msg.derivedKeyBytes)
88
+ msg.derivedKeyBytes.fill(0);
89
+ if (x)
90
+ x.wipeBuffers();
91
+ }
92
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,23 @@
1
+ // ▄▄▄▄▄▄▄▄▄▄
2
+ // ▄████████████████████▄▄ ▒ ▄▀▀ ▒ ▒ █ ▄▀▄ ▀█▀ █ ▒ ▄▀▄ █▀▄
3
+ // ▄██████████████████████ ▀████▄ ▓ ▓▀ ▓ ▓ ▓ ▓▄▓ ▓ ▓▀▓ ▓▄▓ ▓ ▓
4
+ // ▄█████████▀▀▀ ▀███████▄▄███████▌ ▀▄ ▀▄▄ ▀▄▀ ▒ ▒ ▒ ▒ ▒ █ ▒ ▒ ▒ █
5
+ // ▐████████▀ ▄▄▄▄ ▀████████▀██▀█▌
6
+ // ████████ ███▀▀ ████▀ █▀ █▀ Leviathan Crypto Library
7
+ // ███████▌ ▀██▀ ███
8
+ // ███████ ▀███ ▀██ ▀█▄ Repository & Mirror:
9
+ // ▀██████ ▄▄██ ▀▀ ██▄ github.com/xero/leviathan-crypto
10
+ // ▀█████▄ ▄██▄ ▄▀▄▀ unpkg.com/leviathan-crypto
11
+ // ▀████▄ ▄██▄
12
+ // ▐████ ▐███ Author: xero (https://x-e.ro)
13
+ // ▄▄██████████ ▐███ ▄▄ License: MIT
14
+ // ▄██▀▀▀▀▀▀▀▀▀▀ ▄████ ▄██▀
15
+ // ▄▀ ▄▄█████████▄▄ ▀▀▀▀▀ ▄███ This file is provided completely
16
+ // ▄██████▀▀▀▀▀▀██████▄ ▀▄▄▄▄████▀ free, "as is", and without
17
+ // ████▀ ▄▄▄▄▄▄▄ ▀████▄ ▀█████▀ ▄▄▄▄ warranty of any kind. The author
18
+ // █████▄▄█████▀▀▀▀▀▀▄ ▀███▄ ▄████ assumes absolutely no liability
19
+ // ▀██████▀ ▀████▄▄▄████▀ for its {ab,mis,}use.
20
+ // ▀█████▀▀
21
+ //
22
+ // src/ts/aes/types.ts
23
+ export {};
package/dist/aes.wasm ADDED
Binary file
@@ -0,0 +1 @@
1
+ export { WASM_GZ_BASE64 as blake3Wasm } from '../embedded/blake3.js';
@@ -0,0 +1,26 @@
1
+ // ▄▄▄▄▄▄▄▄▄▄
2
+ // ▄████████████████████▄▄ ▒ ▄▀▀ ▒ ▒ █ ▄▀▄ ▀█▀ █ ▒ ▄▀▄ █▀▄
3
+ // ▄██████████████████████ ▀████▄ ▓ ▓▀ ▓ ▓ ▓ ▓▄▓ ▓ ▓▀▓ ▓▄▓ ▓ ▓
4
+ // ▄█████████▀▀▀ ▀███████▄▄███████▌ ▀▄ ▀▄▄ ▀▄▀ ▒ ▒ ▒ ▒ ▒ █ ▒ ▒ ▒ █
5
+ // ▐████████▀ ▄▄▄▄ ▀████████▀██▀█▌
6
+ // ████████ ███▀▀ ████▀ █▀ █▀ Leviathan Crypto Library
7
+ // ███████▌ ▀██▀ ███
8
+ // ███████ ▀███ ▀██ ▀█▄ Repository & Mirror:
9
+ // ▀██████ ▄▄██ ▀▀ ██▄ github.com/xero/leviathan-crypto
10
+ // ▀█████▄ ▄██▄ ▄▀▄▀ unpkg.com/leviathan-crypto
11
+ // ▀████▄ ▄██▄
12
+ // ▐████ ▐███ Author: xero (https://x-e.ro)
13
+ // ▄▄██████████ ▐███ ▄▄ License: MIT
14
+ // ▄██▀▀▀▀▀▀▀▀▀▀ ▄████ ▄██▀
15
+ // ▄▀ ▄▄█████████▄▄ ▀▀▀▀▀ ▄███ This file is provided completely
16
+ // ▄██████▀▀▀▀▀▀██████▄ ▀▄▄▄▄████▀ free, "as is", and without
17
+ // ████▀ ▄▄▄▄▄▄▄ ▀████▄ ▀█████▀ ▄▄▄▄ warranty of any kind. The author
18
+ // █████▄▄█████▀▀▀▀▀▀▄ ▀███▄ ▄████ assumes absolutely no liability
19
+ // ▀██████▀ ▀████▄▄▄████▀ for its {ab,mis,}use.
20
+ // ▀█████▀▀
21
+ //
22
+ // src/ts/blake3/embedded.ts
23
+ //
24
+ // Exports the gzip+base64 blake3 WASM blob for use as a WasmSource.
25
+ // Import via `leviathan-crypto/blake3/embedded`.
26
+ export { WASM_GZ_BASE64 as blake3Wasm } from '../embedded/blake3.js';
@@ -0,0 +1,143 @@
1
+ import { isInitialized } from '../init.js';
2
+ import type { WasmSource } from '../wasm-source.js';
3
+ import type { HashFn } from '../types.js';
4
+ import type { Blake3Exports } from './types.js';
5
+ export type { WasmSource };
6
+ export type { Blake3Exports };
7
+ export { isInitialized };
8
+ export declare function blake3Init(source: WasmSource): Promise<void>;
9
+ /**
10
+ * BLAKE3 default-mode hash (BLAKE3 §2.3 Modes — `hash`).
11
+ *
12
+ * One-shot: `hash(msg, outLen?)` runs the full chunk / tree / root
13
+ * pipeline and returns `outLen` (default 32) bytes of XOF output.
14
+ * Module exclusivity is acquired and released per call.
15
+ */
16
+ export declare class BLAKE3 {
17
+ private readonly x;
18
+ constructor();
19
+ hash(msg: Uint8Array, outLen?: number): Uint8Array;
20
+ dispose(): void;
21
+ }
22
+ /**
23
+ * BLAKE3 keyed_hash (BLAKE3 §2.3 Modes — `keyed_hash`).
24
+ *
25
+ * The 32-byte key seeds the chunk machine in place of the BLAKE3 IV and
26
+ * every compress carries the KEYED_HASH flag. Use cases include MACs and
27
+ * keyed-pseudorandom generation; the construction is a PRF when the key
28
+ * is uniform and secret.
29
+ */
30
+ export declare class BLAKE3KeyedHash {
31
+ private readonly x;
32
+ constructor();
33
+ hash(key: Uint8Array, msg: Uint8Array, outLen?: number): Uint8Array;
34
+ dispose(): void;
35
+ }
36
+ /**
37
+ * BLAKE3 derive_key (BLAKE3 §2.3 Modes — `derive_key`).
38
+ *
39
+ * Two-pass KDF: pass 1 hashes the context string with the
40
+ * DERIVE_KEY_CONTEXT flag, pass 2 hashes the key material with the
41
+ * DERIVE_KEY_MATERIAL flag using the pass-1 output as its starting CV.
42
+ * Context strings are conventionally hardcoded UTF-8 application
43
+ * constants; empty contexts are rejected by `validateContext`.
44
+ */
45
+ export declare class BLAKE3DeriveKey {
46
+ private readonly x;
47
+ constructor();
48
+ derive(context: string | Uint8Array, material: Uint8Array, outLen?: number): Uint8Array;
49
+ dispose(): void;
50
+ }
51
+ /**
52
+ * Streaming BLAKE3 default-mode hash (BLAKE3 §2.3 Modes — `hash`).
53
+ *
54
+ * `update()` accepts chunks of any size; `finalize()` returns the
55
+ * `outLen`-byte (default 32) digest and disposes the instance. Holds
56
+ * exclusive access to the `blake3` WASM module from construction until
57
+ * `dispose()` or `finalize()` / `finalizeXof()`.
58
+ */
59
+ export declare class BLAKE3Stream {
60
+ private readonly x;
61
+ private _tok;
62
+ private readonly _state;
63
+ constructor();
64
+ update(chunk: Uint8Array): this;
65
+ finalize(outLen?: number): Uint8Array;
66
+ finalizeXof(): BLAKE3OutputReader;
67
+ dispose(): void;
68
+ private _checkLive;
69
+ }
70
+ /**
71
+ * Streaming BLAKE3 keyed_hash (BLAKE3 §2.3 Modes). Key is bound at construction
72
+ * time. Same lifecycle as `BLAKE3Stream`.
73
+ */
74
+ export declare class BLAKE3KeyedHashStream {
75
+ private readonly x;
76
+ private _tok;
77
+ private readonly _state;
78
+ private readonly _key;
79
+ constructor(key: Uint8Array);
80
+ update(chunk: Uint8Array): this;
81
+ finalize(outLen?: number): Uint8Array;
82
+ finalizeXof(): BLAKE3OutputReader;
83
+ dispose(): void;
84
+ private _checkLive;
85
+ }
86
+ /**
87
+ * Streaming BLAKE3 derive_key (BLAKE3 §2.3 Modes). Context is bound at
88
+ * construction time; updates stream the material; finalize derives.
89
+ * Same lifecycle as `BLAKE3Stream`.
90
+ */
91
+ export declare class BLAKE3DeriveKeyStream {
92
+ private readonly x;
93
+ private _tok;
94
+ private readonly _state;
95
+ private readonly _ctxBytes;
96
+ constructor(context: string | Uint8Array);
97
+ update(chunk: Uint8Array): this;
98
+ finalize(outLen?: number): Uint8Array;
99
+ finalizeXof(): BLAKE3OutputReader;
100
+ dispose(): void;
101
+ private _checkLive;
102
+ }
103
+ /**
104
+ * BLAKE3 XOF reader (BLAKE3 §2.6 Extendable Output).
105
+ *
106
+ * Sequential `read(nBytes)` calls squeeze the next bytes of XOF output.
107
+ * Constructed via `finalizeXof()` on a streaming class. Holds module
108
+ * exclusivity until `dispose()`.
109
+ *
110
+ * Implementation: the first `read()` runs the underlying hash entry once
111
+ * to populate the WASM-side root-compress snapshot (ROOT_STATE_*), then
112
+ * caches the first 64-byte XOF block. Subsequent reads pump
113
+ * `squeezeXofBlock` on the WASM module with an incrementing counter to
114
+ * lift additional 64-byte blocks off the snapshot. The reader's lifetime
115
+ * coincides with its hold on the module token, so `ROOT_STATE_*` stays
116
+ * intact between read calls (no other consumer can fire a hash that
117
+ * would clobber it).
118
+ */
119
+ export declare class BLAKE3OutputReader {
120
+ private readonly x;
121
+ private _tok;
122
+ private readonly _mode;
123
+ private readonly _input;
124
+ private readonly _key;
125
+ private readonly _ctx;
126
+ private readonly _blockBuf;
127
+ private _blockPos;
128
+ private _nextCounter;
129
+ private _populated;
130
+ read(nBytes: number): Uint8Array;
131
+ dispose(): void;
132
+ private _populate;
133
+ private _squeezeNextBlock;
134
+ }
135
+ /**
136
+ * Stateless BLAKE3-256 HashFn. Shape mirrors `SHA256Hash` in
137
+ * `src/ts/sha2/hash.ts`: 32-byte output, single WASM module dependency,
138
+ * `digest(msg)` runs a one-shot hash with default `outLen`.
139
+ *
140
+ * Usable as a Fortuna accumulator / reseed hash when paired with a
141
+ * matching 32-byte-key Generator.
142
+ */
143
+ export declare const BLAKE3Hash: HashFn;