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
@@ -3,10 +3,10 @@
3
3
  //
4
4
  // Worker for SealStreamPool with SerpentCipher.
5
5
  // Holds 3 derived keys (enc/mac/iv) and raw WASM instances.
6
- // Direct WASM calls no initModule (avoids same-thread module cache conflicts
6
+ // Direct WASM calls, no initModule (avoids same-thread module cache conflicts
7
7
  // in @vitest/web-worker test environment).
8
8
  //
9
- // All HMAC / CBC / PKCS7 primitives come from `./shared-ops.js` the same
9
+ // All HMAC / CBC / PKCS7 primitives come from `./shared-ops.js`, the same
10
10
  // module the main-thread `SerpentCipher` uses. Byte-identical output with
11
11
  // the main thread is the regression guard (see
12
12
  // test/unit/stream/pool-byte-exact.test.ts). Must NOT import from `../init.js`:
@@ -21,9 +21,9 @@ let keys;
21
21
  * Message handler for the Serpent pool worker.
22
22
  *
23
23
  * Accepts three message types:
24
- * - `'init'` instantiate sha2 + serpent WASM modules and store derived keys
25
- * - `'wipe'` zero keys and WASM buffers, then post `{ type: 'wiped' }`
26
- * - `{ op: 'seal' | 'open', ... }` encrypt or decrypt one chunk
24
+ * - `'init'` , instantiate sha2 + serpent WASM modules and store derived keys
25
+ * - `'wipe'` , zero keys and WASM buffers, then post `{ type: 'wiped' }`
26
+ * - `{ op: 'seal' | 'open', ... }`, encrypt or decrypt one chunk
27
27
  *
28
28
  * Replies with `{ type: 'result', id, data }` on success or
29
29
  * `{ type: 'error', id, message, isAuthError }` on failure.
@@ -45,6 +45,8 @@ self.onmessage = async (e) => {
45
45
  self.postMessage({ type: 'ready' });
46
46
  }
47
47
  catch (err) {
48
+ if (msg.derivedKeyBytes)
49
+ msg.derivedKeyBytes.fill(0);
48
50
  self.postMessage({ type: 'error', id: -1, message: err.message, isAuthError: false });
49
51
  }
50
52
  return;
