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,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/x25519/embedded.ts
23
+ //
24
+ // Exports the gzip+base64 curve25519 WASM blob for use as a WasmSource.
25
+ // Ed25519 and X25519 share the same curve25519 WASM binary; both the
26
+ // `leviathan-crypto/ed25519/embedded` and `leviathan-crypto/x25519/embedded`
27
+ // subpaths re-export the same blob under three names: `curve25519Wasm`
28
+ // (canonical), `ed25519Wasm`, and `x25519Wasm` (aliases that read more
29
+ // naturally in the matching subpath context). All three resolve to the
30
+ // identical underlying string; tree-shaking is unaffected.
31
+ export { WASM_GZ_BASE64 as curve25519Wasm, WASM_GZ_BASE64 as x25519Wasm, } from '../embedded/curve25519.js';
@@ -0,0 +1,43 @@
1
+ import { isInitialized } from '../init.js';
2
+ import type { WasmSource } from '../wasm-source.js';
3
+ import type { X25519KeyPair } from './types.js';
4
+ /**
5
+ * Initialise the curve25519 WASM module under the `x25519` alias.
6
+ * Equivalent to `ed25519Init(source)`; both target the same WASM module
7
+ * and the init layer de-dupes when given identical sources.
8
+ */
9
+ export declare function x25519Init(source: WasmSource): Promise<void>;
10
+ export type { WasmSource };
11
+ export type { X25519KeyPair, X25519Exports } from './types.js';
12
+ export { isInitialized };
13
+ export declare class X25519 {
14
+ constructor();
15
+ private get mx();
16
+ /**
17
+ * Deterministic X25519 key generation from a 32-byte secret per
18
+ * RFC 7748 §6. Clamping is applied internally on every WASM call;
19
+ * the returned secretKey is a fresh copy of the supplied sk bytes
20
+ * (NOT pre-clamped).
21
+ */
22
+ keygenDerand(sk: Uint8Array): X25519KeyPair;
23
+ /** Random X25519 key generation, wraps `keygenDerand` with `randomBytes(32)`. */
24
+ keygen(): X25519KeyPair;
25
+ /**
26
+ * X25519 Diffie-Hellman, RFC 7748 §6.
27
+ *
28
+ * Computes the shared u-coordinate from the local secret and the
29
+ * peer's public key. If the resulting shared secret is all-zero
30
+ * (peer public key is a small-order point per RFC 7748 §7), throws
31
+ * `KeyAgreementError` rather than returning the degenerate value.
32
+ * The all-zero scan accumulates via OR across all 32 output bytes
33
+ * before comparing to zero, so the success path is constant-time;
34
+ * the throw branches off only after a known-bad outcome is observed.
35
+ *
36
+ * @param sk 32-byte local secret (NOT pre-clamped, clamped internally)
37
+ * @param peerPk 32-byte peer public key (u-coordinate)
38
+ * @returns 32-byte shared u-coordinate
39
+ * @throws KeyAgreementError on all-zero shared secret
40
+ */
41
+ dh(sk: Uint8Array, peerPk: Uint8Array): Uint8Array;
42
+ dispose(): void;
43
+ }
@@ -0,0 +1,159 @@
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/x25519/index.ts
23
+ //
24
+ // X25519 public API. RFC 7748 §5 (algorithm), §6 (keygen + DH), §7
25
+ // (security considerations and the small-order peer-pk rejection that
26
+ // motivates the TS-layer all-zero shared-secret check).
27
+ //
28
+ // Both Ed25519 and X25519 share the curve25519 WASM module;
29
+ // `ed25519Init(source)` and `x25519Init(source)` both target it and the
30
+ // init() layer de-dupes when given identical sources.
31
+ //
32
+ // Per-call lifecycle mirrors the Ed25519 wrapper: stage caller inputs
33
+ // at fixed offsets above the WASM mutable buffer region, call the
34
+ // underlying export, copy outputs to fresh `Uint8Array`s, wipe both
35
+ // the WASM-internal scratch and the TS-side I/O staging region.
36
+ import { getInstance, initModule, isInitialized, _assertNotOwned } from '../init.js';
37
+ import { randomBytes, wipe } from '../utils.js';
38
+ import { KeyAgreementError } from '../errors.js';
39
+ import { validateSecretKey, validatePublicKey } from './validate.js';
40
+ /**
41
+ * Initialise the curve25519 WASM module under the `x25519` alias.
42
+ * Equivalent to `ed25519Init(source)`; both target the same WASM module
43
+ * and the init layer de-dupes when given identical sources.
44
+ */
45
+ export async function x25519Init(source) {
46
+ return initModule('curve25519', source);
47
+ }
48
+ export { isInitialized };
49
+ // ── I/O staging layout ─────────────────────────────────────────────────────
50
+ //
51
+ // Same base as the ed25519 wrapper, fixed offsets above the WASM mutable
52
+ // buffer region (BUFFER_END = 7836). Two 32-byte input slots plus one
53
+ // 32-byte output slot, no large variable region.
54
+ const IO_BASE = 8192;
55
+ const SK_STAGE = IO_BASE; // 32 bytes
56
+ const PK_STAGE = IO_BASE + 32; // 32 bytes
57
+ const PEER_STAGE = IO_BASE + 64; // 32 bytes
58
+ const SHARED_STAGE = IO_BASE + 96; // 32 bytes
59
+ function ioWipe(mx) {
60
+ // Zero the entire TS-managed staging region. wipeBuffers covers
61
+ // MUTABLE_START..BUFFER_END only; the I/O slots above must be
62
+ // scrubbed at the wrapper layer.
63
+ new Uint8Array(mx.memory.buffer).fill(0, IO_BASE, mx.memory.buffer.byteLength);
64
+ }
65
+ export class X25519 {
66
+ constructor() {
67
+ if (!isInitialized('curve25519'))
68
+ throw new Error('leviathan-crypto: call init({ x25519: ... }) before using X25519');
69
+ }
70
+ get mx() {
71
+ return getInstance('curve25519').exports;
72
+ }
73
+ /**
74
+ * Deterministic X25519 key generation from a 32-byte secret per
75
+ * RFC 7748 §6. Clamping is applied internally on every WASM call;
76
+ * the returned secretKey is a fresh copy of the supplied sk bytes
77
+ * (NOT pre-clamped).
78
+ */
79
+ keygenDerand(sk) {
80
+ _assertNotOwned('curve25519');
81
+ validateSecretKey(sk);
82
+ const mx = this.mx;
83
+ const mem = new Uint8Array(mx.memory.buffer);
84
+ mem.set(sk, SK_STAGE);
85
+ try {
86
+ mx.x25519Keygen(SK_STAGE, PK_STAGE);
87
+ const publicKey = mem.slice(PK_STAGE, PK_STAGE + 32);
88
+ const secretKey = new Uint8Array(32);
89
+ secretKey.set(sk);
90
+ return { publicKey, secretKey };
91
+ }
92
+ finally {
93
+ ioWipe(mx);
94
+ mx.wipeBuffers();
95
+ }
96
+ }
97
+ /** Random X25519 key generation, wraps `keygenDerand` with `randomBytes(32)`. */
98
+ keygen() {
99
+ const sk = randomBytes(32);
100
+ try {
101
+ return this.keygenDerand(sk);
102
+ }
103
+ finally {
104
+ wipe(sk);
105
+ }
106
+ }
107
+ /**
108
+ * X25519 Diffie-Hellman, RFC 7748 §6.
109
+ *
110
+ * Computes the shared u-coordinate from the local secret and the
111
+ * peer's public key. If the resulting shared secret is all-zero
112
+ * (peer public key is a small-order point per RFC 7748 §7), throws
113
+ * `KeyAgreementError` rather than returning the degenerate value.
114
+ * The all-zero scan accumulates via OR across all 32 output bytes
115
+ * before comparing to zero, so the success path is constant-time;
116
+ * the throw branches off only after a known-bad outcome is observed.
117
+ *
118
+ * @param sk 32-byte local secret (NOT pre-clamped, clamped internally)
119
+ * @param peerPk 32-byte peer public key (u-coordinate)
120
+ * @returns 32-byte shared u-coordinate
121
+ * @throws KeyAgreementError on all-zero shared secret
122
+ */
123
+ dh(sk, peerPk) {
124
+ _assertNotOwned('curve25519');
125
+ validateSecretKey(sk);
126
+ validatePublicKey(peerPk);
127
+ const mx = this.mx;
128
+ const mem = new Uint8Array(mx.memory.buffer);
129
+ mem.set(sk, SK_STAGE);
130
+ mem.set(peerPk, PEER_STAGE);
131
+ try {
132
+ mx.x25519DH(SK_STAGE, PEER_STAGE, SHARED_STAGE);
133
+ const shared = mem.slice(SHARED_STAGE, SHARED_STAGE + 32);
134
+ // Constant-time OR-accumulate scan, RFC 7748 §6.1
135
+ // contributory-behaviour requirement. No early exit on the
136
+ // first non-zero byte.
137
+ let acc = 0;
138
+ for (let i = 0; i < 32; i++)
139
+ acc |= shared[i];
140
+ if (acc === 0) {
141
+ wipe(shared);
142
+ throw new KeyAgreementError('leviathan-crypto: X25519 shared secret is all-zero '
143
+ + '(peer public key is a small-order point)');
144
+ }
145
+ return shared;
146
+ }
147
+ finally {
148
+ ioWipe(mx);
149
+ mx.wipeBuffers();
150
+ }
151
+ }
152
+ dispose() {
153
+ try {
154
+ this.mx.wipeBuffers();
155
+ ioWipe(this.mx);
156
+ }
157
+ catch { /* idempotent */ }
158
+ }
159
+ }
@@ -0,0 +1,25 @@
1
+ export interface X25519KeyPair {
2
+ /** 32-byte public u-coordinate. */
3
+ publicKey: Uint8Array;
4
+ /**
5
+ * 32-byte secret. Per RFC 7748 §5 / §6 this is "any 32 random bytes";
6
+ * clamping is applied internally on every WASM call. The stored
7
+ * secretKey is the unclamped form so that round-tripping through
8
+ * keygen / external storage preserves byte-equality.
9
+ */
10
+ secretKey: Uint8Array;
11
+ }
12
+ /**
13
+ * The X25519-relevant subset of the curve25519 WASM exports. The
14
+ * curve25519 module is shared between Ed25519 and X25519; this interface
15
+ * deliberately surfaces only the X25519 high-level entry points plus the
16
+ * layout / wipe primitives.
17
+ */
18
+ export interface X25519Exports {
19
+ memory: WebAssembly.Memory;
20
+ getModuleId: () => number;
21
+ getMemoryPages: () => number;
22
+ x25519Keygen: (skOff: number, pkOff: number) => void;
23
+ x25519DH: (skOff: number, peerPkOff: number, sharedOff: number) => void;
24
+ wipeBuffers: () => void;
25
+ }
@@ -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/x25519/types.ts
23
+ //
24
+ // X25519 type surface: the WASM export interface for the curve25519
25
+ // module (X25519-relevant subset) and the public key-pair shape returned
26
+ // by keygen / keygenDerand. RFC 7748 §5 / §6.
27
+ export {};
@@ -0,0 +1,2 @@
1
+ export declare function validateSecretKey(sk: Uint8Array): void;
2
+ export declare function validatePublicKey(pk: Uint8Array): void;
@@ -0,0 +1,39 @@
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/x25519/validate.ts
23
+ //
24
+ // X25519 caller-side input validation. Pure length / type checks. Peer
25
+ // public-key masking happens inside the WASM (feFromBytes masks bit 255
26
+ // per RFC 7748 §5); the all-zero shared-secret rejection happens in the
27
+ // TS X25519.dh method after the WASM returns.
28
+ export function validateSecretKey(sk) {
29
+ if (!(sk instanceof Uint8Array))
30
+ throw new TypeError('leviathan-crypto: x25519 secret key must be a Uint8Array');
31
+ if (sk.length !== 32)
32
+ throw new RangeError(`leviathan-crypto: x25519 secret key must be 32 bytes (got ${sk.length})`);
33
+ }
34
+ export function validatePublicKey(pk) {
35
+ if (!(pk instanceof Uint8Array))
36
+ throw new TypeError('leviathan-crypto: x25519 public key must be a Uint8Array');
37
+ if (pk.length !== 32)
38
+ throw new RangeError(`leviathan-crypto: x25519 public key must be 32 bytes (got ${pk.length})`);
39
+ }
package/package.json CHANGED
@@ -1,9 +1,17 @@
1
1
  {
2
2
  "name": "leviathan-crypto",
3
- "version": "2.1.0",
4
- "author": "xero (https://x-e.ro)",
3
+ "version": "3.0.0",
5
4
  "license": "MIT",
6
- "description": "Post-quantum WASM cryptography with paranoid ciphers (Serpent-256, XChaCha20-Poly1305), ML-KEM, and forward-secret ratcheting. Zero dependencies. Constant-time verified and strictly typed.",
5
+ "description": "Paranoid post-quantum WASM cryptography library with bitsliced ciphers (Serpent, XChaCha20, AES), ML-KEM, lattice and hash-based signatures (ML-DSA, SLH-DSA, hybrid composites), hashing (SHA-2, SHA-3, BLAKE3), forward-secret ratchet, and Fortuna CSPRNG. Zero dependencies, tree-shakeable, and side-effect-free.",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/xero/leviathan-crypto.git"
9
+ },
10
+ "bugs": {
11
+ "url": "https://github.com/xero/leviathan-crypto/issues"
12
+ },
13
+ "homepage": "https://leviathan.3xi.club",
14
+ "author": "xero (https://x-e.ro)",
7
15
  "type": "module",
