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.
- package/CLAUDE.md +86 -443
- package/README.md +198 -65
- package/dist/aes/aes-cbc.d.ts +40 -0
- package/dist/aes/aes-cbc.js +158 -0
- package/dist/aes/aes-ctr.d.ts +50 -0
- package/dist/aes/aes-ctr.js +141 -0
- package/dist/aes/aes-gcm-siv.d.ts +67 -0
- package/dist/aes/aes-gcm-siv.js +217 -0
- package/dist/aes/aes-gcm.d.ts +61 -0
- package/dist/aes/aes-gcm.js +226 -0
- package/dist/aes/cipher-suite.d.ts +21 -0
- package/dist/aes/cipher-suite.js +179 -0
- package/dist/aes/embedded.d.ts +1 -0
- package/dist/aes/embedded.js +26 -0
- package/dist/aes/generator.d.ts +14 -0
- package/dist/aes/generator.js +103 -0
- package/dist/aes/index.d.ts +58 -0
- package/dist/aes/index.js +125 -0
- package/dist/aes/ops.d.ts +60 -0
- package/dist/aes/ops.js +164 -0
- package/dist/aes/pool-worker.d.ts +1 -0
- package/dist/aes/pool-worker.js +92 -0
- package/dist/aes/types.d.ts +1 -0
- package/dist/aes/types.js +23 -0
- package/dist/aes.wasm +0 -0
- package/dist/blake3/embedded.d.ts +1 -0
- package/dist/blake3/embedded.js +26 -0
- package/dist/blake3/index.d.ts +143 -0
- package/dist/blake3/index.js +620 -0
- package/dist/blake3/types.d.ts +102 -0
- package/dist/blake3/types.js +31 -0
- package/dist/blake3/validate.d.ts +29 -0
- package/dist/blake3/validate.js +80 -0
- package/dist/blake3.wasm +0 -0
- package/dist/chacha20/cipher-suite.js +47 -25
- package/dist/chacha20/generator.d.ts +2 -2
- package/dist/chacha20/generator.js +4 -4
- package/dist/chacha20/index.d.ts +16 -15
- package/dist/chacha20/index.js +52 -46
- package/dist/chacha20/ops.d.ts +7 -7
- package/dist/chacha20/ops.js +34 -34
- package/dist/chacha20/pool-worker.js +5 -3
- package/dist/cte-wasm.d.ts +1 -0
- package/dist/cte-wasm.js +3 -0
- package/dist/curve25519.wasm +0 -0
- package/dist/ecdsa/der.d.ts +23 -0
- package/dist/ecdsa/der.js +192 -0
- package/dist/ecdsa/ecprivatekey-der.d.ts +32 -0
- package/dist/ecdsa/ecprivatekey-der.js +230 -0
- package/dist/ecdsa/embedded.d.ts +1 -0
- package/dist/ecdsa/embedded.js +25 -0
- package/dist/ecdsa/index.d.ts +124 -0
- package/dist/ecdsa/index.js +366 -0
- package/dist/ecdsa/types.d.ts +31 -0
- package/dist/ecdsa/types.js +28 -0
- package/dist/ecdsa/validate.d.ts +18 -0
- package/dist/ecdsa/validate.js +92 -0
- package/dist/ed25519/embedded.d.ts +1 -0
- package/dist/ed25519/embedded.js +31 -0
- package/dist/ed25519/index.d.ts +70 -0
- package/dist/ed25519/index.js +308 -0
- package/dist/ed25519/types.d.ts +27 -0
- package/dist/ed25519/types.js +27 -0
- package/dist/ed25519/validate.d.ts +7 -0
- package/dist/ed25519/validate.js +77 -0
- package/dist/embedded/aes-pool-worker.d.ts +1 -0
- package/dist/embedded/aes-pool-worker.js +5 -0
- package/dist/embedded/aes.d.ts +1 -0
- package/dist/embedded/aes.js +3 -0
- package/dist/embedded/blake3.d.ts +1 -0
- package/dist/embedded/blake3.js +3 -0
- package/dist/embedded/chacha20-pool-worker.d.ts +1 -1
- package/dist/embedded/chacha20-pool-worker.js +2 -2
- package/dist/embedded/chacha20.d.ts +1 -1
- package/dist/embedded/chacha20.js +2 -2
- package/dist/embedded/curve25519.d.ts +1 -0
- package/dist/embedded/curve25519.js +3 -0
- package/dist/embedded/mldsa.d.ts +1 -0
- package/dist/embedded/mldsa.js +3 -0
- package/dist/embedded/mlkem.d.ts +1 -0
- package/dist/embedded/mlkem.js +3 -0
- package/dist/embedded/p256.d.ts +1 -0
- package/dist/embedded/p256.js +3 -0
- package/dist/embedded/serpent-pool-worker.d.ts +1 -1
- package/dist/embedded/serpent-pool-worker.js +2 -2
- package/dist/embedded/serpent.d.ts +1 -1
- package/dist/embedded/serpent.js +2 -2
- package/dist/embedded/sha2.d.ts +1 -1
- package/dist/embedded/sha2.js +2 -2
- package/dist/embedded/sha3.d.ts +1 -1
- package/dist/embedded/sha3.js +2 -2
- package/dist/embedded/slhdsa.d.ts +1 -0
- package/dist/embedded/slhdsa.js +3 -0
- package/dist/errors.d.ts +92 -1
- package/dist/errors.js +111 -1
- package/dist/fortuna.d.ts +5 -5
- package/dist/fortuna.js +37 -64
- package/dist/index.d.ts +38 -9
- package/dist/index.js +63 -19
- package/dist/init.d.ts +1 -1
- package/dist/init.js +11 -25
- package/dist/keccak/embedded.js +1 -1
- package/dist/keccak/index.d.ts +2 -0
- package/dist/keccak/index.js +4 -2
- package/dist/loader.d.ts +1 -24
- package/dist/loader.js +13 -16
- package/dist/merkle/blake3-tree.d.ts +35 -0
- package/dist/merkle/blake3-tree.js +187 -0
- package/dist/merkle/checkpoint.d.ts +58 -0
- package/dist/merkle/checkpoint.js +217 -0
- package/dist/merkle/index.d.ts +19 -0
- package/dist/merkle/index.js +37 -0
- package/dist/merkle/merkle-log.d.ts +130 -0
- package/dist/merkle/merkle-log.js +207 -0
- package/dist/merkle/merkle-verifier.d.ts +126 -0
- package/dist/merkle/merkle-verifier.js +296 -0
- package/dist/merkle/proof.d.ts +70 -0
- package/dist/merkle/proof.js +300 -0
- package/dist/merkle/sha256-tree.d.ts +33 -0
- package/dist/merkle/sha256-tree.js +145 -0
- package/dist/merkle/signed-log.d.ts +156 -0
- package/dist/merkle/signed-log.js +356 -0
- package/dist/merkle/signed-note.d.ts +309 -0
- package/dist/merkle/signed-note.js +648 -0
- package/dist/merkle/sth.d.ts +31 -0
- package/dist/merkle/sth.js +31 -0
- package/dist/merkle/storage.d.ts +40 -0
- package/dist/merkle/storage.js +71 -0
- package/dist/merkle/tree.d.ts +68 -0
- package/dist/merkle/tree.js +94 -0
- package/dist/mldsa/embedded.d.ts +1 -0
- package/dist/{kyber → mldsa}/embedded.js +5 -5
- package/dist/mldsa/expand.d.ts +53 -0
- package/dist/mldsa/expand.js +188 -0
- package/dist/mldsa/format.d.ts +16 -0
- package/dist/mldsa/format.js +68 -0
- package/dist/mldsa/hashvariant.d.ts +32 -0
- package/dist/mldsa/hashvariant.js +248 -0
- package/dist/mldsa/index.d.ts +142 -0
- package/dist/mldsa/index.js +463 -0
- package/dist/mldsa/keygen.d.ts +16 -0
- package/dist/mldsa/keygen.js +232 -0
- package/dist/mldsa/params.d.ts +21 -0
- package/dist/mldsa/params.js +55 -0
- package/dist/mldsa/sha3-helpers.d.ts +30 -0
- package/dist/mldsa/sha3-helpers.js +124 -0
- package/dist/mldsa/sign.d.ts +36 -0
- package/dist/mldsa/sign.js +380 -0
- package/dist/mldsa/types.d.ts +91 -0
- package/dist/mldsa/types.js +25 -0
- package/dist/mldsa/validate.d.ts +55 -0
- package/dist/mldsa/validate.js +125 -0
- package/dist/mldsa/verify.d.ts +29 -0
- package/dist/mldsa/verify.js +269 -0
- package/dist/mldsa.wasm +0 -0
- package/dist/mlkem/embedded.d.ts +1 -0
- package/dist/mlkem/embedded.js +27 -0
- package/dist/mlkem/indcpa.d.ts +49 -0
- package/dist/{kyber → mlkem}/indcpa.js +44 -44
- package/dist/mlkem/index.d.ts +37 -0
- package/dist/{kyber → mlkem}/index.js +24 -34
- package/dist/mlkem/kem.d.ts +21 -0
- package/dist/{kyber → mlkem}/kem.js +44 -64
- package/dist/{kyber → mlkem}/params.d.ts +4 -4
- package/dist/{kyber → mlkem}/params.js +2 -2
- package/dist/mlkem/suite.d.ts +12 -0
- package/dist/{kyber → mlkem}/suite.js +17 -12
- package/dist/{kyber → mlkem}/types.d.ts +3 -3
- package/dist/{kyber → mlkem}/types.js +1 -1
- package/dist/{kyber → mlkem}/validate.d.ts +7 -7
- package/dist/{kyber → mlkem}/validate.js +7 -7
- package/dist/{kyber.wasm → mlkem.wasm} +0 -0
- package/dist/p256.wasm +0 -0
- package/dist/ratchet/index.d.ts +2 -0
- package/dist/ratchet/index.js +1 -0
- package/dist/ratchet/kdf-chain.js +3 -3
- package/dist/ratchet/ratchet-keypair.js +2 -2
- package/dist/ratchet/root-kdf.js +7 -7
- package/dist/ratchet/skipped-key-store.js +4 -4
- package/dist/ratchet/types.d.ts +1 -1
- package/dist/serpent/cipher-suite.js +20 -17
- package/dist/serpent/generator.d.ts +1 -1
- package/dist/serpent/generator.js +2 -2
- package/dist/serpent/index.d.ts +8 -7
- package/dist/serpent/index.js +18 -27
- package/dist/serpent/pool-worker.js +7 -5
- package/dist/serpent/serpent-cbc.d.ts +4 -4
- package/dist/serpent/serpent-cbc.js +11 -8
- package/dist/serpent/shared-ops.d.ts +3 -23
- package/dist/serpent/shared-ops.js +50 -85
- package/dist/serpent.wasm +0 -0
- package/dist/sha2/hkdf.js +5 -5
- package/dist/sha2/index.d.ts +21 -1
- package/dist/sha2/index.js +65 -10
- package/dist/sha2/types.d.ts +41 -2
- package/dist/sha2.wasm +0 -0
- package/dist/sha3/index.d.ts +72 -3
- package/dist/sha3/index.js +240 -14
- package/dist/sha3/kmac.d.ts +121 -0
- package/dist/sha3/kmac.js +800 -0
- package/dist/sha3.wasm +0 -0
- package/dist/shared/pkcs7.d.ts +22 -0
- package/dist/shared/pkcs7.js +84 -0
- package/dist/sign/ctx.d.ts +41 -0
- package/dist/sign/ctx.js +102 -0
- package/dist/sign/envelope.d.ts +45 -0
- package/dist/sign/envelope.js +152 -0
- package/dist/sign/hasher.d.ts +9 -0
- package/dist/sign/hasher.js +132 -0
- package/dist/sign/index.d.ts +11 -0
- package/dist/sign/index.js +34 -0
- package/dist/sign/sign-stream.d.ts +25 -0
- package/dist/sign/sign-stream.js +112 -0
- package/dist/sign/suites/ecdsa-p256.d.ts +2 -0
- package/dist/sign/suites/ecdsa-p256.js +120 -0
- package/dist/sign/suites/ed25519.d.ts +3 -0
- package/dist/sign/suites/ed25519.js +165 -0
- package/dist/sign/suites/hybrid-classical.d.ts +23 -0
- package/dist/sign/suites/hybrid-classical.js +526 -0
- package/dist/sign/suites/hybrid-pq.d.ts +4 -0
- package/dist/sign/suites/hybrid-pq.js +234 -0
- package/dist/sign/suites/mldsa.d.ts +7 -0
- package/dist/sign/suites/mldsa.js +161 -0
- package/dist/sign/suites/slhdsa.d.ts +7 -0
- package/dist/sign/suites/slhdsa.js +176 -0
- package/dist/sign/types.d.ts +106 -0
- package/dist/sign/types.js +28 -0
- package/dist/sign/verify-stream.d.ts +30 -0
- package/dist/sign/verify-stream.js +227 -0
- package/dist/slhdsa/embedded.d.ts +1 -0
- package/dist/slhdsa/embedded.js +26 -0
- package/dist/slhdsa/index.d.ts +149 -0
- package/dist/slhdsa/index.js +493 -0
- package/dist/slhdsa/params.d.ts +26 -0
- package/dist/slhdsa/params.js +70 -0
- package/dist/slhdsa/prehash.d.ts +68 -0
- package/dist/slhdsa/prehash.js +307 -0
- package/dist/slhdsa/sign.d.ts +39 -0
- package/dist/slhdsa/sign.js +116 -0
- package/dist/slhdsa/types.d.ts +129 -0
- package/dist/slhdsa/types.js +27 -0
- package/dist/slhdsa/validate.d.ts +60 -0
- package/dist/slhdsa/validate.js +127 -0
- package/dist/slhdsa/verify.d.ts +32 -0
- package/dist/slhdsa/verify.js +107 -0
- package/dist/slhdsa.wasm +0 -0
- package/dist/stream/header.js +3 -3
- package/dist/stream/index.d.ts +1 -0
- package/dist/stream/index.js +1 -0
- package/dist/stream/open-stream.js +31 -10
- package/dist/stream/seal-stream-pool.d.ts +1 -0
- package/dist/stream/seal-stream-pool.js +63 -26
- package/dist/stream/seal-stream.d.ts +1 -1
- package/dist/stream/seal-stream.js +20 -9
- package/dist/stream/seal.js +6 -6
- package/dist/stream/types.d.ts +3 -1
- package/dist/stream/types.js +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -1
- package/dist/utils.d.ts +3 -3
- package/dist/utils.js +46 -54
- package/dist/wasm-source.d.ts +7 -7
- package/dist/wasm-source.js +1 -1
- package/dist/x25519/embedded.d.ts +1 -0
- package/dist/x25519/embedded.js +31 -0
- package/dist/x25519/index.d.ts +43 -0
- package/dist/x25519/index.js +159 -0
- package/dist/x25519/types.d.ts +25 -0
- package/dist/x25519/types.js +27 -0
- package/dist/x25519/validate.d.ts +2 -0
- package/dist/x25519/validate.js +39 -0
- package/package.json +70 -26
- package/SECURITY.md +0 -163
- package/dist/ct-wasm.d.ts +0 -1
- package/dist/ct-wasm.js +0 -3
- package/dist/docs/aead.md +0 -363
- package/dist/docs/architecture.md +0 -1011
- package/dist/docs/argon2id.md +0 -305
- package/dist/docs/chacha20.md +0 -781
- package/dist/docs/exports.md +0 -277
- package/dist/docs/fortuna.md +0 -530
- package/dist/docs/init.md +0 -301
- package/dist/docs/loader.md +0 -256
- package/dist/docs/serpent.md +0 -617
- package/dist/docs/sha2.md +0 -671
- package/dist/docs/sha3.md +0 -612
- package/dist/docs/types.md +0 -416
- package/dist/docs/utils.md +0 -457
- package/dist/embedded/kyber.d.ts +0 -1
- package/dist/embedded/kyber.js +0 -3
- package/dist/kyber/embedded.d.ts +0 -1
- package/dist/kyber/indcpa.d.ts +0 -49
- package/dist/kyber/index.d.ts +0 -38
- package/dist/kyber/kem.d.ts +0 -21
- package/dist/kyber/suite.d.ts +0 -12
- /package/dist/{ct.wasm → cte.wasm} +0 -0
package/dist/docs/utils.md
DELETED
|
@@ -1,457 +0,0 @@
|
|
|
1
|
-
<img src="https://github.com/xero/leviathan-crypto/raw/main/docs/logo.svg" alt="logo" width="120" align="left" margin="10">
|
|
2
|
-
|
|
3
|
-
### Utilities
|
|
4
|
-
|
|
5
|
-
Pure TypeScript utilities that ship alongside the WASM-backed primitives. No `init()` call required; all functions work immediately on import.
|
|
6
|
-
|
|
7
|
-
> ### Table of Contents
|
|
8
|
-
> - [Security Notes](#security-notes)
|
|
9
|
-
> - [API Reference](#api-reference)
|
|
10
|
-
> - [Usage Examples](#usage-examples)
|
|
11
|
-
> - [Error Conditions](#error-conditions)
|
|
12
|
-
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
The module covers encoding (hex, UTF-8, and base64 conversions between strings
|
|
16
|
-
and `Uint8Array`), security (constant-time comparison and secure memory
|
|
17
|
-
wiping), byte manipulation (XOR and concatenation), and random byte generation.
|
|
18
|
-
|
|
19
|
-
## Security Notes
|
|
20
|
-
|
|
21
|
-
**`constantTimeEqual`** runs inside a WASM SIMD module that removes the JS JIT
|
|
22
|
-
compiler from the timing picture. Use this function whenever you compare MACs,
|
|
23
|
-
hashes, authentication tags, or any secret-derived values. Never use `===`,
|
|
24
|
-
`Buffer.equals`, or a manual loop-with-break for security comparisons. Those
|
|
25
|
-
leak timing information that attackers can exploit to recover secrets. Inputs
|
|
26
|
-
are limited to [`CT_MAX_BYTES`](#ct_max_bytes) (32768 bytes) per side.
|
|
27
|
-
|
|
28
|
-
The length check in `constantTimeEqual` is not constant-time, because array
|
|
29
|
-
length is non-secret in all standard protocols. If your use case treats length
|
|
30
|
-
as secret, pad to equal length before comparing.
|
|
31
|
-
|
|
32
|
-
**`wipe`** zeroes a typed array in-place. Call it on keys, plaintext buffers,
|
|
33
|
-
and any other sensitive data as soon as you are done with them. JavaScript's
|
|
34
|
-
garbage collector does not guarantee timely or complete erasure of memory.
|
|
35
|
-
|
|
36
|
-
**`randomBytes`** delegates to `crypto.getRandomValues` (Web Crypto API), which
|
|
37
|
-
is cryptographically secure in all modern browsers and Node.js 19+. It does not
|
|
38
|
-
fall back to `Math.random` or any insecure source.
|
|
39
|
-
|
|
40
|
-
The encoding functions (`hexToBytes`, `bytesToHex`, `utf8ToBytes`,
|
|
41
|
-
`bytesToUtf8`, `base64ToBytes`, `bytesToBase64`) perform no security-sensitive
|
|
42
|
-
operations.
|
|
43
|
-
|
|
44
|
-
---
|
|
45
|
-
|
|
46
|
-
## API Reference
|
|
47
|
-
|
|
48
|
-
### constantTimeEqual
|
|
49
|
-
|
|
50
|
-
```typescript
|
|
51
|
-
constantTimeEqual(a: Uint8Array, b: Uint8Array): boolean
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
Returns `true` if `a` and `b` contain identical bytes. Returns `false`
|
|
55
|
-
immediately if the arrays differ in length (length is non-secret in all
|
|
56
|
-
standard protocols).
|
|
57
|
-
|
|
58
|
-
The comparison runs inside a WASM SIMD module, removing the JS JIT compiler
|
|
59
|
-
from the timing picture. Speculative optimisation and branch prediction inside
|
|
60
|
-
the engine cannot short-circuit the loop. This function requires WebAssembly
|
|
61
|
-
SIMD; on runtimes without SIMD support it throws `Error: leviathan-crypto:
|
|
62
|
-
constantTimeEqual requires WebAssembly SIMD — this runtime does not support it`
|
|
63
|
-
at first call. SIMD has been a baseline feature of all major browsers and
|
|
64
|
-
Node.js 16.4+ since 2021, and the library's symmetric and post-quantum
|
|
65
|
-
primitives require SIMD already; this function tightens that posture
|
|
66
|
-
consistently.
|
|
67
|
-
|
|
68
|
-
The WASM module ORs the two 64-bit lanes of the SIMD accumulator into a scalar,
|
|
69
|
-
then folds it to 0/1 via `~((diff | -diff) >> 63) & 1`. The only remaining
|
|
70
|
-
observable control flow is the outer length check, which operates on non-secret
|
|
71
|
-
input.
|
|
72
|
-
|
|
73
|
-
**Zero-copy design.** The WASM module has no internal staging buffers. The
|
|
74
|
-
wrapper writes `a` into WASM linear memory at offset 0 and `b` immediately
|
|
75
|
-
after at offset `a.length`, then passes those two offsets directly to the
|
|
76
|
-
`compare` function. No data is duplicated inside the WASM binary; the
|
|
77
|
-
comparison reads in-place from the caller-owned positions. This eliminates an
|
|
78
|
-
entire class of residual-data risk: there is no intermediate copy that outlives
|
|
79
|
-
the operation.
|
|
80
|
-
|
|
81
|
-
**Guaranteed memory zeroing.** After every comparison, the wrapper clears both
|
|
82
|
-
input regions via `mem.fill(0, 0, a.length * 2)` inside a `finally` block. The
|
|
83
|
-
wipe runs whether the comparison succeeds, throws, or is interrupted. Sensitive
|
|
84
|
-
material written into WASM linear memory does not persist past the end of the
|
|
85
|
-
call.
|
|
86
|
-
|
|
87
|
-
WASM SIMD JITs do not guarantee cycle-level constant time; the branch-free tail
|
|
88
|
-
is best-effort hardening against branch-prediction side channels. For
|
|
89
|
-
defence-in-depth against timing attacks on tag comparisons, pair this primitive
|
|
90
|
-
with an authenticated construction (`SerpentCipher`, `XChaCha20Cipher`) that
|
|
91
|
-
terminates on mismatch with a generic error message.
|
|
92
|
-
|
|
93
|
-
Maximum input size is [`CT_MAX_BYTES`](#ct_max_bytes) (32768 bytes) per side.
|
|
94
|
-
Throws `RangeError` if either array exceeds this limit.
|
|
95
|
-
|
|
96
|
-
See [asm_ct.md](./asm_ct.md) for the full WASM module reference, including the
|
|
97
|
-
SIMD algorithm, reduction technique, instantiation model, and memory layout.
|
|
98
|
-
|
|
99
|
-
Use this function when working with lower-level unauthenticated primitives or
|
|
100
|
-
building custom authenticated protocols on top of the hashing and KDF APIs.
|
|
101
|
-
Common cases:
|
|
102
|
-
|
|
103
|
-
- **Encrypt-then-MAC with `SerpentCbc` or `SerpentCtr`.** If you use the
|
|
104
|
-
`dangerUnauthenticated` primitive directly and compute your own HMAC-SHA256
|
|
105
|
-
tag, compare that tag with `constantTimeEqual`. See the [example
|
|
106
|
-
below](#encrypt-then-mac-with-serpentcbc).
|
|
107
|
-
- **Argon2id key verification.** When re-deriving an Argon2id hash to verify a
|
|
108
|
-
passphrase, the final comparison must be constant-time. See
|
|
109
|
-
[argon2id.md](./argon2id.md#password-hashing-and-verification) for the full
|
|
110
|
-
example.
|
|
111
|
-
- **Custom HMAC protocols.** Any protocol where you derive a MAC with
|
|
112
|
-
`HMAC_SHA256` or `HMAC_SHA512` and compare it against a received value. See
|
|
113
|
-
[examples.md](./examples.md#hmac-sha256-message-authentication) for a
|
|
114
|
-
complete example.
|
|
115
|
-
|
|
116
|
-
---
|
|
117
|
-
|
|
118
|
-
### CT_MAX_BYTES
|
|
119
|
-
|
|
120
|
-
```typescript
|
|
121
|
-
const CT_MAX_BYTES: 32768
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
Maximum input size accepted by [`constantTimeEqual`](#constanttimeequal) per
|
|
125
|
-
side, in bytes. Reflects the physical layout of the WASM comparison module: one
|
|
126
|
-
64 KiB page of linear memory split equally between the two input buffers (32
|
|
127
|
-
KiB each).
|
|
128
|
-
|
|
129
|
-
In practice the largest comparison performed anywhere in this library is a
|
|
130
|
-
32-byte HMAC-SHA-256 tag. This limit only matters for custom protocols that
|
|
131
|
-
compare unusually large values. Use this constant to guard your own inputs
|
|
132
|
-
rather than hardcoding the magic number:
|
|
133
|
-
|
|
134
|
-
```typescript
|
|
135
|
-
import { constantTimeEqual, CT_MAX_BYTES } from 'leviathan-crypto'
|
|
136
|
-
|
|
137
|
-
if (a.length > CT_MAX_BYTES || b.length > CT_MAX_BYTES) {
|
|
138
|
-
throw new RangeError(`comparison input exceeds CT_MAX_BYTES (${CT_MAX_BYTES})`)
|
|
139
|
-
}
|
|
140
|
-
const match = constantTimeEqual(a, b)
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
---
|
|
144
|
-
|
|
145
|
-
### hexToBytes
|
|
146
|
-
|
|
147
|
-
```typescript
|
|
148
|
-
hexToBytes(hex: string): Uint8Array
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
Converts a hex string to a `Uint8Array`. Accepts lowercase or uppercase
|
|
152
|
-
characters. An optional `0x` or `0X` prefix is stripped automatically. Throws
|
|
153
|
-
`RangeError` on odd-length or non-hex input.
|
|
154
|
-
|
|
155
|
-
---
|
|
156
|
-
|
|
157
|
-
### bytesToHex
|
|
158
|
-
|
|
159
|
-
```typescript
|
|
160
|
-
bytesToHex(bytes: Uint8Array): string
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
Converts a `Uint8Array` to a lowercase hex string (no prefix).
|
|
164
|
-
|
|
165
|
-
---
|
|
166
|
-
|
|
167
|
-
### utf8ToBytes
|
|
168
|
-
|
|
169
|
-
```typescript
|
|
170
|
-
utf8ToBytes(str: string): Uint8Array
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
Encodes a JavaScript string as UTF-8 bytes using the platform `TextEncoder`.
|
|
174
|
-
|
|
175
|
-
---
|
|
176
|
-
|
|
177
|
-
### bytesToUtf8
|
|
178
|
-
|
|
179
|
-
```typescript
|
|
180
|
-
bytesToUtf8(bytes: Uint8Array): string
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
Decodes UTF-8 bytes to a JavaScript string using the platform `TextDecoder`.
|
|
184
|
-
|
|
185
|
-
---
|
|
186
|
-
|
|
187
|
-
### base64ToBytes
|
|
188
|
-
|
|
189
|
-
```typescript
|
|
190
|
-
base64ToBytes(b64: string): Uint8Array
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
Decodes a base64 or base64url string to a `Uint8Array`. Handles padded,
|
|
194
|
-
unpadded, and legacy `%3d` padding. Unpadded base64url input is accepted (RFC
|
|
195
|
-
4648 §5). Throws `RangeError` if the input is not valid base64 (illegal
|
|
196
|
-
characters or `rem=1` length).
|
|
197
|
-
|
|
198
|
-
---
|
|
199
|
-
|
|
200
|
-
### bytesToBase64
|
|
201
|
-
|
|
202
|
-
```typescript
|
|
203
|
-
bytesToBase64(bytes: Uint8Array, url?: boolean): string
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
Encodes a `Uint8Array` to a base64 string. Pass `url = true` for base64url (RFC
|
|
207
|
-
4648 §5), which uses `-` and `_` instead of `+` and `/` with no padding
|
|
208
|
-
characters. Defaults to standard base64.
|
|
209
|
-
|
|
210
|
-
---
|
|
211
|
-
|
|
212
|
-
### wipe
|
|
213
|
-
|
|
214
|
-
```typescript
|
|
215
|
-
wipe(data: Uint8Array | Uint16Array | Uint32Array): void
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
Zeroes a typed array in-place by calling `fill(0)`. Use this to clear keys,
|
|
219
|
-
plaintext, or any sensitive material when you are done with it.
|
|
220
|
-
|
|
221
|
-
---
|
|
222
|
-
|
|
223
|
-
### xor
|
|
224
|
-
|
|
225
|
-
```typescript
|
|
226
|
-
xor(a: Uint8Array, b: Uint8Array): Uint8Array
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
Returns a new `Uint8Array` where each byte is `a[i] ^ b[i]`. Both arrays must
|
|
230
|
-
have the same length. Throws `RangeError` if they differ.
|
|
231
|
-
|
|
232
|
-
---
|
|
233
|
-
|
|
234
|
-
### concat
|
|
235
|
-
|
|
236
|
-
```typescript
|
|
237
|
-
concat(...arrays: Uint8Array[]): Uint8Array
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
Concatenates one or more `Uint8Array`s into a new array.
|
|
241
|
-
|
|
242
|
-
---
|
|
243
|
-
|
|
244
|
-
### randomBytes
|
|
245
|
-
|
|
246
|
-
```typescript
|
|
247
|
-
randomBytes(n: number): Uint8Array
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
Returns `n` cryptographically secure random bytes via the Web Crypto API
|
|
251
|
-
(`crypto.getRandomValues`).
|
|
252
|
-
|
|
253
|
-
---
|
|
254
|
-
|
|
255
|
-
### hasSIMD
|
|
256
|
-
|
|
257
|
-
```typescript
|
|
258
|
-
hasSIMD(): boolean
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
Returns `true` if the current runtime supports WebAssembly SIMD (the `v128`
|
|
262
|
-
type and associated operations). The result is computed once on first call by
|
|
263
|
-
validating a minimal v128 WASM module, then cached for subsequent calls.
|
|
264
|
-
|
|
265
|
-
A public utility for consumers who want to feature-detect before calling
|
|
266
|
-
`init()`. The library requires SIMD for `serpent`, `chacha20`, and
|
|
267
|
-
`constantTimeEqual`; calls into those modules throw a branded error on
|
|
268
|
-
non-SIMD runtimes. `sha2` and `sha3` do not require SIMD.
|
|
269
|
-
|
|
270
|
-
Supported in all modern browsers and Node.js 16+.
|
|
271
|
-
|
|
272
|
-
---
|
|
273
|
-
|
|
274
|
-
## Usage Examples
|
|
275
|
-
|
|
276
|
-
### Converting between formats
|
|
277
|
-
|
|
278
|
-
```typescript
|
|
279
|
-
import { hexToBytes, bytesToHex, utf8ToBytes, bytesToUtf8 } from 'leviathan-crypto'
|
|
280
|
-
|
|
281
|
-
// Hex round-trip
|
|
282
|
-
const bytes = hexToBytes('deadbeef')
|
|
283
|
-
console.log(bytesToHex(bytes)) // "deadbeef"
|
|
284
|
-
|
|
285
|
-
// 0x prefix is accepted
|
|
286
|
-
const prefixed = hexToBytes('0xCAFE')
|
|
287
|
-
console.log(bytesToHex(prefixed)) // "cafe"
|
|
288
|
-
|
|
289
|
-
// UTF-8 round-trip
|
|
290
|
-
const encoded = utf8ToBytes('hello world')
|
|
291
|
-
console.log(bytesToUtf8(encoded)) // "hello world"
|
|
292
|
-
```
|
|
293
|
-
|
|
294
|
-
---
|
|
295
|
-
|
|
296
|
-
### Base64 encoding and decoding
|
|
297
|
-
|
|
298
|
-
```typescript
|
|
299
|
-
import { bytesToBase64, base64ToBytes, utf8ToBytes, bytesToUtf8 } from 'leviathan-crypto'
|
|
300
|
-
|
|
301
|
-
const data = utf8ToBytes('leviathan-crypto')
|
|
302
|
-
const b64 = bytesToBase64(data)
|
|
303
|
-
console.log(b64) // "bGV2aWF0aGFuLWNyeXB0bw=="
|
|
304
|
-
|
|
305
|
-
// base64url variant (safe for URLs and filenames, no padding)
|
|
306
|
-
const b64url = bytesToBase64(data, true)
|
|
307
|
-
console.log(b64url) // "bGV2aWF0aGFuLWNyeXB0bw"
|
|
308
|
-
|
|
309
|
-
// Decoding (accepts both standard and url variants)
|
|
310
|
-
const decoded = base64ToBytes(b64)
|
|
311
|
-
console.log(bytesToUtf8(decoded)) // "leviathan-crypto"
|
|
312
|
-
```
|
|
313
|
-
|
|
314
|
-
---
|
|
315
|
-
|
|
316
|
-
### Encrypt-then-MAC with SerpentCbc
|
|
317
|
-
|
|
318
|
-
If you use `SerpentCbc` or `SerpentCtr` directly with `{ dangerUnauthenticated:
|
|
319
|
-
true }`, you are responsible for authentication. The correct pattern is
|
|
320
|
-
Encrypt-then-MAC: encrypt first, then compute HMAC-SHA256 over the ciphertext,
|
|
321
|
-
and use `constantTimeEqual` to verify on decrypt.
|
|
322
|
-
|
|
323
|
-
```typescript
|
|
324
|
-
import {
|
|
325
|
-
init, SerpentCbc, HMAC_SHA256,
|
|
326
|
-
constantTimeEqual, randomBytes, wipe, concat,
|
|
327
|
-
} from 'leviathan-crypto'
|
|
328
|
-
import { serpentWasm } from 'leviathan-crypto/serpent/embedded'
|
|
329
|
-
import { sha2Wasm } from 'leviathan-crypto/sha2/embedded'
|
|
330
|
-
|
|
331
|
-
await init({ serpent: serpentWasm, sha2: sha2Wasm })
|
|
332
|
-
|
|
333
|
-
const encKey = randomBytes(32)
|
|
334
|
-
const macKey = randomBytes(32)
|
|
335
|
-
const iv = randomBytes(16)
|
|
336
|
-
|
|
337
|
-
// ── Encrypt ──────────────────────────────────────────────────────────────────
|
|
338
|
-
|
|
339
|
-
const cbc = new SerpentCbc({ dangerUnauthenticated: true })
|
|
340
|
-
const ct = cbc.encrypt(encKey, iv, plaintext)
|
|
341
|
-
cbc.dispose()
|
|
342
|
-
|
|
343
|
-
// MAC covers iv || ct so the IV is authenticated too
|
|
344
|
-
const hmac = new HMAC_SHA256()
|
|
345
|
-
const tag = hmac.hash(macKey, concat(iv, ct))
|
|
346
|
-
hmac.dispose()
|
|
347
|
-
|
|
348
|
-
const envelope = concat(iv, ct, tag) // store or transmit this
|
|
349
|
-
|
|
350
|
-
// ── Decrypt ──────────────────────────────────────────────────────────────────
|
|
351
|
-
|
|
352
|
-
const receivedIv = envelope.subarray(0, 16)
|
|
353
|
-
const receivedCt = envelope.subarray(16, envelope.length - 32)
|
|
354
|
-
const receivedTag = envelope.subarray(envelope.length - 32)
|
|
355
|
-
|
|
356
|
-
const hmac2 = new HMAC_SHA256()
|
|
357
|
-
const expectedTag = hmac2.hash(macKey, concat(receivedIv, receivedCt))
|
|
358
|
-
hmac2.dispose()
|
|
359
|
-
|
|
360
|
-
// Always verify before decrypting — never decrypt unauthenticated ciphertext
|
|
361
|
-
if (!constantTimeEqual(expectedTag, receivedTag)) {
|
|
362
|
-
wipe(expectedTag)
|
|
363
|
-
throw new Error('Authentication failed')
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
const cbc2 = new SerpentCbc({ dangerUnauthenticated: true })
|
|
367
|
-
const pt = cbc2.decrypt(encKey, receivedIv, receivedCt)
|
|
368
|
-
cbc2.dispose()
|
|
369
|
-
wipe(expectedTag)
|
|
370
|
-
```
|
|
371
|
-
|
|
372
|
-
> [!NOTE]
|
|
373
|
-
> `Seal` with `SerpentCipher` does all of this for you; key derivation, IV
|
|
374
|
-
> handling, Encrypt-then-MAC, and constant-time verification, with no manual
|
|
375
|
-
> steps. The pattern above is only relevant if you need direct access to the
|
|
376
|
-
> raw `SerpentCbc` primitive.
|
|
377
|
-
|
|
378
|
-
---
|
|
379
|
-
|
|
380
|
-
### Generating random keys and nonces
|
|
381
|
-
|
|
382
|
-
```typescript
|
|
383
|
-
import { randomBytes } from 'leviathan-crypto'
|
|
384
|
-
|
|
385
|
-
const key = randomBytes(32) // 256-bit symmetric key
|
|
386
|
-
const nonce = randomBytes(24) // 192-bit nonce for XChaCha20
|
|
387
|
-
const iv = randomBytes(16) // 128-bit IV for Serpent-CBC
|
|
388
|
-
```
|
|
389
|
-
|
|
390
|
-
---
|
|
391
|
-
|
|
392
|
-
### Wiping sensitive data after use
|
|
393
|
-
|
|
394
|
-
```typescript
|
|
395
|
-
import { randomBytes, wipe } from 'leviathan-crypto'
|
|
396
|
-
|
|
397
|
-
const key = randomBytes(32)
|
|
398
|
-
|
|
399
|
-
// ... use the key for encryption / decryption ...
|
|
400
|
-
|
|
401
|
-
// When done, zero the key material so it does not linger in memory
|
|
402
|
-
wipe(key)
|
|
403
|
-
// key is now all zeroes
|
|
404
|
-
```
|
|
405
|
-
|
|
406
|
-
---
|
|
407
|
-
|
|
408
|
-
### XOR and concatenation
|
|
409
|
-
|
|
410
|
-
```typescript
|
|
411
|
-
import { xor, concat, randomBytes } from 'leviathan-crypto'
|
|
412
|
-
|
|
413
|
-
const a = randomBytes(16)
|
|
414
|
-
const b = randomBytes(16)
|
|
415
|
-
|
|
416
|
-
// XOR two equal-length arrays
|
|
417
|
-
const xored = xor(a, b)
|
|
418
|
-
|
|
419
|
-
// Concatenate two arrays
|
|
420
|
-
const combined = concat(a, b)
|
|
421
|
-
console.log(combined.length) // 32
|
|
422
|
-
```
|
|
423
|
-
|
|
424
|
-
---
|
|
425
|
-
|
|
426
|
-
## Error Conditions
|
|
427
|
-
|
|
428
|
-
| Function | Condition | Behavior |
|
|
429
|
-
|---|---|---|
|
|
430
|
-
| `hexToBytes` | Odd-length string | Throws `RangeError` |
|
|
431
|
-
| `hexToBytes` | Invalid hex characters | Throws `RangeError` |
|
|
432
|
-
| `base64ToBytes` | Invalid length or characters | Throws `RangeError` |
|
|
433
|
-
| `constantTimeEqual` | Arrays differ in length | Returns `false` immediately |
|
|
434
|
-
| `constantTimeEqual` | Either array exceeds `CT_MAX_BYTES` | Throws `RangeError` |
|
|
435
|
-
| `xor` | Arrays differ in length | Throws `RangeError` |
|
|
436
|
-
| `randomBytes` | `crypto` not available | Throws (runtime-dependent) |
|
|
437
|
-
| `hasSIMD` | `WebAssembly` not available | Returns `false` |
|
|
438
|
-
|
|
439
|
-
---
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
## Cross-References
|
|
443
|
-
|
|
444
|
-
| Document | Description |
|
|
445
|
-
| -------- | ----------- |
|
|
446
|
-
| [index](./README.md) | Project Documentation index |
|
|
447
|
-
| [architecture](./architecture.md) | architecture overview, module relationships, buffer layouts, and build pipeline |
|
|
448
|
-
| [asm_ct](./asm_ct.md) | WASM module reference for `constantTimeEqual`: SIMD algorithm, zero-copy layout, instantiation model, and memory zeroing |
|
|
449
|
-
| [serpent](./serpent.md) | Serpent modes consume keys from `randomBytes`; wrappers use `wipe` and `constantTimeEqual` |
|
|
450
|
-
| [chacha20](./chacha20.md) | ChaCha20/Poly1305 classes use `randomBytes` for nonce generation |
|
|
451
|
-
| [sha2](./sha2.md) | SHA-2 and HMAC classes; output often converted with `bytesToHex` |
|
|
452
|
-
| [sha3](./sha3.md) | SHA-3 and SHAKE classes; output often converted with `bytesToHex` |
|
|
453
|
-
| [argon2id](./argon2id.md) | passphrase-based encryption; uses `constantTimeEqual` for hash verification |
|
|
454
|
-
| [examples](./examples.md) | full HMAC-SHA256 custom protocol example using `constantTimeEqual` |
|
|
455
|
-
| [types](./types.md) | public interfaces whose implementations rely on these utilities |
|
|
456
|
-
| [test-suite](./test-suite.md) | test suite structure and vector corpus |
|
|
457
|
-
|
package/dist/embedded/kyber.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const WASM_GZ_BASE64 = "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";
|
package/dist/embedded/kyber.js
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
// Generated by scripts/embed-wasm.ts — do not edit
|
|
2
|
-
// gzip-compressed WASM binary, base64-encoded. Decoded and decompressed by loadEmbedded().
|
|
3
|
-
export const WASM_GZ_BASE64 = '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';
|
package/dist/kyber/embedded.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { WASM_GZ_BASE64 as kyberWasm } from '../embedded/kyber.js';
|
package/dist/kyber/indcpa.d.ts
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import type { KyberExports, Sha3Exports } from './types.js';
|
|
2
|
-
import type { KyberParams } 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: KyberExports, sx: Sha3Exports, params: KyberParams, 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: KyberExports, sx: Sha3Exports, params: KyberParams, 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: KyberExports, params: KyberParams, skCpa: Uint8Array, ct: Uint8Array): Uint8Array;
|
package/dist/kyber/index.d.ts
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { isInitialized } from '../init.js';
|
|
2
|
-
import type { WasmSource } from '../wasm-source.js';
|
|
3
|
-
import type { KyberExports, Sha3Exports, KyberKeyPair, KyberEncapsulation } from './types.js';
|
|
4
|
-
import { KyberParams, MLKEM512, MLKEM768, MLKEM1024 } from './params.js';
|
|
5
|
-
export declare function kyberInit(source: WasmSource): Promise<void>;
|
|
6
|
-
export declare function _kyberReady(): boolean;
|
|
7
|
-
export type { WasmSource };
|
|
8
|
-
export type { KyberKeyPair, KyberEncapsulation, KyberExports, Sha3Exports };
|
|
9
|
-
export { MLKEM512, MLKEM768, MLKEM1024 };
|
|
10
|
-
export type { KyberParams };
|
|
11
|
-
export { isInitialized };
|
|
12
|
-
export { KyberSuite } from './suite.js';
|
|
13
|
-
export declare class MlKemBase {
|
|
14
|
-
readonly params: KyberParams;
|
|
15
|
-
constructor(params: KyberParams);
|
|
16
|
-
private get kx();
|
|
17
|
-
private get sx();
|
|
18
|
-
keygenDerand(d: Uint8Array, z: Uint8Array): KyberKeyPair;
|
|
19
|
-
keygen(): KyberKeyPair;
|
|
20
|
-
encapsulateDerand(ek: Uint8Array, m: Uint8Array): KyberEncapsulation;
|
|
21
|
-
encapsulate(ek: Uint8Array): KyberEncapsulation;
|
|
22
|
-
decapsulate(dk: Uint8Array, c: Uint8Array): Uint8Array;
|
|
23
|
-
checkEncapsulationKey(ek: Uint8Array): boolean;
|
|
24
|
-
checkDecapsulationKey(dk: Uint8Array): boolean;
|
|
25
|
-
dispose(): void;
|
|
26
|
-
}
|
|
27
|
-
/** ML-KEM-512 — k=2, η₁=3, η₂=2, dᵤ=10, dᵥ=4. */
|
|
28
|
-
export declare class MlKem512 extends MlKemBase {
|
|
29
|
-
constructor();
|
|
30
|
-
}
|
|
31
|
-
/** ML-KEM-768 — k=3, η₁=2, η₂=2, dᵤ=10, dᵥ=4. */
|
|
32
|
-
export declare class MlKem768 extends MlKemBase {
|
|
33
|
-
constructor();
|
|
34
|
-
}
|
|
35
|
-
/** ML-KEM-1024 — k=4, η₁=2, η₂=2, dᵤ=11, dᵥ=5. */
|
|
36
|
-
export declare class MlKem1024 extends MlKemBase {
|
|
37
|
-
constructor();
|
|
38
|
-
}
|
package/dist/kyber/kem.d.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import type { KyberExports, Sha3Exports, KyberKeyPair, KyberEncapsulation } from './types.js';
|
|
2
|
-
import type { KyberParams } from './params.js';
|
|
3
|
-
/**
|
|
4
|
-
* ML-KEM.KeyGen_internal (FIPS 203 Algorithm 15).
|
|
5
|
-
*
|
|
6
|
-
* dk = skCpa || ek || H(ek) || z
|
|
7
|
-
*/
|
|
8
|
-
export declare function kemKeypairDerand(kx: KyberExports, sx: Sha3Exports, params: KyberParams, d: Uint8Array, z: Uint8Array): KyberKeyPair;
|
|
9
|
-
/**
|
|
10
|
-
* ML-KEM.Encaps_internal (FIPS 203 Algorithm 16).
|
|
11
|
-
*
|
|
12
|
-
* (K, r) = G(m || H(ek)), c = K-PKE.Encrypt(ek, m, r)
|
|
13
|
-
*/
|
|
14
|
-
export declare function kemEncapsulateDerand(kx: KyberExports, sx: Sha3Exports, params: KyberParams, ek: Uint8Array, m: Uint8Array): KyberEncapsulation;
|
|
15
|
-
/**
|
|
16
|
-
* ML-KEM.Decaps_internal (FIPS 203 Algorithm 17).
|
|
17
|
-
*
|
|
18
|
-
* Constant-time: uses ct_verify and ct_cmov from kyber WASM.
|
|
19
|
-
* MUST NOT branch on secret data in JS — all comparison via WASM primitives.
|
|
20
|
-
*/
|
|
21
|
-
export declare function kemDecapsulate(kx: KyberExports, sx: Sha3Exports, params: KyberParams, dk: Uint8Array, c: Uint8Array): Uint8Array;
|
package/dist/kyber/suite.d.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { CipherSuite } from '../stream/types.js';
|
|
2
|
-
import type { KyberKeyPair, KyberEncapsulation } from './types.js';
|
|
3
|
-
import type { KyberParams } from './params.js';
|
|
4
|
-
export interface MlKemLike {
|
|
5
|
-
readonly params: KyberParams;
|
|
6
|
-
encapsulate(ek: Uint8Array): KyberEncapsulation;
|
|
7
|
-
decapsulate(dk: Uint8Array, c: Uint8Array): Uint8Array;
|
|
8
|
-
keygen(): KyberKeyPair;
|
|
9
|
-
}
|
|
10
|
-
export declare function KyberSuite(kem: MlKemLike, inner: CipherSuite): CipherSuite & {
|
|
11
|
-
keygen(): KyberKeyPair;
|
|
12
|
-
};
|
|
File without changes
|