@@ -19,16 +19,16 @@ export declare class SerpentCbc {
19
19
  * Encrypt plaintext with Serpent-256 CBC + PKCS7 padding.
20
20
  *
21
21
  * @param key 16, 24, or 32 bytes
22
- * @param iv 16 bytes must be random and unique per (key, message)
23
- * @param plaintext any length PKCS7 padding applied automatically
22
+ * @param iv 16 bytes, must be random and unique per (key, message)
23
+ * @param plaintext any length, PKCS7 padding applied automatically
24
24
  * @returns ciphertext (length = ceil((plaintext.length + 1) / 16) * 16)
25
25
  */
26
26
  encrypt(key: Uint8Array, iv: Uint8Array, plaintext: Uint8Array): Uint8Array;
27
27
  /**
28
28
  * Decrypt Serpent-256 CBC + PKCS7.
29
29
  *
30
- * All failure modes empty input, non-multiple-of-16 length, and any
31
- * PKCS7 validation failure throw the same generic `RangeError` with
30
+ * All failure modes, empty input, non-multiple-of-16 length, and any
31
+ * PKCS7 validation failure, throw the same generic `RangeError` with
32
32
  * message `'invalid ciphertext'`. Padding validation runs branch-free
33
33
  * over the last 16 bytes regardless of where the mismatch is, closing
34
34
  * the Vaudenay 2002 padding-oracle surface for callers using
@@ -21,7 +21,7 @@
21
21
  //
22
22
  // src/ts/serpent/serpent-cbc.ts
23
23
  //
24
- // SerpentCbc Serpent-256 CBC + PKCS7, internal module.
24
+ // SerpentCbc, Serpent-256 CBC + PKCS7, internal module.
25
25
  // Extracted to break the cipher-suite.ts ↔ index.ts circular dependency.
26
26
  // Import from here directly; index.ts re-exports for the public API surface.
27
27
  import { getInstance, _acquireModule, _releaseModule } from '../init.js';
@@ -53,13 +53,13 @@ export class SerpentCbc {
53
53
  _tok;
54
54
  constructor(opts) {
55
55
  if (!opts?.dangerUnauthenticated) {
56
- throw new Error('leviathan-crypto: SerpentCbc is unauthenticated use Seal with SerpentCipher instead. ' +
56
+ throw new Error('leviathan-crypto: SerpentCbc is unauthenticated, use Seal with SerpentCipher instead. ' +
57
57
  'To use SerpentCbc directly, pass { dangerUnauthenticated: true }.');
58
58
  }
59
59
  this.x = getExports();
60
60
  this._tok = _acquireModule('serpent');
61
61
  }
62
- /** View over WASM linear memory. Rebind on every access memory can be detached after grow. @internal */
62
+ /** View over WASM linear memory. Rebind on every access, memory can be detached after grow. @internal */
63
63
  get mem() {
64
64
  return new Uint8Array(this.x.memory.buffer);
65
65
  }
@@ -67,8 +67,8 @@ export class SerpentCbc {
67
67
  * Encrypt plaintext with Serpent-256 CBC + PKCS7 padding.
68
68
  *
69
69
  * @param key 16, 24, or 32 bytes
70
- * @param iv 16 bytes must be random and unique per (key, message)
71
- * @param plaintext any length PKCS7 padding applied automatically
70
+ * @param iv 16 bytes, must be random and unique per (key, message)
71
+ * @param plaintext any length, PKCS7 padding applied automatically
72
72
  * @returns ciphertext (length = ceil((plaintext.length + 1) / 16) * 16)
73
73
  */
74
74
  encrypt(key, iv, plaintext) {
@@ -95,8 +95,8 @@ export class SerpentCbc {
95
95
  /**
96
96
  * Decrypt Serpent-256 CBC + PKCS7.
97
97
  *
98
- * All failure modes empty input, non-multiple-of-16 length, and any
99
- * PKCS7 validation failure throw the same generic `RangeError` with
98
+ * All failure modes, empty input, non-multiple-of-16 length, and any
99
+ * PKCS7 validation failure, throw the same generic `RangeError` with
100
100
  * message `'invalid ciphertext'`. Padding validation runs branch-free
101
101
  * over the last 16 bytes regardless of where the mismatch is, closing
102
102
  * the Vaudenay 2002 padding-oracle surface for callers using
@@ -145,7 +145,10 @@ export class SerpentCbc {
145
145
  if (key.length !== 16 && key.length !== 24 && key.length !== 32)
146
146
  throw new RangeError(`Serpent key must be 16, 24, or 32 bytes (got ${key.length})`);
147
147
  this.mem.set(key, this.x.getKeyOffset());
148
- this.x.loadKey(key.length);
148
+ if (this.x.loadKey(key.length) !== 0) {
149
+ this.x.wipeBuffers();
150
+ throw new Error('SerpentCbc: loadKey failed');
151
+ }
149
152
  }
150
153
  /**
151
154
  * Write `iv` into the WASM CBC IV buffer.
@@ -1,3 +1,4 @@
1
+ export { pkcs7Pad, pkcs7Strip, PKCS7_INVALID } from '../shared/pkcs7.js';
1
2
  /** Subset of the sha2 WASM exports used by `hmacSha256`. */
2
3
  export interface Sha2OpsExports {
3
4
  memory: WebAssembly.Memory;
@@ -21,35 +22,14 @@ export interface SerpentOpsExports {
21
22
  loadKey: (n: number) => number;
22
23
  cbcEncryptChunk: (n: number) => number;
23
24
  cbcDecryptChunk_simd: (n: number) => number;
25
+ wipeBuffers: () => void;
24
26
  }
25
- export declare const PKCS7_INVALID = "invalid ciphertext";
26
- /**
27
- * Apply PKCS7 padding to `data` so the result length is a multiple of 16.
28
- * Padding length is always 1–16 bytes so a full pad block is appended when
29
- * `data.length` is already block-aligned.
30
- * @param data Input bytes of any length
31
- * @returns New Uint8Array padded to the next 16-byte boundary
32
- */
33
- export declare function pkcs7Pad(data: Uint8Array): Uint8Array;
34
- /**
35
- * Remove PKCS7 padding from a block-aligned buffer in constant time.
36
- *
37
- * Branch-free over all secret bits — padding length and per-byte comparisons
38
- * are accumulated into a single `bad` flag with no early exit. Closes the
39
- * Vaudenay 2002 padding-oracle surface. Throws a single generic
40
- * `RangeError('invalid ciphertext')` for every failure mode: empty input,
41
- * non-block-aligned length, padding byte out of range 1–16, and any per-byte
42
- * mismatch in the padding region.
43
- * @param data Block-aligned ciphertext (length must be a multiple of 16)
44
- * @returns Plaintext with padding removed
45
- */
46
- export declare function pkcs7Strip(data: Uint8Array): Uint8Array;
47
27
  /**
48
28
  * Compute HMAC-SHA-256 using raw WASM sha2 exports.
49
29
  *
50
30
  * Keys longer than 64 bytes are pre-hashed per RFC 2104 §3. The SHA-256
51
31
  * input buffer is fed in 64-byte chunks to match the WASM block size.
52
- * Does not call `_acquireModule` callers must ensure no stateful instance
32
+ * Does not call `_acquireModule`, callers must ensure no stateful instance
53
33
  * owns the sha2 module before calling.
54
34
  * @param sx sha2 WASM exports
55
35
  * @param key HMAC key of any length
@@ -23,8 +23,8 @@
23
23
  //
24
24
  // Pure-function primitives shared between the main-thread `SerpentCipher`
25
25
  // (cipher-suite.ts) and the `SealStreamPool` worker (pool-worker.ts). Both
26
- // call sites hold their own WASM exports pool workers instantiate modules
27
- // locally, the main thread fetches via `getInstance()` so every function
26
+ // call sites hold their own WASM exports, pool workers instantiate modules
27
+ // locally, the main thread fetches via `getInstance()`, so every function
28
28
  // here takes the sha2/serpent exports as parameters. No dependency on
29
29
  // `init.ts`, no module-level state, no instance wrappers.
30
30
  //
@@ -32,74 +32,19 @@
32
32
  // payload into chunks ≤ WASM CHUNK_SIZE. For multi-chunk use, see
33
33
  // `SerpentCbc.encrypt`/`decrypt`, which loop over the same WASM exports.
34
34
  //
35
- // This file owns the canonical `pkcs7Pad` / `pkcs7Strip`; `serpent-cbc.ts`
36
- // re-exports them. A single source of truth keeps the branch-free,
37
- // Vaudenay-2002-closed padding check identical on the main-thread and
38
- // pool-worker paths divergence between the two would reintroduce an
39
- // oracle.
40
- // ── PKCS7 ───────────────────────────────────────────────────────────────────
41
- // Generic error string used by every failure mode of `pkcs7Strip` and the
42
- // length/alignment gate in `SerpentCbc.decrypt`. No numeric leaks, no
43
- // structural disclosure — a caller cannot distinguish "bad length" from
44
- // "bad padding" by message or by timing.
45
- export const PKCS7_INVALID = 'invalid ciphertext';
46
- /**
47
- * Apply PKCS7 padding to `data` so the result length is a multiple of 16.
48
- * Padding length is always 1–16 bytes so a full pad block is appended when
49
- * `data.length` is already block-aligned.
50
- * @param data Input bytes of any length
51
- * @returns New Uint8Array padded to the next 16-byte boundary
52
- */
53
- export function pkcs7Pad(data) {
54
- const padLen = 16 - (data.length % 16); // 1..16
55
- const out = new Uint8Array(data.length + padLen);
56
- out.set(data);
57
- out.fill(padLen, data.length);
58
- return out;
59
- }
60
- /**
61
- * Remove PKCS7 padding from a block-aligned buffer in constant time.
62
- *
63
- * Branch-free over all secret bits — padding length and per-byte comparisons
64
- * are accumulated into a single `bad` flag with no early exit. Closes the
65
- * Vaudenay 2002 padding-oracle surface. Throws a single generic
66
- * `RangeError('invalid ciphertext')` for every failure mode: empty input,
67
- * non-block-aligned length, padding byte out of range 1–16, and any per-byte
68
- * mismatch in the padding region.
69
- * @param data Block-aligned ciphertext (length must be a multiple of 16)
70
- * @returns Plaintext with padding removed
71
- */
72
- export function pkcs7Strip(data) {
73
- if (data.length === 0 || data.length % 16 !== 0)
74
- throw new RangeError(PKCS7_INVALID);
75
- const padLen = data[data.length - 1];
76
- let bad = 0;
77
- bad |= ((padLen - 1) >>> 31); // 1 if padLen == 0
78
- bad |= ((16 - padLen) >>> 31); // 1 if padLen > 16
79
- // Per-byte pad-region mask without branches on secret bits.
80
- // inPadRegion = 0xff when i >= 16 - padLen
81
- // = 0x00 otherwise
82
- //
83
- // (16 - padLen - i - 1) is negative iff i >= 16 - padLen. A signed
84
- // arithmetic shift by 31 yields -1 for negative, 0 for non-negative;
85
- // ANDing with 0xff collapses those to 0xff and 0x00.
86
- for (let i = 0; i < 16; i++) {
87
- const idx = data.length - 16 + i;
88
- const mask = ((16 - padLen - i - 1) >> 31) & 0xff;
89
- bad |= (data[idx] ^ padLen) & mask;
90
- }
91
- const invalid = ((bad - 1) >>> 31) ^ 1;
92
- if (invalid)
93
- throw new RangeError(PKCS7_INVALID);
94
- return data.subarray(0, data.length - padLen);
95
- }
35
+ // `pkcs7Pad` / `pkcs7Strip` / `PKCS7_INVALID` live in `../shared/pkcs7.js`
36
+ // and are re-exported here so existing serpent-side imports keep working.
37
+ // A single source of truth keeps the branch-free, Vaudenay-2002-closed
38
+ // padding check identical across all CBC paths.
39
+ export { pkcs7Pad, pkcs7Strip, PKCS7_INVALID } from '../shared/pkcs7.js';
40
+ import { pkcs7Pad, pkcs7Strip, PKCS7_INVALID } from '../shared/pkcs7.js';
96
41
  // ── HMAC-SHA-256 ────────────────────────────────────────────────────────────
97
42
  /**
98
43
  * Compute HMAC-SHA-256 using raw WASM sha2 exports.
99
44
  *
100
45
  * Keys longer than 64 bytes are pre-hashed per RFC 2104 §3. The SHA-256
101
46
  * input buffer is fed in 64-byte chunks to match the WASM block size.
102
- * Does not call `_acquireModule` callers must ensure no stateful instance
47
+ * Does not call `_acquireModule`, callers must ensure no stateful instance
103
48
  * owns the sha2 module before calling.
104
49
  * @param sx sha2 WASM exports
105
50
  * @param key HMAC key of any length
@@ -157,16 +102,24 @@ function feedMemory(memory, inputOff, msg, chunkSize, update) {
157
102
  */
158
103
  export function cbcEncryptChunk(kx, key, iv, chunk) {
159
104
  loadKeyAndIv(kx, key, iv);
160
- const padded = pkcs7Pad(chunk);
161
- const ptOff = kx.getChunkPtOffset();
162
- const ctOff = kx.getChunkCtOffset();
163
- const mem = new Uint8Array(kx.memory.buffer);
164
- mem.set(padded, ptOff);
165
- const ret = kx.cbcEncryptChunk(padded.length);
166
- if (ret < 0)
167
- throw new RangeError(`cbcEncryptChunk rejected len=${padded.length}` +
168
- ` (WASM CHUNK_SIZE=${kx.getChunkSize()})`);
169
- return new Uint8Array(kx.memory.buffer).slice(ctOff, ctOff + padded.length);
105
+ try {
106
+ const padded = pkcs7Pad(chunk);
107
+ const ptOff = kx.getChunkPtOffset();
108
+ const ctOff = kx.getChunkCtOffset();
109
+ const mem = new Uint8Array(kx.memory.buffer);
110
+ mem.set(padded, ptOff);
111
+ const ret = kx.cbcEncryptChunk(padded.length);
112
+ if (ret < 0)
113
+ throw new RangeError(`cbcEncryptChunk rejected len=${padded.length}` +
114
+ ` (WASM CHUNK_SIZE=${kx.getChunkSize()})`);
115
+ return new Uint8Array(kx.memory.buffer).slice(ctOff, ctOff + padded.length);
116
+ }
117
+ catch (err) {
118
+ // Length-error or any other throw past loadKeyAndIv leaves key+iv staged.
119
+ // Wipe before re-throwing, the cipher-suite caller may not call dispose.
120
+ kx.wipeBuffers();
121
+ throw err;
122
+ }
170
123
  }
171
124
  /**
172
125
  * Decrypt one Serpent-256 CBC chunk using the SIMD path and strip PKCS7 padding.
@@ -183,16 +136,25 @@ export function cbcDecryptChunk(kx, key, iv, ct) {
183
136
  if (ct.length === 0 || ct.length % 16 !== 0)
184
137
  throw new RangeError(PKCS7_INVALID);
185
138
  loadKeyAndIv(kx, key, iv);
186
- const ctOff = kx.getChunkCtOffset();
187
- const ptOff = kx.getChunkPtOffset();
188
- const mem = new Uint8Array(kx.memory.buffer);
189
- mem.set(ct, ctOff);
190
- const ret = kx.cbcDecryptChunk_simd(ct.length);
191
- if (ret < 0)
192
- throw new RangeError(`cbcDecryptChunk_simd rejected len=${ct.length}` +
193
- ` (WASM CHUNK_SIZE=${kx.getChunkSize()})`);
194
- const raw = new Uint8Array(kx.memory.buffer).slice(ptOff, ptOff + ct.length);
195
- return pkcs7Strip(raw);
139
+ try {
140
+ const ctOff = kx.getChunkCtOffset();
141
+ const ptOff = kx.getChunkPtOffset();
142
+ const mem = new Uint8Array(kx.memory.buffer);
143
+ mem.set(ct, ctOff);
144
+ const ret = kx.cbcDecryptChunk_simd(ct.length);
145
+ if (ret < 0)
146
+ throw new RangeError(`cbcDecryptChunk_simd rejected len=${ct.length}` +
147
+ ` (WASM CHUNK_SIZE=${kx.getChunkSize()})`);
148
+ const raw = new Uint8Array(kx.memory.buffer).slice(ptOff, ptOff + ct.length);
149
+ return pkcs7Strip(raw);
150
+ }
151
+ catch (err) {
152
+ // Length-error, padding mismatch, or any other throw past loadKeyAndIv
153
+ // leaves key+iv staged. Wipe before re-throwing, bad PKCS7 padding is
154
+ // a Vaudenay-attack signal; per-chunk staged key+iv must not survive it.
155
+ kx.wipeBuffers();
156
+ throw err;
157
+ }
196
158
  }
197
159
  /**
198
160
  * Validate, then write `key` and `iv` into the WASM buffers and expand the key schedule.
@@ -208,6 +170,9 @@ function loadKeyAndIv(kx, key, iv) {
208
170
  throw new RangeError(`CBC IV must be 16 bytes (got ${iv.length})`);
209
171
  const mem = new Uint8Array(kx.memory.buffer);
210
172
  mem.set(key, kx.getKeyOffset());
211
- kx.loadKey(key.length);
173
+ if (kx.loadKey(key.length) !== 0) {
174
+ kx.wipeBuffers();
175
+ throw new Error('Serpent shared-ops: loadKey failed');
176
+ }
212
177
  mem.set(iv, kx.getCbcIvOffset());
213
178
  }
package/dist/serpent.wasm CHANGED
Binary file
package/dist/sha2/hkdf.js CHANGED
@@ -21,7 +21,7 @@
21
21
  //
22
22
  // src/ts/sha2/hkdf.ts
23
23
  //
24
- // RFC 5869 HKDF (HMAC-based Extract-and-Expand Key Derivation Function)
24
+ // RFC 5869, HKDF (HMAC-based Extract-and-Expand Key Derivation Function)
25
25
  // Pure TS composition over HMAC_SHA256 and HMAC_SHA512.
26
26
  import { HMAC_SHA256, HMAC_SHA512 } from './index.js';
27
27
  // ── HKDF_SHA256 ─────────────────────────────────────────────────────────────
@@ -30,12 +30,12 @@ export class HKDF_SHA256 {
30
30
  constructor() {
31
31
  this.hmac = new HMAC_SHA256();
32
32
  }
33
- // RFC 5869 §2.2 Extract
33
+ // RFC 5869 §2.2, Extract
34
34
  extract(salt, ikm) {
35
35
  const s = (!salt || salt.length === 0) ? new Uint8Array(32) : salt;
36
36
  return this.hmac.hash(s, ikm);
37
37
  }
38
- // RFC 5869 §2.3 Expand
38
+ // RFC 5869 §2.3, Expand
39
39
  expand(prk, info, length) {
40
40
  if (prk.length !== 32)
41
41
  throw new RangeError('HKDF expand: PRK must be 32 bytes');
@@ -79,12 +79,12 @@ export class HKDF_SHA512 {
79
79
  constructor() {
80
80
  this.hmac = new HMAC_SHA512();
81
81
  }
82
- // RFC 5869 §2.2 Extract
82
+ // RFC 5869 §2.2, Extract
83
83
  extract(salt, ikm) {
84
84
  const s = (!salt || salt.length === 0) ? new Uint8Array(64) : salt;
85
85
  return this.hmac.hash(s, ikm);
86
86
  }
87
- // RFC 5869 §2.3 Expand
87
+ // RFC 5869 §2.3, Expand
88
88
  expand(prk, info, length) {
89
89
  if (prk.length !== 64)
90
90
  throw new RangeError('HKDF expand: PRK must be 64 bytes');
@@ -1,7 +1,9 @@
1
1
  import type { WasmSource } from '../wasm-source.js';
2
+ import type { Sha2Exports } from './types.js';
2
3
  export declare function sha2Init(source: WasmSource): Promise<void>;
3
4
  export type { WasmSource };
4
- export declare function _sha2Ready(): boolean;
5
+ export type { Sha2Exports };
6
+ export { isInitialized } from '../init.js';
5
7
  export declare class SHA256 {
6
8
  private readonly x;
7
9
  constructor();
@@ -20,6 +22,24 @@ export declare class SHA384 {
20
22
  hash(msg: Uint8Array): Uint8Array;
21
23
  dispose(): void;
22
24
  }
25
+ export declare class SHA224 {
26
+ private readonly x;
27
+ constructor();
28
+ hash(msg: Uint8Array): Uint8Array;
29
+ dispose(): void;
30
+ }
31
+ export declare class SHA512_224 {
32
+ private readonly x;
33
+ constructor();
34
+ hash(msg: Uint8Array): Uint8Array;
35
+ dispose(): void;
36
+ }
37
+ export declare class SHA512_256 {
38
+ private readonly x;
39
+ constructor();
40
+ hash(msg: Uint8Array): Uint8Array;
41
+ dispose(): void;
42
+ }
23
43
  export declare class HMAC_SHA256 {
24
44
  private readonly x;
25
45
  constructor();
@@ -22,23 +22,15 @@
22
22
  // src/ts/sha2/index.ts
23
23
  //
24
24
  // Public API classes for the SHA-2 WASM module.
25
- // Uses the init() module cache call sha2Init(source) before constructing.
25
+ // Uses the init() module cache, call sha2Init(source) before constructing.
26
26
  import { getInstance, initModule, _assertNotOwned } from '../init.js';
27
27
  export async function sha2Init(source) {
28
28
  return initModule('sha2', source);
29
29
  }
30
+ export { isInitialized } from '../init.js';
30
31
  function getExports() {
31
32
  return getInstance('sha2').exports;
32
33
  }
33
- export function _sha2Ready() {
34
- try {
35
- getInstance('sha2');
36
- return true;
37
- }
38
- catch {
39
- return false;
40
- }
41
- }
42
34
  // Write msg into input buffer in chunks, calling update for each chunk.
43
35
  function feedHash(x, msg, inputOff, chunkSize, updateFn) {
44
36
  const mem = new Uint8Array(x.memory.buffer);
@@ -107,6 +99,69 @@ export class SHA384 {
107
99
  this.x.wipeBuffers();
108
100
  }
109
101
  }
102
+ // ── SHA224 ──────────────────────────────────────────────────────────────────
103
+ // FIPS 180-4 §6.3, SHA-256 round logic with the §5.3.2 IV; output is the
104
+ // leftmost 224 bits (28 bytes) of the SHA-256 state.
105
+ export class SHA224 {
106
+ x;
107
+ constructor() {
108
+ this.x = getExports();
109
+ }
110
+ hash(msg) {
111
+ _assertNotOwned('sha2');
112
+ this.x.sha224Init();
113
+ feedHash(this.x, msg, this.x.getSha256InputOffset(), 64, this.x.sha256Update);
114
+ this.x.sha224Final();
115
+ const mem = new Uint8Array(this.x.memory.buffer);
116
+ return mem.slice(this.x.getSha256OutOffset(), this.x.getSha256OutOffset() + 28);
117
+ }
118
+ dispose() {
119
+ _assertNotOwned('sha2');
120
+ this.x.wipeBuffers();
121
+ }
122
+ }
123
+ // ── SHA512_224 ──────────────────────────────────────────────────────────────
124
+ // FIPS 180-4 §6.7.1, SHA-512 round logic with the §5.3.6.1 IV; output is the
125
+ // leftmost 224 bits (28 bytes) of the SHA-512 state.
126
+ export class SHA512_224 {
127
+ x;
128
+ constructor() {
129
+ this.x = getExports();
130
+ }
131
+ hash(msg) {
132
+ _assertNotOwned('sha2');
133
+ this.x.sha512_224Init();
134
+ feedHash(this.x, msg, this.x.getSha512InputOffset(), 128, this.x.sha512Update);
135
+ this.x.sha512_224Final();
136
+ const mem = new Uint8Array(this.x.memory.buffer);
137
+ return mem.slice(this.x.getSha512OutOffset(), this.x.getSha512OutOffset() + 28);
138
+ }
139
+ dispose() {
140
+ _assertNotOwned('sha2');
141
+ this.x.wipeBuffers();
142
+ }
143
+ }
144
+ // ── SHA512_256 ──────────────────────────────────────────────────────────────
145
+ // FIPS 180-4 §6.7.2, SHA-512 round logic with the §5.3.6.2 IV; output is the
146
+ // leftmost 256 bits (32 bytes) of the SHA-512 state.
147
+ export class SHA512_256 {
148
+ x;
149
+ constructor() {
150
+ this.x = getExports();
151
+ }
152
+ hash(msg) {
153
+ _assertNotOwned('sha2');
154
+ this.x.sha512_256Init();
155
+ feedHash(this.x, msg, this.x.getSha512InputOffset(), 128, this.x.sha512Update);
156
+ this.x.sha512_256Final();
157
+ const mem = new Uint8Array(this.x.memory.buffer);
158
+ return mem.slice(this.x.getSha512OutOffset(), this.x.getSha512OutOffset() + 32);
159
+ }
160
+ dispose() {
161
+ _assertNotOwned('sha2');
162
+ this.x.wipeBuffers();
163
+ }
164
+ }
110
165
  // ── HMAC_SHA256 ─────────────────────────────────────────────────────────────
111
166
  export class HMAC_SHA256 {
112
167
  x;
@@ -1,5 +1,44 @@
1
- /** WASM exports for the sha2 module */
1
+ /** WASM exports for the sha2 module, full FIPS 180-4 surface plus
2
+ * HMAC variants. Importable from cross-module wrappers (e.g. mldsa's
3
+ * HashML-DSA pre-hash dispatcher) that need to drive sha2 directly
4
+ * without going through the public class API. */
2
5
  export interface Sha2Exports {
3
6
  memory: WebAssembly.Memory;
4
- getModuleId(): number;
7
+ getModuleId: () => number;
8
+ getSha256InputOffset: () => number;
9
+ getSha256OutOffset: () => number;
10
+ getSha256HOffset: () => number;
11
+ getSha512InputOffset: () => number;
12
+ getSha512OutOffset: () => number;
13
+ getSha512HOffset: () => number;
14
+ getHmac256IpadOffset: () => number;
15
+ getHmac256OpadOffset: () => number;
16
+ getHmac256InnerOffset: () => number;
17
+ getHmac512IpadOffset: () => number;
18
+ getHmac512OpadOffset: () => number;
19
+ getHmac512InnerOffset: () => number;
20
+ sha256Init: () => void;
21
+ sha256Update: (len: number) => void;
22
+ sha256Final: () => void;
23
+ sha224Init: () => void;
24
+ sha224Final: () => void;
25
+ sha512Init: () => void;
26
+ sha384Init: () => void;
27
+ sha512_224Init: () => void;
28
+ sha512_256Init: () => void;
29
+ sha512Update: (len: number) => void;
30
+ sha512Final: () => void;
31
+ sha384Final: () => void;
32
+ sha512_224Final: () => void;
33
+ sha512_256Final: () => void;
34
+ hmac256Init: (keyLen: number) => void;
35
+ hmac256Update: (len: number) => void;
36
+ hmac256Final: () => void;
37
+ hmac512Init: (keyLen: number) => void;
38
+ hmac512Update: (len: number) => void;
39
+ hmac512Final: () => void;
40
+ hmac384Init: (keyLen: number) => void;
41
+ hmac384Update: (len: number) => void;
42
+ hmac384Final: () => void;
43
+ wipeBuffers: () => void;
5
44
  }
package/dist/sha2.wasm CHANGED
Binary file
@@ -1,7 +1,7 @@
1
1
  import type { WasmSource } from '../wasm-source.js';
2
2
  export declare function sha3Init(source: WasmSource): Promise<void>;
3
3
  export type { WasmSource };
4
- export declare function _sha3Ready(): boolean;
4
+ export { isInitialized } from '../init.js';
5
5
  export declare class SHA3_256 {
6
6
  private readonly x;
7
7
  constructor();
@@ -27,7 +27,7 @@ export declare class SHA3_224 {
27
27
  dispose(): void;
28
28
  }
29
29
  /**
30
- * SHAKE128 XOF extendable output, multi-squeeze capable.
30
+ * SHAKE128 XOF, extendable output, multi-squeeze capable.
31
31
  *
32
32
  * Holds exclusive access to the `sha3` WASM module from construction until
33
33
  * `dispose()`. Constructing a second SHAKE128/SHAKE256 or any other sha3
@@ -48,7 +48,7 @@ export declare class SHAKE128 {
48
48
  dispose(): void;
49
49
  }
50
50
  /**
51
- * SHAKE256 XOF extendable output, multi-squeeze capable.
51
+ * SHAKE256 XOF, extendable output, multi-squeeze capable.
52
52
  *
53
53
  * Holds exclusive access to the `sha3` WASM module from construction until
54
54
  * `dispose()`. Constructing a second SHAKE128/SHAKE256 or any other sha3
@@ -68,4 +68,73 @@ export declare class SHAKE256 {
68
68
  hash(msg: Uint8Array, outputLength: number): Uint8Array;
69
69
  dispose(): void;
70
70
  }
71
+ /**
72
+ * Incremental SHA3-256. Construct, `update()` chunks (any size), `finalize()`
73
+ * to get the 32-byte digest. Finalize disposes the instance.
74
+ *
75
+ * Holds exclusive access to the `sha3` WASM module from construction until
76
+ * `dispose()` or `finalize()`. Mirrors SHAKE128 lifecycle.
77
+ */
78
+ export declare class SHA3_256Stream {
79
+ private readonly x;
80
+ private _tok;
81
+ constructor();
82
+ update(chunk: Uint8Array): this;
83
+ finalize(): Uint8Array;
84
+ dispose(): void;
85
+ }
86
+ /**
87
+ * Incremental SHA3-512. Construct, `update()` chunks (any size), `finalize()`
88
+ * to get the 64-byte digest. Finalize disposes the instance.
89
+ *
90
+ * Holds exclusive access to the `sha3` WASM module from construction until
91
+ * `dispose()` or `finalize()`. Mirrors SHAKE128 lifecycle.
92
+ */
93
+ export declare class SHA3_512Stream {
94
+ private readonly x;
95
+ private _tok;
96
+ constructor();
97
+ update(chunk: Uint8Array): this;
98
+ finalize(): Uint8Array;
99
+ dispose(): void;
100
+ }
101
+ /**
102
+ * Single-shot streaming SHAKE128. `outputLen` is bound at construction;
103
+ * `update()` absorbs chunks of any size, `finalize()` pads and squeezes
104
+ * exactly `outputLen` bytes, then disposes the instance.
105
+ *
106
+ * Used by `createRunningHash` in the sign layer: each StreamableSignatureSuite
107
+ * with `prehashAlgorithm: 'shake-128'` declares its `prehashSize` and that
108
+ * value is passed in here at construction time. The multi-squeeze
109
+ * `SHAKE128` class above remains for the XOF surface; this class is the
110
+ * fixed-output cousin that matches the RunningHash contract.
111
+ *
112
+ * Holds exclusive access to the `sha3` WASM module from construction until
113
+ * `dispose()` or `finalize()`. Mirrors `SHA3_256Stream` lifecycle.
114
+ */
115
+ export declare class SHAKE128Stream {
116
+ private readonly x;
117
+ private readonly _rate;
118
+ private readonly outputLen;
119
+ private _tok;
120
+ constructor(outputLen: number);
121
+ update(chunk: Uint8Array): this;
122
+ finalize(): Uint8Array;
123
+ dispose(): void;
124
+ }
125
+ /**
126
+ * Single-shot streaming SHAKE256. `outputLen` is bound at construction;
127
+ * mirrors `SHAKE128Stream`. See that class for usage notes.
128
+ */
129
+ export declare class SHAKE256Stream {
130
+ private readonly x;
131
+ private readonly _rate;
132
+ private readonly outputLen;
133
+ private _tok;
134
+ constructor(outputLen: number);
135
+ update(chunk: Uint8Array): this;
136
+ finalize(): Uint8Array;
137
+ dispose(): void;
138
+ }
71
139
  export { SHA3_256Hash } from './hash.js';
140
+ export { CSHAKE128, CSHAKE256, KMAC128, KMAC256, KMACXOF128, KMACXOF256 } from './kmac.js';