8
16
  "sideEffects": false,
9
17
  "exports": {
@@ -19,24 +27,31 @@
19
27
  "./sha3/embedded": "./dist/sha3/embedded.js",
20
28
  "./keccak": "./dist/keccak/index.js",
21
29
  "./keccak/embedded": "./dist/keccak/embedded.js",
22
- "./kyber": "./dist/kyber/index.js",
23
- "./kyber/embedded": "./dist/kyber/embedded.js",
24
- "./ratchet": "./dist/ratchet/index.js"
30
+ "./mlkem": "./dist/mlkem/index.js",
31
+ "./mlkem/embedded": "./dist/mlkem/embedded.js",
32
+ "./aes": "./dist/aes/index.js",
33
+ "./aes/embedded": "./dist/aes/embedded.js",
34
+ "./blake3": "./dist/blake3/index.js",
35
+ "./blake3/embedded": "./dist/blake3/embedded.js",
36
+ "./ecdsa": "./dist/ecdsa/index.js",
37
+ "./ecdsa/embedded": "./dist/ecdsa/embedded.js",
38
+ "./ed25519": "./dist/ed25519/index.js",
39
+ "./ed25519/embedded": "./dist/ed25519/embedded.js",
40
+ "./mldsa": "./dist/mldsa/index.js",
41
+ "./mldsa/embedded": "./dist/mldsa/embedded.js",
42
+ "./slhdsa": "./dist/slhdsa/index.js",
43
+ "./slhdsa/embedded": "./dist/slhdsa/embedded.js",
44
+ "./x25519": "./dist/x25519/index.js",
45
+ "./x25519/embedded": "./dist/x25519/embedded.js",
46
+ "./ratchet": "./dist/ratchet/index.js",
47
+ "./sign": "./dist/sign/index.js",
48
+ "./merkle": "./dist/merkle/index.js"
25
49
  },
