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,102 @@
1
+ /** BLAKE3 WASM exports. */
2
+ export interface Blake3Exports {
3
+ memory: WebAssembly.Memory;
4
+ getModuleId: () => number;
5
+ getMemoryPages: () => number;
6
+ getInputStagingOffset: () => number;
7
+ getOutputStagingOffset: () => number;
8
+ getCvOffset: () => number;
9
+ getMsgOffset: () => number;
10
+ getCounterOffset: () => number;
11
+ getBlockLenOffset: () => number;
12
+ getFlagsOffset: () => number;
13
+ getCompressOutOffset: () => number;
14
+ getKeyedKeyOffset: () => number;
15
+ getDeriveCvOffset: () => number;
16
+ getCompress4CvInOffset: () => number;
17
+ getCompress4MsgInOffset: () => number;
18
+ getCompress4CtrInOffset: () => number;
19
+ getCompress4OutOffset: () => number;
20
+ getCompress4BlenInOffset: () => number;
21
+ getCompress4FlagsInOffset: () => number;
22
+ getModeCvOffset: () => number;
23
+ FLAG_CHUNK_START: {
24
+ value: number;
25
+ };
26
+ FLAG_CHUNK_END: {
27
+ value: number;
28
+ };
29
+ FLAG_PARENT: {
30
+ value: number;
31
+ };
32
+ FLAG_ROOT: {
33
+ value: number;
34
+ };
35
+ FLAG_KEYED_HASH: {
36
+ value: number;
37
+ };
38
+ FLAG_DERIVE_KEY_CONTEXT: {
39
+ value: number;
40
+ };
41
+ FLAG_DERIVE_KEY_MATERIAL: {
42
+ value: number;
43
+ };
44
+ BLAKE3_IV0: {
45
+ value: number;
46
+ };
47
+ BLAKE3_IV1: {
48
+ value: number;
49
+ };
50
+ BLAKE3_IV2: {
51
+ value: number;
52
+ };
53
+ BLAKE3_IV3: {
54
+ value: number;
55
+ };
56
+ BLAKE3_IV4: {
57
+ value: number;
58
+ };
59
+ BLAKE3_IV5: {
60
+ value: number;
61
+ };
62
+ BLAKE3_IV6: {
63
+ value: number;
64
+ };
65
+ BLAKE3_IV7: {
66
+ value: number;
67
+ };
68
+ compress: (cvOff: number, blockOff: number, counterLo: number, counterHi: number, blockLen: number, flags: number, outOff: number) => void;
69
+ compress4: () => void;
70
+ chunkInit: (chunkIndex: bigint) => void;
71
+ chunkUpdate: (blockOff: number, blockLen: number) => void;
72
+ chunkFinalize: (outCvOff: number, isRootSoloChunk: number) => void;
73
+ treeInit: () => void;
74
+ treePushChunk: (chunkCvOff: number) => void;
75
+ treeFinalizeRoot: (outOff: number) => void;
76
+ hash: (inputOff: number, inputLen: number, outOff: number, outLen: number) => void;
77
+ hashKeyed: (keyOff: number, inputOff: number, inputLen: number, outOff: number, outLen: number) => void;
78
+ deriveKey: (contextOff: number, contextLen: number, materialOff: number, materialLen: number, outOff: number, outLen: number) => void;
79
+ squeezeXofBlock: (counterLo: number, counterHi: number, outOff: number) => void;
80
+ wipeBuffers: () => void;
81
+ }
82
+ /**
83
+ * BLAKE3 WASM internal test exports. NOT part of the consumer surface,
84
+ * NOT re-exported from `src/ts/blake3/index.ts`. Wired exclusively for
85
+ * the tree-internals test suite (`test/unit/blake3/blake3-tree-internals
86
+ * .test.ts`) and the Merkle-tree substrate
87
+ * (`src/ts/merkle/blake3-tree.ts`) which casts
88
+ * `Blake3Exports & Blake3TestExports` inside the merkle module.
89
+ *
90
+ * Tests obtain these via `test/unit/blake3/helpers.ts`, which casts the
91
+ * public `Blake3Exports` to `Blake3Exports & Blake3TestExports`. Consumer
92
+ * code never sees the `_test*` surface.
93
+ */
94
+ export interface Blake3TestExports {
95
+ _testChunkCV: (inputOff: number, inputLen: number, chunkIndex: bigint, startCvOff: number, modeFlags: number, outCvOff: number) => void;
96
+ _testParentCV: (leftCvOff: number, rightCvOff: number, startCvOff: number, modeFlags: number, isRoot: number, outCvOff: number) => void;
97
+ _testDeriveContextCV: (contextOff: number, contextLen: number, outCcvOff: number) => void;
98
+ _getBatch4CallCount: () => number;
99
+ _resetBatch4CallCount: () => void;
100
+ _getParentBatch4CallCount: () => number;
101
+ _resetParentBatch4CallCount: () => void;
102
+ }
@@ -0,0 +1,31 @@
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/types.ts
23
+ //
24
+ // BLAKE3 WASM exports interface. Mirrors the AssemblyScript surface in
25
+ // `src/asm/blake3/index.ts`. The consumer-facing TS surface (BLAKE3,
26
+ // BLAKE3Stream and the keyed_hash / derive_key variants) calls the
27
+ // top-level `hash` / `hashKeyed` / `deriveKey` entry points. Lower-level
28
+ // primitives (`compress`, flag constants, buffer accessors) are typed
29
+ // here for completeness and so test code can drive each layer in
30
+ // isolation if needed.
31
+ export {};
@@ -0,0 +1,29 @@
1
+ /**
2
+ * BLAKE3 §2.3 Modes: keyed_hash takes a 32-byte key. The key seeds the chunk
3
+ * machine in place of the BLAKE3 IV and every compress carries the
4
+ * KEYED_HASH flag. A key of any other length is a contract violation.
5
+ */
6
+ export declare function validateKey(key: Uint8Array): void;
7
+ /**
8
+ * BLAKE3 §2.3 Modes: derive_key takes a context string and produces a
9
+ * derived key. The context string is a domain separator and is
10
+ * conventionally a UTF-8 hardcoded application constant. An empty context
11
+ * defeats the domain separation §2.3 is designed to provide; reject it.
12
+ *
13
+ * Accepts a JS string (UTF-8 encoded here) or a Uint8Array (passed
14
+ * through). No upper cap on length.
15
+ */
16
+ export declare function validateContext(context: string | Uint8Array): Uint8Array;
17
+ /**
18
+ * BLAKE3 §2.6 XOF: default-length output is 32 bytes; the XOF can in principle
19
+ * produce up to 2^64 - 1 bytes. The one-shot path (BLAKE3.hash /
20
+ * BLAKE3KeyedHash.hash / BLAKE3DeriveKey.derive and the streaming
21
+ * finalize(outLen) counterparts) writes outLen bytes through a single
22
+ * WASM call sized by the OUTPUT_STAGING region, so the practical
23
+ * upper bound is `OUTPUT_STAGING_SIZE` (1024 bytes); larger consumers
24
+ * use `finalizeXof()` and stream from `BLAKE3OutputReader.read(n)`
25
+ * which squeezes 64 bytes at a time off the WASM-side root snapshot.
26
+ * This validator rejects nonsense (zero, negative, non-finite,
27
+ * non-integer); the one-shot wrappers enforce the per-call ceiling.
28
+ */
29
+ export declare function validateOutputLen(outLen: number): void;
@@ -0,0 +1,80 @@
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/validate.ts
23
+ //
24
+ // BLAKE3 caller-side input validation. Pure length / type checks, no
25
+ // crypto. BLAKE3 is a hash family, not a signature scheme; rejected
26
+ // inputs throw `RangeError` / `TypeError` (no `SigningError`).
27
+ /**
28
+ * BLAKE3 §2.3 Modes: keyed_hash takes a 32-byte key. The key seeds the chunk
29
+ * machine in place of the BLAKE3 IV and every compress carries the
30
+ * KEYED_HASH flag. A key of any other length is a contract violation.
31
+ */
32
+ export function validateKey(key) {
33
+ if (!(key instanceof Uint8Array))
34
+ throw new TypeError('leviathan-crypto: blake3 key must be a Uint8Array');
35
+ if (key.length !== 32)
36
+ throw new RangeError(`leviathan-crypto: blake3 key must be 32 bytes (got ${key.length})`);
37
+ }
38
+ /**
39
+ * BLAKE3 §2.3 Modes: derive_key takes a context string and produces a
40
+ * derived key. The context string is a domain separator and is
41
+ * conventionally a UTF-8 hardcoded application constant. An empty context
42
+ * defeats the domain separation §2.3 is designed to provide; reject it.
43
+ *
44
+ * Accepts a JS string (UTF-8 encoded here) or a Uint8Array (passed
45
+ * through). No upper cap on length.
46
+ */
47
+ export function validateContext(context) {
48
+ let bytes;
49
+ if (typeof context === 'string') {
50
+ bytes = new TextEncoder().encode(context);
51
+ }
52
+ else if (context instanceof Uint8Array) {
53
+ bytes = context;
54
+ }
55
+ else {
56
+ throw new TypeError('leviathan-crypto: blake3 derive_key context must be a string or Uint8Array');
57
+ }
58
+ if (bytes.length === 0)
59
+ throw new RangeError('leviathan-crypto: blake3 derive_key context must be non-empty '
60
+ + '(empty context defeats §2.3 domain separation)');
61
+ return bytes;
62
+ }
63
+ /**
64
+ * BLAKE3 §2.6 XOF: default-length output is 32 bytes; the XOF can in principle
65
+ * produce up to 2^64 - 1 bytes. The one-shot path (BLAKE3.hash /
66
+ * BLAKE3KeyedHash.hash / BLAKE3DeriveKey.derive and the streaming
67
+ * finalize(outLen) counterparts) writes outLen bytes through a single
68
+ * WASM call sized by the OUTPUT_STAGING region, so the practical
69
+ * upper bound is `OUTPUT_STAGING_SIZE` (1024 bytes); larger consumers
70
+ * use `finalizeXof()` and stream from `BLAKE3OutputReader.read(n)`
71
+ * which squeezes 64 bytes at a time off the WASM-side root snapshot.
72
+ * This validator rejects nonsense (zero, negative, non-finite,
73
+ * non-integer); the one-shot wrappers enforce the per-call ceiling.
74
+ */
75
+ export function validateOutputLen(outLen) {
76
+ if (typeof outLen !== 'number' || !Number.isFinite(outLen) || !Number.isInteger(outLen))
77
+ throw new RangeError(`leviathan-crypto: blake3 outLen must be a finite integer (got ${String(outLen)})`);
78
+ if (outLen < 1)
79
+ throw new RangeError(`leviathan-crypto: blake3 outLen must be >= 1 (got ${outLen})`);
80
+ }
Binary file
@@ -21,14 +21,15 @@
21
21
  //
