leviathan-crypto 2.0.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (312) hide show
  1. package/CLAUDE.md +88 -281
  2. package/LICENSE +4 -0
  3. package/README.md +275 -87
  4. package/dist/aes/aes-cbc.d.ts +40 -0
  5. package/dist/aes/aes-cbc.js +158 -0
  6. package/dist/aes/aes-ctr.d.ts +50 -0
  7. package/dist/aes/aes-ctr.js +141 -0
  8. package/dist/aes/aes-gcm-siv.d.ts +67 -0
  9. package/dist/aes/aes-gcm-siv.js +217 -0
  10. package/dist/aes/aes-gcm.d.ts +61 -0
  11. package/dist/aes/aes-gcm.js +226 -0
  12. package/dist/aes/cipher-suite.d.ts +21 -0
  13. package/dist/aes/cipher-suite.js +179 -0
  14. package/dist/aes/embedded.d.ts +1 -0
  15. package/dist/aes/embedded.js +26 -0
  16. package/dist/aes/generator.d.ts +14 -0
  17. package/dist/aes/generator.js +103 -0
  18. package/dist/aes/index.d.ts +58 -0
  19. package/dist/aes/index.js +125 -0
  20. package/dist/aes/ops.d.ts +60 -0
  21. package/dist/aes/ops.js +164 -0
  22. package/dist/aes/pool-worker.d.ts +1 -0
  23. package/dist/aes/pool-worker.js +92 -0
  24. package/dist/aes/types.d.ts +1 -0
  25. package/dist/aes/types.js +23 -0
  26. package/dist/aes.wasm +0 -0
  27. package/dist/blake3/embedded.d.ts +1 -0
  28. package/dist/blake3/embedded.js +26 -0
  29. package/dist/blake3/index.d.ts +143 -0
  30. package/dist/blake3/index.js +620 -0
  31. package/dist/blake3/types.d.ts +102 -0
  32. package/dist/blake3/types.js +31 -0
  33. package/dist/blake3/validate.d.ts +29 -0
  34. package/dist/blake3/validate.js +80 -0
  35. package/dist/blake3.wasm +0 -0
  36. package/dist/chacha20/cipher-suite.d.ts +10 -0
  37. package/dist/chacha20/cipher-suite.js +98 -13
  38. package/dist/chacha20/generator.d.ts +12 -0
  39. package/dist/chacha20/generator.js +91 -0
  40. package/dist/chacha20/index.d.ts +100 -3
  41. package/dist/chacha20/index.js +169 -35
  42. package/dist/chacha20/ops.d.ts +57 -6
  43. package/dist/chacha20/ops.js +107 -27
  44. package/dist/chacha20/pool-worker.js +14 -0
  45. package/dist/chacha20/types.d.ts +1 -32
  46. package/dist/cte-wasm.d.ts +1 -0
  47. package/dist/cte-wasm.js +3 -0
  48. package/dist/cte.wasm +0 -0
  49. package/dist/curve25519.wasm +0 -0
  50. package/dist/ecdsa/der.d.ts +23 -0
  51. package/dist/ecdsa/der.js +192 -0
  52. package/dist/ecdsa/ecprivatekey-der.d.ts +32 -0
  53. package/dist/ecdsa/ecprivatekey-der.js +230 -0
  54. package/dist/ecdsa/embedded.d.ts +1 -0
  55. package/dist/ecdsa/embedded.js +25 -0
  56. package/dist/ecdsa/index.d.ts +124 -0
  57. package/dist/ecdsa/index.js +366 -0
  58. package/dist/ecdsa/types.d.ts +31 -0
  59. package/dist/ecdsa/types.js +28 -0
  60. package/dist/ecdsa/validate.d.ts +18 -0
  61. package/dist/ecdsa/validate.js +92 -0
  62. package/dist/ed25519/embedded.d.ts +1 -0
  63. package/dist/ed25519/embedded.js +31 -0
  64. package/dist/ed25519/index.d.ts +70 -0
  65. package/dist/ed25519/index.js +308 -0
  66. package/dist/ed25519/types.d.ts +27 -0
  67. package/dist/ed25519/types.js +27 -0
  68. package/dist/ed25519/validate.d.ts +7 -0
  69. package/dist/ed25519/validate.js +77 -0
  70. package/dist/embedded/aes-pool-worker.d.ts +1 -0
  71. package/dist/embedded/aes-pool-worker.js +5 -0
  72. package/dist/embedded/aes.d.ts +1 -0
  73. package/dist/embedded/aes.js +3 -0
  74. package/dist/embedded/blake3.d.ts +1 -0
  75. package/dist/embedded/blake3.js +3 -0
  76. package/dist/embedded/chacha20-pool-worker.d.ts +1 -0
  77. package/dist/embedded/chacha20-pool-worker.js +5 -0
  78. package/dist/embedded/chacha20.d.ts +1 -1
  79. package/dist/embedded/chacha20.js +2 -2
  80. package/dist/embedded/curve25519.d.ts +1 -0
  81. package/dist/embedded/curve25519.js +3 -0
  82. package/dist/embedded/mldsa.d.ts +1 -0
  83. package/dist/embedded/mldsa.js +3 -0
  84. package/dist/embedded/mlkem.d.ts +1 -0
  85. package/dist/embedded/mlkem.js +3 -0
  86. package/dist/embedded/p256.d.ts +1 -0
  87. package/dist/embedded/p256.js +3 -0
  88. package/dist/embedded/serpent-pool-worker.d.ts +1 -0
  89. package/dist/embedded/serpent-pool-worker.js +5 -0
  90. package/dist/embedded/serpent.d.ts +1 -1
  91. package/dist/embedded/serpent.js +2 -2
  92. package/dist/embedded/sha2.d.ts +1 -1
  93. package/dist/embedded/sha2.js +2 -2
  94. package/dist/embedded/sha3.d.ts +1 -1
  95. package/dist/embedded/sha3.js +2 -2
  96. package/dist/embedded/slhdsa.d.ts +1 -0
  97. package/dist/embedded/slhdsa.js +3 -0
  98. package/dist/errors.d.ts +92 -1
  99. package/dist/errors.js +111 -1
  100. package/dist/fortuna.d.ts +18 -12
  101. package/dist/fortuna.js +166 -99
  102. package/dist/index.d.ts +42 -11
  103. package/dist/index.js +65 -20
  104. package/dist/init.d.ts +1 -3
  105. package/dist/init.js +73 -7
  106. package/dist/keccak/embedded.js +1 -1
  107. package/dist/keccak/index.d.ts +2 -0
  108. package/dist/keccak/index.js +4 -2
  109. package/dist/loader.d.ts +1 -19
  110. package/dist/loader.js +26 -32
  111. package/dist/merkle/blake3-tree.d.ts +35 -0
  112. package/dist/merkle/blake3-tree.js +187 -0
  113. package/dist/merkle/checkpoint.d.ts +58 -0
  114. package/dist/merkle/checkpoint.js +217 -0
  115. package/dist/merkle/index.d.ts +19 -0
  116. package/dist/merkle/index.js +37 -0
  117. package/dist/merkle/merkle-log.d.ts +130 -0
  118. package/dist/merkle/merkle-log.js +207 -0
  119. package/dist/merkle/merkle-verifier.d.ts +126 -0
  120. package/dist/merkle/merkle-verifier.js +296 -0
  121. package/dist/merkle/proof.d.ts +70 -0
  122. package/dist/merkle/proof.js +300 -0
  123. package/dist/merkle/sha256-tree.d.ts +33 -0
  124. package/dist/merkle/sha256-tree.js +145 -0
  125. package/dist/merkle/signed-log.d.ts +156 -0
  126. package/dist/merkle/signed-log.js +356 -0
  127. package/dist/merkle/signed-note.d.ts +309 -0
  128. package/dist/merkle/signed-note.js +648 -0
  129. package/dist/merkle/sth.d.ts +31 -0
  130. package/dist/merkle/sth.js +31 -0
  131. package/dist/merkle/storage.d.ts +40 -0
  132. package/dist/merkle/storage.js +71 -0
  133. package/dist/merkle/tree.d.ts +68 -0
  134. package/dist/merkle/tree.js +94 -0
  135. package/dist/mldsa/embedded.d.ts +1 -0
  136. package/dist/{kyber → mldsa}/embedded.js +5 -5
  137. package/dist/mldsa/expand.d.ts +53 -0
  138. package/dist/mldsa/expand.js +188 -0
  139. package/dist/mldsa/format.d.ts +16 -0
  140. package/dist/mldsa/format.js +68 -0
  141. package/dist/mldsa/hashvariant.d.ts +32 -0
  142. package/dist/mldsa/hashvariant.js +248 -0
  143. package/dist/mldsa/index.d.ts +142 -0
  144. package/dist/mldsa/index.js +463 -0
  145. package/dist/mldsa/keygen.d.ts +16 -0
  146. package/dist/mldsa/keygen.js +232 -0
  147. package/dist/mldsa/params.d.ts +21 -0
  148. package/dist/mldsa/params.js +55 -0
  149. package/dist/mldsa/sha3-helpers.d.ts +30 -0
  150. package/dist/mldsa/sha3-helpers.js +124 -0
  151. package/dist/mldsa/sign.d.ts +36 -0
  152. package/dist/mldsa/sign.js +380 -0
  153. package/dist/mldsa/types.d.ts +91 -0
  154. package/dist/mldsa/types.js +25 -0
  155. package/dist/mldsa/validate.d.ts +55 -0
  156. package/dist/mldsa/validate.js +125 -0
  157. package/dist/mldsa/verify.d.ts +29 -0
  158. package/dist/mldsa/verify.js +269 -0
  159. package/dist/mldsa.wasm +0 -0
  160. package/dist/mlkem/embedded.d.ts +1 -0
  161. package/dist/mlkem/embedded.js +27 -0
  162. package/dist/mlkem/indcpa.d.ts +49 -0
  163. package/dist/{kyber → mlkem}/indcpa.js +48 -48
  164. package/dist/mlkem/index.d.ts +37 -0
  165. package/dist/{kyber → mlkem}/index.js +41 -31
  166. package/dist/mlkem/kem.d.ts +21 -0
  167. package/dist/{kyber → mlkem}/kem.js +48 -13
  168. package/dist/{kyber → mlkem}/params.d.ts +4 -4
  169. package/dist/{kyber → mlkem}/params.js +2 -2
  170. package/dist/mlkem/suite.d.ts +12 -0
  171. package/dist/{kyber → mlkem}/suite.js +17 -12
  172. package/dist/{kyber → mlkem}/types.d.ts +4 -3
  173. package/dist/{kyber → mlkem}/types.js +1 -1
  174. package/dist/mlkem/validate.d.ts +23 -0
  175. package/dist/{kyber → mlkem}/validate.js +24 -20
  176. package/dist/{kyber.wasm → mlkem.wasm} +0 -0
  177. package/dist/p256.wasm +0 -0
  178. package/dist/ratchet/index.d.ts +8 -0
  179. package/dist/ratchet/index.js +38 -0
  180. package/dist/ratchet/kdf-chain.d.ts +13 -0
  181. package/dist/ratchet/kdf-chain.js +85 -0
  182. package/dist/ratchet/ratchet-keypair.d.ts +9 -0
  183. package/dist/ratchet/ratchet-keypair.js +61 -0
  184. package/dist/ratchet/root-kdf.d.ts +4 -0
  185. package/dist/ratchet/root-kdf.js +124 -0
  186. package/dist/ratchet/skipped-key-store.d.ts +14 -0
  187. package/dist/ratchet/skipped-key-store.js +154 -0
  188. package/dist/ratchet/types.d.ts +36 -0
  189. package/dist/ratchet/types.js +26 -0
  190. package/dist/serpent/cipher-suite.d.ts +10 -0
  191. package/dist/serpent/cipher-suite.js +144 -56
  192. package/dist/serpent/generator.d.ts +12 -0
  193. package/dist/serpent/generator.js +97 -0
  194. package/dist/serpent/index.d.ts +62 -1
  195. package/dist/serpent/index.js +97 -21
  196. package/dist/serpent/pool-worker.js +28 -102
  197. package/dist/serpent/serpent-cbc.d.ts +16 -6
  198. package/dist/serpent/serpent-cbc.js +58 -37
  199. package/dist/serpent/shared-ops.d.ts +63 -0
  200. package/dist/serpent/shared-ops.js +178 -0
  201. package/dist/serpent/types.d.ts +1 -5
  202. package/dist/serpent.wasm +0 -0
  203. package/dist/sha2/hash.d.ts +2 -0
  204. package/dist/sha2/hash.js +53 -0
  205. package/dist/sha2/hkdf.js +5 -5
  206. package/dist/sha2/index.d.ts +22 -1
  207. package/dist/sha2/index.js +80 -11
  208. package/dist/sha2/types.d.ts +41 -2
  209. package/dist/sha2.wasm +0 -0
  210. package/dist/sha3/hash.d.ts +2 -0
  211. package/dist/sha3/hash.js +53 -0
  212. package/dist/sha3/index.d.ts +87 -3
  213. package/dist/sha3/index.js +317 -19
  214. package/dist/sha3/kmac.d.ts +121 -0
  215. package/dist/sha3/kmac.js +800 -0
  216. package/dist/sha3.wasm +0 -0
  217. package/dist/shared/pkcs7.d.ts +22 -0
  218. package/dist/shared/pkcs7.js +84 -0
  219. package/dist/sign/ctx.d.ts +41 -0
  220. package/dist/sign/ctx.js +102 -0
  221. package/dist/sign/envelope.d.ts +45 -0
  222. package/dist/sign/envelope.js +152 -0
  223. package/dist/sign/hasher.d.ts +9 -0
  224. package/dist/sign/hasher.js +132 -0
  225. package/dist/sign/index.d.ts +11 -0
  226. package/dist/sign/index.js +34 -0
  227. package/dist/sign/sign-stream.d.ts +25 -0
  228. package/dist/sign/sign-stream.js +112 -0
  229. package/dist/sign/suites/ecdsa-p256.d.ts +2 -0
  230. package/dist/sign/suites/ecdsa-p256.js +120 -0
  231. package/dist/sign/suites/ed25519.d.ts +3 -0
  232. package/dist/sign/suites/ed25519.js +165 -0
  233. package/dist/sign/suites/hybrid-classical.d.ts +23 -0
  234. package/dist/sign/suites/hybrid-classical.js +526 -0
  235. package/dist/sign/suites/hybrid-pq.d.ts +4 -0
  236. package/dist/sign/suites/hybrid-pq.js +234 -0
  237. package/dist/sign/suites/mldsa.d.ts +7 -0
  238. package/dist/sign/suites/mldsa.js +161 -0
  239. package/dist/sign/suites/slhdsa.d.ts +7 -0
  240. package/dist/sign/suites/slhdsa.js +176 -0
  241. package/dist/sign/types.d.ts +106 -0
  242. package/dist/sign/types.js +28 -0
  243. package/dist/sign/verify-stream.d.ts +30 -0
  244. package/dist/sign/verify-stream.js +227 -0
  245. package/dist/slhdsa/embedded.d.ts +1 -0
  246. package/dist/slhdsa/embedded.js +26 -0
  247. package/dist/slhdsa/index.d.ts +149 -0
  248. package/dist/slhdsa/index.js +493 -0
  249. package/dist/slhdsa/params.d.ts +26 -0
  250. package/dist/slhdsa/params.js +70 -0
  251. package/dist/slhdsa/prehash.d.ts +68 -0
  252. package/dist/slhdsa/prehash.js +307 -0
  253. package/dist/slhdsa/sign.d.ts +39 -0
  254. package/dist/slhdsa/sign.js +116 -0
  255. package/dist/slhdsa/types.d.ts +129 -0
  256. package/dist/slhdsa/types.js +27 -0
  257. package/dist/slhdsa/validate.d.ts +60 -0
  258. package/dist/slhdsa/validate.js +127 -0
  259. package/dist/slhdsa/verify.d.ts +32 -0
  260. package/dist/slhdsa/verify.js +107 -0
  261. package/dist/slhdsa.wasm +0 -0
  262. package/dist/stream/header.js +8 -8
  263. package/dist/stream/index.d.ts +1 -0
  264. package/dist/stream/index.js +1 -0
  265. package/dist/stream/open-stream.js +65 -22
  266. package/dist/stream/seal-stream-pool.d.ts +2 -0
  267. package/dist/stream/seal-stream-pool.js +100 -33
  268. package/dist/stream/seal-stream.d.ts +1 -1
  269. package/dist/stream/seal-stream.js +48 -19
  270. package/dist/stream/seal.js +6 -6
  271. package/dist/stream/types.d.ts +3 -1
  272. package/dist/stream/types.js +1 -1
  273. package/dist/types.d.ts +22 -1
  274. package/dist/types.js +1 -1
  275. package/dist/utils.d.ts +9 -10
  276. package/dist/utils.js +84 -59
  277. package/dist/wasm-source.d.ts +9 -8
  278. package/dist/wasm-source.js +1 -1
  279. package/dist/x25519/embedded.d.ts +1 -0
  280. package/dist/x25519/embedded.js +31 -0
  281. package/dist/x25519/index.d.ts +43 -0
  282. package/dist/x25519/index.js +159 -0
  283. package/dist/x25519/types.d.ts +25 -0
  284. package/dist/x25519/types.js +27 -0
  285. package/dist/x25519/validate.d.ts +2 -0
  286. package/dist/x25519/validate.js +39 -0
  287. package/package.json +123 -64
  288. package/SECURITY.md +0 -276
  289. package/dist/ct-wasm.d.ts +0 -1
  290. package/dist/ct-wasm.js +0 -3
  291. package/dist/ct.wasm +0 -0
  292. package/dist/docs/aead.md +0 -323
  293. package/dist/docs/architecture.md +0 -932
  294. package/dist/docs/argon2id.md +0 -302
  295. package/dist/docs/chacha20.md +0 -674
  296. package/dist/docs/exports.md +0 -241
  297. package/dist/docs/fortuna.md +0 -313
  298. package/dist/docs/init.md +0 -302
  299. package/dist/docs/loader.md +0 -161
  300. package/dist/docs/serpent.md +0 -519
  301. package/dist/docs/sha2.md +0 -613
  302. package/dist/docs/sha3.md +0 -546
  303. package/dist/docs/types.md +0 -276
  304. package/dist/docs/utils.md +0 -367
  305. package/dist/embedded/kyber.d.ts +0 -1
  306. package/dist/embedded/kyber.js +0 -3
  307. package/dist/kyber/embedded.d.ts +0 -1
  308. package/dist/kyber/indcpa.d.ts +0 -49
  309. package/dist/kyber/index.d.ts +0 -38
  310. package/dist/kyber/kem.d.ts +0 -21
  311. package/dist/kyber/suite.d.ts +0 -13
  312. package/dist/kyber/validate.d.ts +0 -19