26
50
  "types": "./dist/index.d.ts",
27
51
  "files": [
28
52
  "dist",
29
- "SECURITY.md",
30
53
  "CLAUDE.md"
31
54
  ],
32
- "repository": {
33
- "type": "git",
34
- "url": "git+https://github.com/xero/leviathan-crypto.git"
35
- },
36
- "homepage": "https://leviathan.3xi.club",
37
- "bugs": {
38
- "url": "https://github.com/xero/leviathan-crypto/issues"
39
- },
40
55
  "keywords": [
41
56
  "cryptography",
42
57
  "encryption",
@@ -44,38 +59,67 @@
44
59
  "typescript",
45
60
  "wasm",
46
61
  "webassembly",
62
+ "simd",
63
+ "isomorphic",
47
64
  "zero-dependency",
48
65
  "constant-time",
66
+ "bitsliced",
49
67
  "side-channel",
68
+ "post-quantum",
69
+ "pqc",
70
+ "hybrid",
71
+ "aead",
72
+ "kem",
73
+ "key-encapsulation",
74
+ "signing",
75
+ "signature",
76
+ "hashing",
77
+ "cipher",
50
78
  "serpent",
51
79
  "serpent-256",
52
- "cipher",
53
- "aead",
54
80
  "chacha20",
55
81
  "xchacha20",
56
82
  "poly1305",
57
83
  "xchacha20-poly1305",
84
+ "aes",
85
+ "aes-256",
86
+ "aes-gcm-siv",
58
87
  "kyber",
59
88
  "ml-kem",
60
89
  "mlkem",
61
- "pqc",
62
- "post-quantum",
63
- "key-encapsulation",
64
- "kem",
65
- "double-ratchet",
66
- "ratchet",
67
- "forward-secrecy",
68
- "spqr",
90
+ "ml-dsa",
91
+ "mldsa",
92
+ "slh-dsa",
93
+ "slhdsa",
94
+ "ed25519",
95
+ "x25519",
96
+ "ecdsa",
97
+ "ecdsa-p256",
98
+ "p256",
99
+ "prime256v1",
100
+ "secp256r1",
69
101
  "sha",
70
102
  "sha-256",
71
103
  "sha-512",
72
104
  "sha-3",
73
105
  "keccak",
74
106
  "shake",
107
+ "cshake",
108
+ "blake3",
75
109
  "hmac",
110
+ "kmac",
76
111
  "hkdf",
112
+ "argon2",
113
+ "argon2id",
77
114
  "fortuna",
78
115
  "csprng",
79
- "entropy"
116
+ "entropy",
117
+ "double-ratchet",
118
+ "ratchet",
119
+ "forward-secrecy",
120
+ "spqr",
121
+ "merkle",
122
+ "merkle-tree",
123
+ "transparency-log"
80
124
  ]
81
125
  }