22
22
  // src/ts/chacha20/cipher-suite.ts
23
23
  //
24
- // XChaCha20Cipher CipherSuite implementation for the STREAM construction.
24
+ // XChaCha20Cipher, CipherSuite implementation for the STREAM construction.
25
25
  // HKDF-SHA-256 key derivation → HChaCha20 subkey → ChaCha20-Poly1305 per chunk.
26
26
  import { getInstance, _assertNotOwned } from '../init.js';
27
27
  import { HKDF_SHA256 } from '../sha2/index.js';
28
28
  import { aeadEncrypt, aeadDecrypt, deriveSubkey } from './ops.js';
29
- import { wipe, randomBytes } from '../utils.js';
29
+ import { wipe, randomBytes, concat } from '../utils.js';
30
+ import { HEADER_SIZE } from '../stream/constants.js';
30
31
  import { WORKER_SOURCE } from '../embedded/chacha20-pool-worker.js';
31
- const INFO = new TextEncoder().encode('xchacha20-sealstream-v2');
32
+ const INFO = new TextEncoder().encode('xchacha20-sealstream-v3');
32
33
  /** Returns the raw chacha20 WASM export object. @internal */
33
34
  function getExports() {
34
35
  return getInstance('chacha20').exports;
@@ -44,11 +45,12 @@ function getExports() {
44
45
  * this object directly. Use `XChaCha20Cipher.keygen()` to generate a 32-byte key.
45
46
  */
46
47
  export const XChaCha20Cipher = {
47
- formatEnum: 0x01,
48
+ formatEnum: 0x03,
48
49
  formatName: 'xchacha20',
49
- hkdfInfo: 'xchacha20-sealstream-v2',
50
+ hkdfInfo: 'xchacha20-sealstream-v3',
50
51
  keySize: 32,
51
52
  kemCtSize: 0,
53
+ commitmentSize: 32,
52
54
  tagSize: 16,
53
55
  padded: false,
54
56
  wasmChunkSize: 65536, // src/asm/chacha20/buffers.ts CHUNK_SIZE
@@ -58,22 +60,50 @@ export const XChaCha20Cipher = {
58
60
  return randomBytes(32);
59
61
  },
60
62
  /**
61
- * Derive a 32-byte HChaCha20 subkey from `masterKey` and `nonce` via
62
- * HKDF-SHA-256 followed by HChaCha20 subkey derivation.
63
+ * Derive a 32-byte HChaCha20 subkey and a 32-byte key commitment from
64
+ * `masterKey` and `nonce` via HKDF-SHA-256 followed by HChaCha20 subkey
65
+ * derivation. The full 20-byte preamble header is appended to the HKDF
66
+ * info string, binding `formatEnum`, framed flag, nonce, and chunkSize
67
+ * into the derived material, header tampering causes derived keys to
68
+ * differ and AEAD fails on the first chunk.
69
+ *
70
+ * The 64-byte HKDF output is split: bytes 0..32 feed HChaCha20 subkey
71
+ * derivation, bytes 32..64 are the key commitment that ends up in the
72
+ * preamble. Verifying the commitment before any chunk is processed
73
+ * closes the Invisible Salamanders attack surface, Poly1305 alone is
74
+ * not key-committing, so without this an adversary with control over
75
+ * two master keys could craft a single ciphertext + tag that decrypts
76
+ * validly under both.
77
+ *
63
78
  * @param masterKey 32-byte master key
64
- * @param nonce Stream nonce (24 bytes minimum for XChaCha20 subkey derivation)
65
- * @returns `DerivedKeys` holding the 32-byte subkey
79
+ * @param nonce Stream nonce (16 bytes, also used as HChaCha20 input)
80
+ * @param _kemCt Unused for symmetric XChaCha20; KEM wrappers pass it through
81
+ * @param header 20-byte preamble header, required (throws otherwise)
82
+ * @returns `DerivedKeys` holding the 32-byte HChaCha20 subkey and 32-byte commitment
66
83
  */
67
- deriveKeys(masterKey, nonce, _kemCt) {
84
+ deriveKeys(masterKey, nonce, _kemCt, header) {
85
+ if (!header || header.length !== HEADER_SIZE)
86
+ throw new Error(`XChaCha20Cipher.deriveKeys: header binding required (got ${header?.length ?? 'undefined'} bytes)`);
68
87
  _assertNotOwned('chacha20');
69
88
  const hkdf = new HKDF_SHA256();
70
- const streamKey = hkdf.derive(masterKey, nonce, INFO, 32);
71
- hkdf.dispose();
72
- // HChaCha20 subkey derivation nonce[0:16] as XChaCha input
89
+ let okm;
90
+ try {
91
+ // INFO || header, binds formatEnum, framed flag, nonce, chunkSize into the KDF.
92
+ // Any header tampering produces different keys, AEAD fails on the first chunk.
93
+ const info = concat(INFO, header);
94
+ okm = hkdf.derive(masterKey, nonce, info, 64);
95
+ }
96
+ finally {
97
+ hkdf.dispose();
98
+ }
99
+ // Bytes 0..32: streamKey for HChaCha20 subkey derivation.
100
+ // Bytes 32..64: key commitment for the seal preamble.
101
+ const streamKey = okm.subarray(0, 32);
102
+ const commitment = okm.slice(32, 64); // independent backing, survives okm wipe
73
103
  const x = getExports();
74
104
  const subkey = deriveSubkey(x, streamKey, nonce);
75
- wipe(streamKey);
76
- return { bytes: subkey };
105
+ wipe(okm); // wipe both halves of okm; commitment is safe (independent backing)
106
+ return { bytes: subkey, commitment };
77
107
  },
78
108
  /**
79
109
  * Encrypt and authenticate one stream chunk with ChaCha20-Poly1305.
@@ -96,7 +126,7 @@ export const XChaCha20Cipher = {
96
126
  /**
97
127
  * Verify and decrypt one stream chunk. Throws `AuthenticationError` on tag mismatch.
98
128
  * @param keys Derived keys from `deriveKeys`
99
- * @param counterNonce 12-byte per-chunk nonce must match the value used by `sealChunk`
129
+ * @param counterNonce 12-byte per-chunk nonce, must match the value used by `sealChunk`
100
130
  * @param chunk Ciphertext || 16-byte Poly1305 tag
101
131
  * @param aad Optional additional authenticated data
102
132
  * @returns Plaintext
@@ -124,18 +154,10 @@ export const XChaCha20Cipher = {
124
154
  * @returns Newly constructed `Worker` instance
125
155
  */
126
156
  createPoolWorker() {
127
- // IIFE source is bundled at lib build time (scripts/embed-workers.ts).
128
- // Avoids the syntactic `new Worker(new URL(..., import.meta.url))`
129
- // pattern that triggers eager worker-chunk emission in Vite's
130
- // transform hook (issue.md). Classic worker via blob URL —
131
- // module workers fail on file:// in Chromium (issue2.md).
157
+ // See docs/architecture.md#pool-worker-spawn-pattern.
132
158
  const blob = new Blob([WORKER_SOURCE], { type: 'application/javascript' });
133
159
  const url = URL.createObjectURL(blob);
134
160
  const w = new Worker(url);
135
- // Worker spec fetches the URL synchronously at construction. Revoke
136
- // in a macrotask so the spawn completes first; releases the Blob
137
- // (~5 KB per spawn × N workers) instead of leaking it for the
138
- // document's lifetime.
139
161
  setTimeout(() => URL.revokeObjectURL(url), 0);
140
162
  return w;
141
163
  },
@@ -4,9 +4,9 @@ import type { Generator } from '../types.js';
4
4
  *
5
5
  * The 32-bit counter is read from `counter` as a little-endian u32. Each call
6
6
  * to `generate()` encrypts zero blocks to produce keystream output (RFC 8439 §2.3).
7
- * The nonce is fixed to zero Fortuna's counter is the only varying input.
7
+ * The nonce is fixed to zero, Fortuna's counter is the only varying input.
8
8
  *
9
- * Pass to `Fortuna.create({ generator: ChaCha20Generator, ... })` do not
9
+ * Pass to `Fortuna.create({ generator: ChaCha20Generator, ... })`, do not
10
10
  * call `generate()` directly outside of Fortuna.
11
11
  */
12
12
  export declare const ChaCha20Generator: Generator;
@@ -21,7 +21,7 @@
21
21
  //
22
22
  // src/ts/chacha20/generator.ts
23
23
  //
24
- // RFC 8439 §2.3 ChaCha20 block function as PRF
24
+ // RFC 8439 §2.3, ChaCha20 block function as PRF
25
25
  // ChaCha20 counter-mode PRF for Fortuna's generator slot.
26
26
  //
27
27
  // Counter is treated as a 32-bit LE integer. Fortuna's 4-byte genCnt provides
@@ -32,9 +32,9 @@ import { _assertNotOwned, getInstance } from '../init.js';
32
32
  *
33
33
  * The 32-bit counter is read from `counter` as a little-endian u32. Each call
34
34
  * to `generate()` encrypts zero blocks to produce keystream output (RFC 8439 §2.3).
35
- * The nonce is fixed to zero Fortuna's counter is the only varying input.
35
+ * The nonce is fixed to zero, Fortuna's counter is the only varying input.
36
36
  *
37
- * Pass to `Fortuna.create({ generator: ChaCha20Generator, ... })` do not
37
+ * Pass to `Fortuna.create({ generator: ChaCha20Generator, ... })`, do not
38
38
  * call `generate()` directly outside of Fortuna.
39
39
  */
40
40
  export const ChaCha20Generator = {
@@ -62,7 +62,7 @@ export const ChaCha20Generator = {
62
62
  const mem = new Uint8Array(x.memory.buffer);
63
63
  try {
64
64
  mem.set(key, x.getKeyOffset());
65
- // Fixed zero nonce Fortuna's counter is the only varying input
65
+ // Fixed zero nonce, Fortuna's counter is the only varying input
66
66
  mem.fill(0, x.getChachaNonceOffset(), x.getChachaNonceOffset() + 12);
67
67
  x.chachaSetCounter(c);
68
68
  x.chachaLoadKey();
@@ -4,11 +4,12 @@ export { AuthenticationError };
4
4
  /**
5
5
  * Load and initialise the ChaCha20 WASM module from `source`.
6
6
  * Must be called before constructing any ChaCha20 class.
7
- * @param source WASM binary gzip+base64 string, URL, ArrayBuffer, Uint8Array,
7
+ * @param source WASM binary, gzip+base64 string, URL, ArrayBuffer, Uint8Array,
8
8
  * pre-compiled WebAssembly.Module, Response, or Promise<Response>
9
9
  */
10
10
  export declare function chacha20Init(source: WasmSource): Promise<void>;
11
11
  export type { WasmSource };
12
+ export { isInitialized } from '../init.js';
12
13
  /**
13
14
  * Raw ChaCha20 stream cipher (RFC 8439 §2.4).
14
15
  *
@@ -24,23 +25,23 @@ export declare class ChaCha20 {
24
25
  * Load key and nonce into WASM state and set the block counter to 1.
25
26
  * Must be called before each message (RFC 8439 §2.4).
26
27
  * @param key 32 bytes
27
- * @param nonce 12 bytes must be unique per (key, message)
28
+ * @param nonce 12 bytes, must be unique per (key, message)
28
29
  */
29
30
  beginEncrypt(key: Uint8Array, nonce: Uint8Array): void;
30
31
  /**
31
32
  * XOR `chunk` with the next keystream block(s). Counter advances automatically.
32
- * @param chunk Plaintext chunk must not exceed WASM CHUNK_SIZE
33
+ * @param chunk Plaintext chunk, must not exceed WASM CHUNK_SIZE
33
34
  * @returns Ciphertext of the same length
34
35
  */
35
36
  encryptChunk(chunk: Uint8Array): Uint8Array;
36
37
  /**
37
- * Alias for `beginEncrypt` ChaCha20 is a stream cipher (symmetric).
38
+ * Alias for `beginEncrypt`, ChaCha20 is a stream cipher (symmetric).
38
39
  * @param key 32 bytes
39
- * @param nonce 12 bytes must match the value used to encrypt
40
+ * @param nonce 12 bytes, must match the value used to encrypt
40
41
  */
41
42
  beginDecrypt(key: Uint8Array, nonce: Uint8Array): void;
42
43
  /**
43
- * Alias for `encryptChunk` ChaCha20 is a stream cipher (symmetric).
44
+ * Alias for `encryptChunk`, ChaCha20 is a stream cipher (symmetric).
44
45
  * @param chunk Ciphertext chunk
45
46
  * @returns Plaintext of the same length
46
47
  */
@@ -61,7 +62,7 @@ export declare class Poly1305 {
61
62
  constructor();
62
63
  /**
63
64
  * Compute a 16-byte Poly1305 MAC for `msg` using `key`.
64
- * @param key 32-byte one-time key must not be reused across messages
65
+ * @param key 32-byte one-time key, must not be reused across messages
65
66
  * @param msg Message to authenticate
66
67
  * @returns 16-byte Poly1305 tag
67
68
  */
@@ -78,7 +79,7 @@ export declare class Poly1305 {
78
79
  * Single-use encrypt guard: `encrypt()` may only be called once per instance.
79
80
  * Create a new instance for each encryption to prevent nonce reuse.
80
81
  *
81
- * `decrypt()` uses constant-time tag comparison XOR-accumulate pattern,
82
+ * `decrypt()` uses constant-time tag comparison, XOR-accumulate pattern,
82
83
  * no early return on mismatch. Plaintext is never returned on failure.
83
84
  */
84
85
  export declare class ChaCha20Poly1305 {
@@ -89,10 +90,10 @@ export declare class ChaCha20Poly1305 {
89
90
  * Encrypt and authenticate `plaintext` with ChaCha20-Poly1305 (RFC 8439 §2.8).
90
91
  *
91
92
  * **Single-use guard:** `encrypt()` may only be called once per instance.
92
- * Any throw including validation errors permanently locks this instance.
93
+ * Any throw, including validation errors, permanently locks this instance.
93
94
  * Always create a new `ChaCha20Poly1305` per message.
94
95
  * @param key 32 bytes
95
- * @param nonce 12 bytes must be unique per (key, message)
96
+ * @param nonce 12 bytes, must be unique per (key, message)
96
97
  * @param plaintext Data to encrypt
97
98
  * @param aad Additional authenticated data (optional)
98
99
  * @returns Ciphertext || 16-byte Poly1305 tag
@@ -102,7 +103,7 @@ export declare class ChaCha20Poly1305 {
102
103
  * Verify and decrypt a ChaCha20-Poly1305 ciphertext (RFC 8439 §2.8).
103
104
  * Throws `AuthenticationError` if the tag does not match.
104
105
  * @param key 32 bytes
105
- * @param nonce 12 bytes must match the value used to encrypt
106
+ * @param nonce 12 bytes, must match the value used to encrypt
106
107
  * @param ciphertext Ciphertext || 16-byte tag (combined format from `encrypt`)
107
108
  * @param aad Additional authenticated data (optional)
108
109
  * @returns Plaintext
@@ -116,7 +117,7 @@ export declare class ChaCha20Poly1305 {
116
117
  * XChaCha20-Poly1305 AEAD (IETF draft-irtf-cfrg-xchacha).
117
118
  *
118
119
  * Recommended authenticated encryption primitive for most use cases.
119
- * Uses a 24-byte nonce safe for random generation via crypto.getRandomValues.
120
+ * Uses a 24-byte nonce, safe for random generation via crypto.getRandomValues.
120
121
  *
121
122
  * Single-use encrypt guard: `encrypt()` may only be called once per instance.
122
123
  * Create a new instance for each encryption to prevent nonce reuse.
@@ -132,10 +133,10 @@ export declare class XChaCha20Poly1305 {
132
133
  * (draft-irtf-cfrg-xchacha). Recommended for general-purpose AEAD.
133
134
  *
134
135
  * **Single-use guard:** `encrypt()` may only be called once per instance.
135
- * Any throw including validation errors permanently locks this instance.
136
+ * Any throw, including validation errors, permanently locks this instance.
136
137
  * Always create a new `XChaCha20Poly1305` per message to prevent nonce reuse.
137
138
  * @param key 32 bytes
138
- * @param nonce 24 bytes safe to generate randomly via `randomBytes(24)`
139
+ * @param nonce 24 bytes, safe to generate randomly via `randomBytes(24)`
139
140
  * @param plaintext Data to encrypt
140
141
  * @param aad Additional authenticated data (optional)
141
142
  * @returns Ciphertext || 16-byte Poly1305 tag
@@ -145,7 +146,7 @@ export declare class XChaCha20Poly1305 {
145
146
  * Verify and decrypt an XChaCha20-Poly1305 ciphertext.
146
147
  * Throws `AuthenticationError` if the tag does not match.
147
148
  * @param key 32 bytes
148
- * @param nonce 24 bytes must match the value used to encrypt
149
+ * @param nonce 24 bytes, must match the value used to encrypt
149
150
  * @param ciphertext Ciphertext || 16-byte tag (combined format from `encrypt`)
150
151
  * @param aad Additional authenticated data (optional)
151
152
  * @returns Plaintext