@@ -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/mldsa/validate.ts
23
+ //
24
+ // ML-DSA caller-side input validation. Pure length / type checks, no
25
+ // content validation here. Semantic content validity (e.g. malformed hint
26
+ // encoding) is handled inside Verify_internal via hint_bit_unpack's -1
27
+ // sentinel (FIPS 204 Algorithm 21 / §D.3).
28
+ //
29
+ // Length checks throw RangeError. The public verify() method intercepts
30
+ // pk/sig length mismatches and returns false instead of propagating the
31
+ // throw, that is FIPS 204 §3.6.2 protocol shape, not a contract violation.
32
+ // validateContext, validateSigningKey, validateRnd ARE contract violations
33
+ // and propagate the throw.
34
+ import { SigningError } from '../errors.js';
35
+ import { digestSize } from './hashvariant.js';
36
+ /**
37
+ * FIPS 204 §5.2 / §5.3 line 1, ctx must be ≤ 255 bytes (the byte that
38
+ * follows the domain separator in M' is ctx.length, so longer values
39
+ * cannot be encoded).
40
+ */
41
+ export function validateContext(ctx) {
42
+ if (!(ctx instanceof Uint8Array))
43
+ throw new TypeError('leviathan-crypto: ctx must be a Uint8Array');
44
+ if (ctx.length > 255)
45
+ throw new RangeError(`leviathan-crypto: ctx must be ≤ 255 bytes (got ${ctx.length})`);
46
+ }
47
+ /**
48
+ * FIPS 204 §3.6.2, verification key must be exactly pkBytes long for
49
+ * its parameter set. Throws here; the public verify() method catches
50
+ * the throw and returns false so wrong-length pk reads as "not a valid
51
+ * signature" rather than a caller error.
52
+ */
53
+ export function validateVerificationKey(vk, params) {
54
+ if (!(vk instanceof Uint8Array))
55
+ throw new TypeError('leviathan-crypto: verification key must be a Uint8Array');
56
+ if (vk.length !== params.pkBytes)
57
+ throw new RangeError(`leviathan-crypto: verification key must be ${params.pkBytes} bytes for ${params.paramSet} `
58
+ + `(got ${vk.length})`);
59
+ }
60
+ /**
61
+ * Signing key must be exactly skBytes long for its parameter set. Wrong
62
+ * length is a caller error (the caller produced this sk via keygen* or
63
+ * loaded it from storage they own); throw RangeError unconditionally.
64
+ */
65
+ export function validateSigningKey(sk, params) {
66
+ if (!(sk instanceof Uint8Array))
67
+ throw new TypeError('leviathan-crypto: signing key must be a Uint8Array');
68
+ if (sk.length !== params.skBytes)
69
+ throw new RangeError(`leviathan-crypto: signing key must be ${params.skBytes} bytes for ${params.paramSet} `
70
+ + `(got ${sk.length})`);
71
+ }
72
+ /**
73
+ * FIPS 204 §3.6.2, signature must be exactly sigBytes long for its
74
+ * parameter set. Throws here; the public verify() method catches and
75
+ * returns false (same protocol shape as wrong-length pk).
76
+ */
77
+ export function validateSignature(sig, params) {
78
+ if (!(sig instanceof Uint8Array))
79
+ throw new TypeError('leviathan-crypto: signature must be a Uint8Array');
80
+ if (sig.length !== params.sigBytes)
81
+ throw new RangeError(`leviathan-crypto: signature must be ${params.sigBytes} bytes for ${params.paramSet} `
82
+ + `(got ${sig.length})`);
83
+ }
84
+ /**
85
+ * FIPS 204 Algorithm 7 line 1, rnd must be 32 bytes. Used by signDerand
86
+ * (the testing/CAVP API). Hedged sign supplies rnd internally; deterministic
87
+ * sign uses zeros; only signDerand exposes rnd to the caller.
88
+ */
89
+ export function validateRnd(rnd) {
90
+ if (!(rnd instanceof Uint8Array))
91
+ throw new TypeError('leviathan-crypto: rnd must be a Uint8Array');
92
+ if (rnd.length !== 32)
93
+ throw new RangeError(`leviathan-crypto: rnd must be 32 bytes (got ${rnd.length})`);
94
+ }
95
+ /**
96
+ * Confirms M is a Uint8Array. FIPS 204 places no length restriction on
97
+ * the message, M is absorbed into a SHAKE256 sponge (μ derivation,
98
+ * §6.2/§6.3) so any byte length is admissible. The bit-vs-byte
99
+ * distinction visible in §5.2/§5.3 (BytesToBits in M' construction)
100
+ * collapses at the byte boundary inside our SHAKE wrapper.
101
+ */
102
+ export function validateMessage(M) {
103
+ if (!(M instanceof Uint8Array))
104
+ throw new TypeError('leviathan-crypto: message must be a Uint8Array');
105
+ }
106
+ /**
107
+ * FIPS 204 §5.4.1, the prehash PH_M passed to HashML-DSA Sign_internal /
108
+ * Verify_internal must be exactly the digest size of `algo`. Used by the
109
+ * `*Prehashed` family where the caller computes PH externally; the
110
+ * non-prehashed family produces PH internally so this check is implicit.
111
+ *
112
+ * Throws `SigningError('sig-malformed-input')` on mismatch. The verify
113
+ * surface intercepts this to return false (a wrong-size digest is a
114
+ * structural mismatch, indistinguishable from a wrong signature), while
115
+ * the sign surface lets the throw propagate (the caller supplied bad
116
+ * input, that is a contract violation per the FIPS 204 §5.4 input
117
+ * contract).
118
+ */
119
+ export function validateDigest(digest, algo) {
120
+ if (!(digest instanceof Uint8Array))
121
+ throw new SigningError('sig-malformed-input', 'digest must be a Uint8Array');
122
+ const expected = digestSize(algo);
123
+ if (digest.length !== expected)
124
+ throw new SigningError('sig-malformed-input', `digest length ${digest.length} != ${expected} for ${algo}`);
125
+ }
@@ -0,0 +1,29 @@
1
+ import type { MlDsaExports, Sha3Exports } from './types.js';
2
+ import type { MlDsaParams } from './params.js';
3
+ import { type PreHashAlgorithm } from './hashvariant.js';
4
+ /**
5
+ * ML-DSA.Verify_internal, FIPS 204 Algorithm 8.
6
+ *
7
+ * Inputs (all caller-validated for length by the public verify() method):
8
+ * vk , encoded verification key (pkBytes)
9
+ * MPrime, domain-separated message bytes
10
+ * sig , encoded signature (sigBytes)
11
+ *
12
+ * Returns: boolean.
13
+ * true , signature authenticates the message under vk.
14
+ * false, wrong sig, malformed hint encoding, or norm check failure.
15
+ */
16
+ export declare function mldsaVerifyInternal(mx: MlDsaExports, sx: Sha3Exports, params: MlDsaParams, vk: Uint8Array, MPrime: Uint8Array, sig: Uint8Array): boolean;
17
+ /**
18
+ * HashML-DSA verify, post-prehash. FIPS 204 §5.4 Algorithm 5 lines 17-19.
19
+ * Builds M' = 0x01 ‖ |ctx| ‖ ctx ‖ OID(algo) ‖ prehash and drives
20
+ * Verify_internal.
21
+ *
22
+ * Same return / throw posture as `mldsaVerifyInternal`: returns a pure
23
+ * boolean for every signature outcome. Caller (in index.ts) is expected
24
+ * to have already filtered wrong-length vk / sig / digest with the
25
+ * appropriate verdict (false) before calling this helper.
26
+ *
27
+ * The caller owns `prehash`; this helper never wipes it.
28
+ */
29
+ export declare function verifyWithPrehash(mx: MlDsaExports, sx: Sha3Exports, params: MlDsaParams, vk: Uint8Array, prehash: Uint8Array, sig: Uint8Array, algo: PreHashAlgorithm, ctx: Uint8Array): boolean;
@@ -0,0 +1,269 @@
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/mldsa/verify.ts
23
+ //
24
+ // FIPS 204 §6.3 Algorithm 8, ML-DSA.Verify_internal.
25
+ //
26
+ // Verify is a pure boolean predicate: returns true iff the signature
27
+ // passes the FIPS 204 norm check (‖z‖∞ < γ₁ − β) AND the constant-time
28
+ // comparison of the recomputed c̃' against the σ-supplied c̃. There is
29
+ // no analog to the FO transform's implicit-rejection branch (ML-KEM's
30
+ // `return pseudorandom shared secret on failure`); ML-DSA verification
31
+ // is binary.
32
+ //
33
+ // SUF-CMA-critical preconditions enforced here:
34
+ // 1. Length check on pk and σ, caller (verify() in index.ts) returns
35
+ // false on mismatch BEFORE invoking this internal function, per
36
+ // FIPS 204 §3.6.2.
37
+ // 2. HintBitUnpack-malformed → false (FIPS 204 §D.3 / Algorithm 21
38
+ // lines 4, 9, 17). The kernel returns -1; we propagate as false.
39
+ // 3. Constant-time c̃ ↔ c̃' comparison via leviathan-crypto's
40
+ // `constantTimeEqual` (SIMD WASM XOR-accumulate, no early-exit).
41
+ //
42
+ // Slot allocation:
43
+ // POLYVEC_SLOT_0 t₁ → t₁·2^d (regular) → t̂₁·2^d (regular) → tomont
44
+ // POLYVEC_SLOT_1 z (time-domain) → ẑ (regular) → ẑ tomont
45
+ // POLYVEC_SLOT_2 h (hint polyvec; alive through use_hint)
46
+ // POLYVEC_SLOT_3 Â · ẑ → w'_approx → w'₁ (in place via use_hint aliasing)
47
+ // POLYVEC_SLOT_4 ĉ · t̂₁·2^d intermediate
48
+ // POLY_SLOT_0 signs (8 bytes, sample_in_ball signsOff)
49
+ // POLY_SLOT_1 c → ĉ
50
+ // POLY_SLOT_7 reserved scratch for polyvec_pointwise_acc_montgomery
51
+ import { constantTimeEqual, wipe } from '../utils.js';
52
+ import { sha3Absorb, shake256Hash, shake256HashConcat } from './sha3-helpers.js';
53
+ import { expandA } from './expand.js';
54
+ import { getOid } from './hashvariant.js';
55
+ import { constructMPrimeHash } from './format.js';
56
+ const POLY_BYTES = 1024;
57
+ const D = 13;
58
+ const Q = 8380417;
59
+ const SHAKE256_RATE = 136;
60
+ function bitlen(n) {
61
+ let b = 0;
62
+ let x = n;
63
+ while (x > 0) {
64
+ b++;
65
+ x >>>= 1;
66
+ }
67
+ return b;
68
+ }
69
+ /**
70
+ * ML-DSA.Verify_internal, FIPS 204 Algorithm 8.
71
+ *
72
+ * Inputs (all caller-validated for length by the public verify() method):
73
+ * vk , encoded verification key (pkBytes)
74
+ * MPrime, domain-separated message bytes
75
+ * sig , encoded signature (sigBytes)
76
+ *
77
+ * Returns: boolean.
78
+ * true , signature authenticates the message under vk.
79
+ * false, wrong sig, malformed hint encoding, or norm check failure.
80
+ */
81
+ export function mldsaVerifyInternal(mx, sx, params, vk, MPrime, sig) {
82
+ const { k, l, tau, lambda, gamma1, gamma2, beta, omega } = params;
83
+ const lambdaOver4 = lambda >>> 2; // 32 / 48 / 64
84
+ const c = 1 + bitlen(gamma1 - 1); // 18 or 20
85
+ const zPolyBytes = 32 * c;
86
+ const t1Bitlen = bitlen(Q - 1) - D; // 23 − 13 = 10
87
+ const t1PolyBytes = (256 * t1Bitlen) >> 3; // 320
88
+ const w1Bitlen = bitlen(((Q - 1) / (2 * gamma2)) - 1);
89
+ const w1PolyBytes = (256 * w1Bitlen) >> 3;
90
+ const w1TotalBytes = k * w1PolyBytes;
91
+ const t1ScalarShift = D; // multiply t₁ by 2^d in time domain
92
+ // ── WASM offsets ─────────────────────────────────────────────────────
93
+ const matOff = mx.getMatrixSlot();
94
+ const slot0 = mx.getPolyvecSlot0(); // t₁ then t̂₁·2^d (tomont)
95
+ const slot1 = mx.getPolyvecSlot1(); // z then ẑ (tomont)
96
+ const slot2 = mx.getPolyvecSlot2(); // h
97
+ const slot3 = mx.getPolyvecSlot3(); // ·ẑ → w'_approx → w'₁
98
+ const slot4 = mx.getPolyvecSlot4(); // ĉ·t̂₁·2^d
99
+ const polySlotBase = mx.getPolySlotBase();
100
+ const polySlot0 = mx.getPolySlot0(); // signs
101
+ const polySlot1 = mx.getPolySlot1(); // c → ĉ
102
+ const xofOff = mx.getXofPrfOffset();
103
+ const mlMem = new Uint8Array(mx.memory.buffer);
104
+ const sha3Mem = new Uint8Array(sx.memory.buffer);
105
+ const sha3OutOff = sx.getOutOffset();
106
+ // Public-derivable but wipe in finally for hygiene + symmetry with sign.
107
+ let mu;
108
+ let tr;
109
+ let cTilde;
110
+ let cTildeNew;
111
+ let w1Bytes;
112
+ try {
113
+ // ── Step 1: pkDecode (FIPS 204 §7.2 Algorithm 23) ────────────────
114
+ const rho = vk.subarray(0, 32);
115
+ for (let r = 0; r < k; r++) {
116
+ const srcOff = 32 + r * t1PolyBytes;
117
+ mlMem.set(vk.subarray(srcOff, srcOff + t1PolyBytes), xofOff);
118
+ mx.simple_bit_unpack(slot0 + r * POLY_BYTES, xofOff, t1Bitlen);
119
+ }
120
+ // ── Step 2: sigDecode (FIPS 204 §7.2 Algorithm 27) ────────────────
121
+ // σ = c̃ ‖ z_packed ‖ h_packed
122
+ cTilde = sig.slice(0, lambdaOver4);
123
+ let off = lambdaOver4;
124
+ for (let r = 0; r < l; r++) {
125
+ mlMem.set(sig.subarray(off, off + zPolyBytes), xofOff);
126
+ mx.bit_unpack(slot1 + r * POLY_BYTES, xofOff, gamma1 - 1, gamma1);
127
+ off += zPolyBytes;
128
+ }
129
+ // HintBitUnpack, FIPS 204 Algorithm 21. Returns -1 on any of the
130
+ // three malformed-input checks (lines 4, 9, 17). Propagate as
131
+ // false: this is the SUF-CMA fix from FIPS 204 §D.3.
132
+ mlMem.set(sig.subarray(off, off + omega + k), xofOff);
133
+ if (mx.hint_bit_unpack(slot2, xofOff, k, omega) < 0)
134
+ return false;
135
+ // ── Step (Alg 8 line 4) Â ← ExpandA(ρ) ─────────────────────────
136
+ expandA(mx, sx, params, rho, matOff);
137
+ // ── Step (Alg 8 line 5) tr ← H(BytesToBits(pk), 64) ──────────────
138
+ tr = shake256Hash(sx, vk, 64);
139
+ // ── Step (Alg 8 line 6) μ ← H(BytesToBits(tr) ‖ M', 64) ──────────
140
+ mu = shake256HashConcat(sx, [tr, MPrime], 64);
141
+ // ── Step (Alg 8 line 7) c ← SampleInBall(c̃) ───────────────────
142
+ mlMem.fill(0, polySlot1, polySlot1 + POLY_BYTES);
143
+ sx.shake256Init();
144
+ sha3Absorb(sx, cTilde);
145
+ sx.shakePad();
146
+ sx.shakeSqueezeBlock();
147
+ mlMem.set(sha3Mem.subarray(sha3OutOff, sha3OutOff + 8), polySlot0);
148
+ mlMem.set(sha3Mem.subarray(sha3OutOff + 8, sha3OutOff + SHAKE256_RATE), xofOff);
149
+ let sampleI = mx.sample_in_ball(polySlot1, polySlot0, xofOff, SHAKE256_RATE - 8, tau, 256 - tau);
150
+ while (sampleI < 256) {
151
+ sx.shakeSqueezeBlock();
152
+ mlMem.set(sha3Mem.subarray(sha3OutOff, sha3OutOff + SHAKE256_RATE), xofOff);
153
+ sampleI = mx.sample_in_ball(polySlot1, polySlot0, xofOff, SHAKE256_RATE, tau, sampleI);
154
+ }
155
+ // ── Step (Alg 8 line 8) w'_approx ← NTT⁻¹(Â ∘ NTT(z) − NTT(c) ∘ NTT(t₁·2^d))
156
+ // (a) NTT z, then tomont so the matrix kernel's R⁻¹ leaves regular result.
157
+ mx.polyvec_ntt(slot1, l);
158
+ mx.polyvec_tomont(slot1, l);
159
+ // (b) Compute t₁·2^d in time domain. t₁[i] ∈ [0, 1023]; t₁[i]·2^13
160
+ // ≤ 1023 · 8192 = 8,380,416 < q = 8,380,417, so no mod needed
161
+ // and no overflow. Use Int32Array view over the slot region.
162
+ const t1View = new Int32Array(mlMem.buffer, slot0, k * 256);
163
+ for (let i = 0; i < k * 256; i++)
164
+ t1View[i] <<= t1ScalarShift;
165
+ mx.polyvec_ntt(slot0, k);
166
+ mx.polyvec_tomont(slot0, k);
167
+ // (c) ĉ ← NTT(c), single polynomial in place.
168
+ mx.ntt(polySlot1);
169
+ // (d) Â · ẑ → slot3 (regular form in NTT domain)
170
+ mx.polyvec_matrix_pointwise_montgomery(slot3, matOff, slot1, k, l);
171
+ // (e) ĉ · t̂₁·2^d → slot4, TS-side per-poly loop; ĉ regular, t̂₁·2^d
172
+ // tomont so the kernel's R⁻¹ leaves the result regular.
173
+ for (let r = 0; r < k; r++) {
174
+ mx.poly_pointwise_montgomery(slot4 + r * POLY_BYTES, polySlot1, slot0 + r * POLY_BYTES);
175
+ }
176
+ // (f) w'_approx (NTT domain) ← ·ẑ − ĉ·t̂₁·2^d
177
+ mx.polyvec_sub(slot3, slot3, slot4, k);
178
+ mx.polyvec_invntt(slot3, k);
179
+ mx.polyvec_caddq(slot3, k); // canonical for use_hint
180
+ // ── Step (Alg 8 line 9) w'₁ ← UseHint(h, w'_approx) ─────────────
181
+ // use_hint is alias-safe between r and a (read both before write
182
+ // per coefficient), so overwrite w'_approx with w'₁ in slot3.
183
+ mx.polyvec_use_hint(slot3, slot2, slot3, k, gamma2);
184
+ // ── Step (Alg 8 line 10) c̃' ← H(μ ‖ w₁Encode(w'₁), λ/4) ─────────
185
+ for (let r = 0; r < k; r++) {
186
+ mx.simple_bit_pack(xofOff + r * w1PolyBytes, slot3 + r * POLY_BYTES, w1Bitlen);
187
+ }
188
+ w1Bytes = mlMem.slice(xofOff, xofOff + w1TotalBytes);
189
+ cTildeNew = shake256HashConcat(sx, [mu, w1Bytes], lambdaOver4);
190
+ // ── Step (Alg 8 line 11) return ‖z‖∞ < γ₁ − β AND c̃ = c̃' ───────
191
+ // The sigDecode bit_unpack output is in centered residues
192
+ // [-(γ₁-1), γ₁], chknorm consumes that form directly without
193
+ // polyvec_reduce. We must check norm AFTER the NTT path because
194
+ // our slot1 holds NTT-domain ẑ now. Re-decode z into a fresh slot
195
+ // for the norm check.
196
+ //
197
+ // Re-decode is cheap (bit_unpack is a single-pass kernel). Use
198
+ // slot4 (already overwritten above) as the destination.
199
+ off = lambdaOver4;
200
+ for (let r = 0; r < l; r++) {
201
+ mlMem.set(sig.subarray(off, off + zPolyBytes), xofOff);
202
+ mx.bit_unpack(slot4 + r * POLY_BYTES, xofOff, gamma1 - 1, gamma1);
203
+ off += zPolyBytes;
204
+ }
205
+ const normFail = mx.polyvec_chknorm(slot4, gamma1 - beta, l);
206
+ // Constant-time comparison via the SIMD ct WASM module. We
207
+ // evaluate normFail and the c̃ comparison both before returning,
208
+ // so that an attacker who can observe timing cannot distinguish
209
+ // "norm failed" from "c̃ mismatch", both run to completion before
210
+ // the boolean reduction. (The c̃ != c̃' branch is taken regardless
211
+ // of normFail; both signals are public-input-derived so this is
212
+ // not a CT requirement, but it preserves the symmetry.)
213
+ const cTildeEq = constantTimeEqual(cTilde, cTildeNew);
214
+ return normFail === 0 && cTildeEq;
215
+ }
216
+ catch {
217
+ // FIPS 204 verify is a pure predicate. Any unexpected exception
218
+ // (out-of-memory, kernel argument errors) is treated as "did not
219
+ // authenticate", never propagate. The SUF-CMA risk of swallowing
220
+ // is bounded by validate*.ts callers: the ones that throw on
221
+ // caller contract violations (oversize ctx) run BEFORE this
222
+ // function executes.
223
+ return false;
224
+ }
225
+ finally {
226
+ // Wipe TS-side scratch.
227
+ if (mu)
228
+ wipe(mu);
229
+ if (tr)
230
+ wipe(tr);
231
+ if (cTilde)
232
+ wipe(cTilde);
233
+ if (cTildeNew)
234
+ wipe(cTildeNew);
235
+ if (w1Bytes)
236
+ wipe(w1Bytes);
237
+ // Wipe WASM scratch, verify operates on public inputs (vk, sig,
238
+ // M, ctx all public; t₁, ẑ, w'_approx, h all public-derivable),
239
+ // but the discipline mirrors sign for review consistency. Cheap.
240
+ mlMem.fill(0, mx.getPolyvecSlotBase(), mx.getPolyvecSlotBase() + 5 * mx.getPolyvecSlotSize());
241
+ mlMem.fill(0, polySlotBase, polySlotBase + 8 * POLY_BYTES);
242
+ mlMem.fill(0, xofOff, xofOff + 8192);
243
+ // SHA3 module: wipe state across op boundary, same convention as
244
+ // keygen / sign. Holds vk (public), tr (public), μ (public-derivable).
245
+ sx.wipeBuffers();
246
+ }
247
+ }
248
+ /**
249
+ * HashML-DSA verify, post-prehash. FIPS 204 §5.4 Algorithm 5 lines 17-19.
250
+ * Builds M' = 0x01 ‖ |ctx| ‖ ctx ‖ OID(algo) ‖ prehash and drives
251
+ * Verify_internal.
252
+ *
253
+ * Same return / throw posture as `mldsaVerifyInternal`: returns a pure
254
+ * boolean for every signature outcome. Caller (in index.ts) is expected
255
+ * to have already filtered wrong-length vk / sig / digest with the
256
+ * appropriate verdict (false) before calling this helper.
257
+ *
258
+ * The caller owns `prehash`; this helper never wipes it.
259
+ */
260
+ export function verifyWithPrehash(mx, sx, params, vk, prehash, sig, algo, ctx) {
261
+ const oid = getOid(algo);
262
+ const MPrime = constructMPrimeHash(ctx, oid, prehash);
263
+ try {
264
+ return mldsaVerifyInternal(mx, sx, params, vk, MPrime, sig);
265
+ }
266
+ finally {
267
+ wipe(MPrime);
268
+ }
269
+ }
Binary file
@@ -0,0 +1 @@
1
+ export { WASM_GZ_BASE64 as mlkemWasm } from '../embedded/mlkem.js';
@@ -0,0 +1,27 @@
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/mlkem/embedded.ts
23
+ //
24
+ // Exports the gzip+base64 ML-KEM WASM blob for use as a WasmSource.
25
+ // This is the only file in the mlkem subpath that references the embedded blob.
26
+ // Import via `leviathan-crypto/mlkem/embedded`.
27
+ export { WASM_GZ_BASE64 as mlkemWasm } from '../embedded/mlkem.js';
@@ -0,0 +1,49 @@
1
+ import type { MlKemExports, Sha3Exports } from './types.js';
2
+ import type { MlKemParams } from './params.js';
3
+ /** SHA3-512(msg) → 64 bytes. Resets sha3 state. */
4
+ export declare function sha3_512Hash(sx: Sha3Exports, msg: Uint8Array): Uint8Array;
5
+ /** SHA3-256(msg) → 32 bytes. Resets sha3 state. */
6
+ export declare function sha3_256Hash(sx: Sha3Exports, msg: Uint8Array): Uint8Array;
7
+ /**
8
+ * SHAKE256(msg, n) → n bytes. Resets sha3 state.
9
+ * Used for J function (z || c) and PRF seeding in kem.ts.
10
+ */
11
+ export declare function shake256Hash(sx: Sha3Exports, msg: Uint8Array, n: number): Uint8Array;
12
+ /**
13
+ * K-PKE.KeyGen (FIPS 203 Algorithm 12), deterministic.
14
+ *
15
+ * Slot map:
16
+ * pvec0, current row of  (overwritten per row)
17
+ * pvec1, ŝ (noise, persistent through dot products)
18
+ * pvec2, ê (noise)
19
+ * pvec3, t̂ = ·ŝ + ê (output)
20
+ */
21
+ export declare function indcpaKeypairDerand(kx: MlKemExports, sx: Sha3Exports, params: MlKemParams, d: Uint8Array): {
22
+ ekCpa: Uint8Array;
23
+ skCpa: Uint8Array;
24
+ };
25
+ /**
26
+ * K-PKE.Encrypt (FIPS 203 Algorithm 13), deterministic.
27
+ *
28
+ * Slot map:
29
+ * pvec0, current row of Â^T (transposed, overwritten per row)
30
+ * pvec1, r̂ = NTT(r)
31
+ * pvec2, e₁ (noise)
32
+ * pvec3, u = invNTT(Â^T · r̂) + e₁
33
+ * pvec4, t̂ (unpacked from ek)
34
+ * poly1 , e₂ (noise)
35
+ * poly2 , v = invNTT(t̂^T · r̂) + e₂ + msg
36
+ * poly3 , message polynomial
37
+ */
38
+ export declare function indcpaEncrypt(kx: MlKemExports, sx: Sha3Exports, params: MlKemParams, ek: Uint8Array, m: Uint8Array, coins: Uint8Array): Uint8Array;
39
+ /**
40
+ * K-PKE.Decrypt (FIPS 203 Algorithm 14).
41
+ *
42
+ * Slot map:
43
+ * pvec0, û (decompressed from ct)
44
+ * pvec1, ŝ (from sk)
45
+ * poly0 , v (decompressed from ct)
46
+ * poly1 , w = invNTT(ŝ^T · NTT(û))
47
+ * poly2 , m' = v - w
48
+ */
49
+ export declare function indcpaDecrypt(kx: MlKemExports, params: MlKemParams, skCpa: Uint8Array, ct: Uint8Array): Uint8Array;