leviathan-crypto 1.4.0 → 2.0.1
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 +129 -94
- package/README.md +166 -223
- package/SECURITY.md +90 -45
- package/dist/chacha20/cipher-suite.d.ts +4 -0
- package/dist/chacha20/cipher-suite.js +79 -0
- package/dist/chacha20/embedded.d.ts +1 -0
- package/dist/chacha20/embedded.js +27 -0
- package/dist/chacha20/index.d.ts +20 -27
- package/dist/chacha20/index.js +40 -59
- package/dist/chacha20/ops.d.ts +1 -1
- package/dist/chacha20/ops.js +19 -18
- package/dist/chacha20/pool-worker.js +77 -0
- package/dist/ct-wasm.d.ts +1 -0
- package/dist/ct-wasm.js +3 -0
- package/dist/ct.wasm +0 -0
- package/dist/docs/aead.md +323 -0
- package/dist/docs/architecture.md +427 -292
- package/dist/docs/argon2id.md +42 -30
- package/dist/docs/chacha20.md +192 -266
- package/dist/docs/exports.md +241 -0
- package/dist/docs/fortuna.md +60 -69
- package/dist/docs/init.md +172 -178
- package/dist/docs/loader.md +87 -142
- package/dist/docs/serpent.md +134 -583
- package/dist/docs/sha2.md +91 -103
- package/dist/docs/sha3.md +70 -36
- package/dist/docs/types.md +94 -16
- package/dist/docs/utils.md +109 -32
- package/dist/embedded/kyber.d.ts +1 -0
- package/dist/embedded/kyber.js +3 -0
- package/dist/embedded/serpent.d.ts +1 -1
- package/dist/embedded/serpent.js +1 -1
- package/dist/errors.d.ts +10 -0
- package/dist/errors.js +38 -0
- package/dist/fortuna.d.ts +0 -6
- package/dist/fortuna.js +5 -5
- package/dist/index.d.ts +25 -9
- package/dist/index.js +36 -7
- package/dist/init.d.ts +3 -7
- package/dist/init.js +18 -35
- package/dist/keccak/embedded.d.ts +1 -0
- package/dist/keccak/embedded.js +27 -0
- package/dist/keccak/index.d.ts +4 -0
- package/dist/keccak/index.js +31 -0
- package/dist/kyber/embedded.d.ts +1 -0
- package/dist/kyber/embedded.js +27 -0
- package/dist/kyber/indcpa.d.ts +49 -0
- package/dist/kyber/indcpa.js +352 -0
- package/dist/kyber/index.d.ts +38 -0
- package/dist/kyber/index.js +150 -0
- package/dist/kyber/kem.d.ts +21 -0
- package/dist/kyber/kem.js +160 -0
- package/dist/kyber/params.d.ts +14 -0
- package/dist/kyber/params.js +37 -0
- package/dist/kyber/suite.d.ts +13 -0
- package/dist/kyber/suite.js +94 -0
- package/dist/kyber/types.d.ts +98 -0
- package/dist/kyber/types.js +25 -0
- package/dist/kyber/validate.d.ts +19 -0
- package/dist/kyber/validate.js +68 -0
- package/dist/kyber.wasm +0 -0
- package/dist/loader.d.ts +15 -6
- package/dist/loader.js +65 -21
- package/dist/serpent/cipher-suite.d.ts +4 -0
- package/dist/serpent/cipher-suite.js +122 -0
- package/dist/serpent/embedded.d.ts +1 -0
- package/dist/serpent/embedded.js +27 -0
- package/dist/serpent/index.d.ts +6 -37
- package/dist/serpent/index.js +9 -118
- package/dist/serpent/pool-worker.d.ts +1 -0
- package/dist/serpent/pool-worker.js +208 -0
- package/dist/serpent/serpent-cbc.d.ts +30 -0
- package/dist/serpent/serpent-cbc.js +142 -0
- package/dist/serpent.wasm +0 -0
- package/dist/sha2/embedded.d.ts +1 -0
- package/dist/sha2/embedded.js +27 -0
- package/dist/sha2/hkdf.js +6 -2
- package/dist/sha2/index.d.ts +3 -2
- package/dist/sha2/index.js +3 -4
- package/dist/sha3/embedded.d.ts +1 -0
- package/dist/sha3/embedded.js +27 -0
- package/dist/sha3/index.d.ts +3 -2
- package/dist/sha3/index.js +3 -4
- package/dist/stream/constants.d.ts +6 -0
- package/dist/stream/constants.js +30 -0
- package/dist/stream/header.d.ts +9 -0
- package/dist/stream/header.js +77 -0
- package/dist/stream/index.d.ts +7 -0
- package/dist/stream/index.js +27 -0
- package/dist/stream/open-stream.d.ts +21 -0
- package/dist/stream/open-stream.js +146 -0
- package/dist/stream/seal-stream-pool.d.ts +38 -0
- package/dist/stream/seal-stream-pool.js +400 -0
- package/dist/stream/seal-stream.d.ts +20 -0
- package/dist/stream/seal-stream.js +142 -0
- package/dist/stream/seal.d.ts +9 -0
- package/dist/stream/seal.js +75 -0
- package/dist/stream/types.d.ts +25 -0
- package/dist/stream/types.js +26 -0
- package/dist/utils.d.ts +7 -2
- package/dist/utils.js +49 -3
- package/dist/wasm-source.d.ts +12 -0
- package/dist/wasm-source.js +26 -0
- package/package.json +13 -5
- package/dist/chacha20/pool.d.ts +0 -52
- package/dist/chacha20/pool.js +0 -178
- package/dist/chacha20/pool.worker.js +0 -37
- package/dist/chacha20/stream-sealer.d.ts +0 -49
- package/dist/chacha20/stream-sealer.js +0 -327
- package/dist/docs/chacha20_pool.md +0 -309
- package/dist/docs/wasm.md +0 -194
- package/dist/serpent/seal.d.ts +0 -8
- package/dist/serpent/seal.js +0 -72
- package/dist/serpent/stream-pool.d.ts +0 -48
- package/dist/serpent/stream-pool.js +0 -275
- package/dist/serpent/stream-sealer.d.ts +0 -55
- package/dist/serpent/stream-sealer.js +0 -342
- package/dist/serpent/stream.d.ts +0 -28
- package/dist/serpent/stream.js +0 -205
- package/dist/serpent/stream.worker.d.ts +0 -32
- package/dist/serpent/stream.worker.js +0 -117
- /package/dist/chacha20/{pool.worker.d.ts → pool-worker.d.ts} +0 -0
package/dist/docs/loader.md
CHANGED
|
@@ -5,205 +5,150 @@
|
|
|
5
5
|
> instantiation of WebAssembly binaries. You normally do not interact
|
|
6
6
|
> with this module directly.
|
|
7
7
|
|
|
8
|
+
> ### Table of Contents
|
|
9
|
+
> - [Overview](#overview)
|
|
10
|
+
> - [Security Notes](#security-notes)
|
|
11
|
+
> - [API Reference](#api-reference)
|
|
12
|
+
> - [Internal Details](#internal-details)
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
8
16
|
## Overview
|
|
9
17
|
|
|
10
|
-
When you call `init()
|
|
11
|
-
WASM binary to the loader. The
|
|
18
|
+
When you call [`init()`](./init.md), it delegates the work of obtaining and compiling the
|
|
19
|
+
WASM binary to the loader. The loading strategy is inferred from the
|
|
20
|
+
`WasmSource` type, so no mode string is required:
|
|
21
|
+
|
|
22
|
+
**Embedded string.** gzip-compressed, base64-encoded WASM bundled in the package. Decoded and decompressed at [`init()`](./init.md) time using `DecompressionStream`. No network requests. This is the default and simplest option.
|
|
23
|
+
|
|
24
|
+
**URL.** Fetches the `.wasm` file and uses the browser's streaming compilation API. The browser can start compiling while still downloading.
|
|
25
|
+
|
|
26
|
+
**ArrayBuffer / Uint8Array.** Raw WASM bytes, compiled directly.
|
|
27
|
+
|
|
28
|
+
**WebAssembly.Module.** Already compiled. Instantiated immediately. Useful for edge runtimes and KV-cached modules.
|
|
12
29
|
|
|
13
|
-
|
|
14
|
-
gzip-compressed, base64-encoded string. The loader decodes and decompresses
|
|
15
|
-
it at `init()` time using `DecompressionStream`. No network requests are
|
|
16
|
-
made. This is the default and simplest option.
|
|
17
|
-
- **Streaming** -- The loader fetches the `.wasm` file from a URL you provide
|
|
18
|
-
and uses the browser's streaming compilation API. The browser can start
|
|
19
|
-
compiling the binary while it is still downloading, which can improve
|
|
20
|
-
load times for larger modules.
|
|
21
|
-
- **Manual** -- You provide the raw binary data (as a `Uint8Array` or
|
|
22
|
-
`ArrayBuffer`) and the loader instantiates it directly. This gives you
|
|
23
|
-
full control over how the binary is obtained.
|
|
30
|
+
**Response / Promise\<Response\>.** Streaming compilation from an in-flight or deferred fetch.
|
|
24
31
|
|
|
25
|
-
All
|
|
26
|
-
|
|
32
|
+
All strategies produce the same result: a `WebAssembly.Instance` that the
|
|
33
|
+
wrapper classes use to perform cryptographic operations.
|
|
27
34
|
|
|
28
35
|
---
|
|
29
36
|
|
|
30
37
|
## Security Notes
|
|
31
38
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
- **Manual mode places integrity responsibility on you.** The loader
|
|
40
|
-
instantiates whatever binary you provide. If you use manual mode, you are
|
|
41
|
-
responsible for verifying that the binary is authentic and unmodified.
|
|
42
|
-
- **Each module gets its own memory.** Every instantiation creates a fresh
|
|
43
|
-
`WebAssembly.Memory` with 3 pages (192 KB). Modules cannot share or
|
|
44
|
-
access each other's memory. This means key material loaded into one
|
|
45
|
-
module's memory space is isolated from all other modules.
|
|
39
|
+
**Embedded mode requires no network access.** The WASM binary is part of the installed package. This eliminates the risk of a compromised CDN or man-in-the-middle attack altering the binary at load time.
|
|
40
|
+
|
|
41
|
+
**URL-based loading requires correct MIME type.** The `.wasm` files must be served with `Content-Type: application/wasm`. This is a browser requirement for `WebAssembly.instantiateStreaming`. If the header is missing or wrong, the browser will reject the response.
|
|
42
|
+
|
|
43
|
+
**Raw binary / Module sources place integrity responsibility on you.** The loader instantiates whatever binary you provide. If you supply your own bytes or pre-compiled Module, you are responsible for verifying authenticity.
|
|
44
|
+
|
|
45
|
+
**Each module gets its own memory.** Every instantiation creates a fresh `WebAssembly.Memory` with 3 pages (192 KB). Modules cannot share or access each other's memory. Key material in one module's memory space is isolated from all other modules.
|
|
46
46
|
|
|
47
47
|
---
|
|
48
48
|
|
|
49
49
|
## API Reference
|
|
50
50
|
|
|
51
51
|
These functions are exported from `loader.ts` and called by `init.ts`. They
|
|
52
|
-
are not part of the public API
|
|
53
|
-
and for contributors working on the internals.
|
|
54
|
-
|
|
55
|
-
### `loadEmbedded(thunk)`
|
|
52
|
+
are not part of the public API. They are documented here for completeness and for contributors working on the internals.
|
|
56
53
|
|
|
54
|
+
### `loadWasm(source)`
|
|
57
55
|
```typescript
|
|
58
|
-
async function
|
|
59
|
-
thunk: () => Promise<string>,
|
|
60
|
-
): Promise<WebAssembly.Instance>
|
|
56
|
+
async function loadWasm(source: WasmSource): Promise<WebAssembly.Instance>
|
|
61
57
|
```
|
|
62
58
|
|
|
63
|
-
Loads a WASM module from
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
**How it works:**
|
|
67
|
-
|
|
68
|
-
1. Calls the thunk, which dynamically imports the embedded binary file and
|
|
69
|
-
returns the gzip-compressed, base64-encoded WASM string.
|
|
70
|
-
2. Decodes the base64 string and decompresses the result using
|
|
71
|
-
`DecompressionStream('gzip')`.
|
|
72
|
-
3. Instantiates the WASM module with a fresh 3-page `WebAssembly.Memory`.
|
|
73
|
-
|
|
74
|
-
The thunk is provided by each module's own `init()` function (e.g.
|
|
75
|
-
`serpent/index.ts` passes `() => import('../embedded/serpent.js').then(m => m.WASM_GZ_BASE64)`).
|
|
76
|
-
This design means `loader.ts` has no knowledge of module names or embedded file
|
|
77
|
-
paths -- each module owns its own embedded import, enabling tree-shaking.
|
|
59
|
+
Loads and instantiates a WASM module from any accepted source type. Each
|
|
60
|
+
instance receives a fresh 3-page `WebAssembly.Memory`.
|
|
78
61
|
|
|
79
|
-
**
|
|
62
|
+
**Source type handling:**
|
|
80
63
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
64
|
+
| Source type | Loading path |
|
|
65
|
+
|--------------------------------|----------------------------------------------------------------------|
|
|
66
|
+
| `string` | Decoded from gzip+base64 via `decodeWasm()`, then `WebAssembly.instantiate()`. |
|
|
67
|
+
| `URL` | `WebAssembly.instantiateStreaming(fetch(url))`. |
|
|
68
|
+
| `ArrayBuffer` | `WebAssembly.instantiate()`. |
|
|
69
|
+
| `Uint8Array` | `WebAssembly.instantiate()`. |
|
|
70
|
+
| `WebAssembly.Module` | `WebAssembly.instantiate(module, imports)`. |
|
|
71
|
+
| `Response` / `Promise<Response>` | `WebAssembly.instantiateStreaming()`. |
|
|
84
72
|
|
|
85
|
-
**
|
|
73
|
+
**Throws:**
|
|
86
74
|
|
|
87
|
-
|
|
75
|
+
- `TypeError` if `source` is null, numeric, or otherwise unrecognised.
|
|
76
|
+
- `TypeError` with `"empty string"` if `source` is an empty string.
|
|
88
77
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
78
|
+
**Runtime guards:** `Response` and `Promise` checks are guarded with
|
|
79
|
+
`typeof Response !== 'undefined'` to avoid `ReferenceError` in runtimes
|
|
80
|
+
where these globals do not exist (Node < 18).
|
|
92
81
|
|
|
93
82
|
---
|
|
94
83
|
|
|
95
|
-
### `
|
|
96
|
-
|
|
84
|
+
### `compileWasm(source)`
|
|
97
85
|
```typescript
|
|
98
|
-
async function
|
|
99
|
-
_mod: Module,
|
|
100
|
-
baseUrl: URL | string,
|
|
101
|
-
filename: string,
|
|
102
|
-
): Promise<WebAssembly.Instance>
|
|
86
|
+
async function compileWasm(source: WasmSource): Promise<WebAssembly.Module>
|
|
103
87
|
```
|
|
104
88
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
**How it works:**
|
|
108
|
-
|
|
109
|
-
1. Constructs the full URL by combining `baseUrl` and `filename`
|
|
110
|
-
(e.g. `https://example.com/wasm/` + `serpent.wasm`).
|
|
111
|
-
2. Calls `WebAssembly.instantiateStreaming(fetch(url), imports)`, which
|
|
112
|
-
allows the browser to compile the module while it downloads.
|
|
113
|
-
3. Creates a fresh 3-page `WebAssembly.Memory` for the instance.
|
|
114
|
-
|
|
115
|
-
**Parameters:**
|
|
89
|
+
Compiles a `WasmSource` to a `WebAssembly.Module` without instantiating it.
|
|
90
|
+
Used by pool infrastructure to send a compiled module to workers. Each worker receives the `Module` and instantiates it with their own isolated memory.
|
|
116
91
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
`URL` object or a string.
|
|
121
|
-
- `filename` -- The `.wasm` filename (e.g. `'serpent.wasm'`). This is
|
|
122
|
-
determined by `init.ts` using its internal filename mapping.
|
|
92
|
+
**Source type handling:** Same dispatch table as `loadWasm()`, but calls
|
|
93
|
+
`WebAssembly.compile()` / `WebAssembly.compileStreaming()` instead of the
|
|
94
|
+
`instantiate` variants. `WebAssembly.Module` sources are returned as-is.
|
|
123
95
|
|
|
124
|
-
**
|
|
125
|
-
|
|
126
|
-
**Error conditions:**
|
|
127
|
-
|
|
128
|
-
- Network failure (server unreachable, 404, etc.) will cause the Promise
|
|
129
|
-
to reject.
|
|
130
|
-
- If the server does not respond with `Content-Type: application/wasm`,
|
|
131
|
-
the browser will reject the streaming compilation. This is a common
|
|
132
|
-
issue with misconfigured web servers -- ensure your server is configured
|
|
133
|
-
to serve `.wasm` files with the correct MIME type.
|
|
96
|
+
**Throws:** Same as `loadWasm()`.
|
|
134
97
|
|
|
135
98
|
---
|
|
136
99
|
|
|
137
|
-
### `
|
|
138
|
-
|
|
100
|
+
### `decodeWasm(b64)`
|
|
139
101
|
```typescript
|
|
140
|
-
async function
|
|
141
|
-
binary: Uint8Array | ArrayBuffer,
|
|
142
|
-
): Promise<WebAssembly.Instance>
|
|
102
|
+
async function decodeWasm(b64: string): Promise<Uint8Array>
|
|
143
103
|
```
|
|
144
104
|
|
|
145
|
-
|
|
105
|
+
Decodes a gzip-compressed, base64-encoded WASM string to raw bytes.
|
|
146
106
|
|
|
147
|
-
|
|
107
|
+
1. Base64-decodes the string using the shared `base64ToBytes` utility.
|
|
108
|
+
2. Decompresses the result using `DecompressionStream('gzip')`.
|
|
148
109
|
|
|
149
|
-
|
|
150
|
-
2. Instantiates the WASM module with a fresh 3-page `WebAssembly.Memory`.
|
|
110
|
+
**Throws:**
|
|
151
111
|
|
|
152
|
-
|
|
112
|
+
- `Error` if `DecompressionStream` is not available in the runtime.
|
|
113
|
+
The error message directs the user to provide a URL, ArrayBuffer, or
|
|
114
|
+
WebAssembly.Module source instead.
|
|
115
|
+
- `Error` if base64 decoding fails (corrupt embedded blob).
|
|
153
116
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
**Returns:** A Promise that resolves to a `WebAssembly.Instance`.
|
|
157
|
-
|
|
158
|
-
**Error conditions:**
|
|
159
|
-
|
|
160
|
-
- If the binary is not a valid WASM module, `WebAssembly.instantiate` will
|
|
161
|
-
throw. The error message will come from the browser's WASM engine and
|
|
162
|
-
will typically mention a validation or compilation failure.
|
|
117
|
+
Exported for use by pool worker launchers that need to decode blobs
|
|
118
|
+
before spawning threads.
|
|
163
119
|
|
|
164
120
|
---
|
|
165
121
|
|
|
166
122
|
## Internal Details
|
|
167
123
|
|
|
168
|
-
### Embedded binary
|
|
124
|
+
### Embedded binary structure
|
|
169
125
|
|
|
170
|
-
Each module
|
|
171
|
-
file. The loader has no knowledge of module names or file paths -- it receives
|
|
172
|
-
a thunk from `initModule()` and calls it. This means `loader.ts` has no
|
|
173
|
-
dependency on any embedded file, which enables bundlers to tree-shake unused
|
|
174
|
-
modules.
|
|
126
|
+
Each module provides two paths to its embedded blob:
|
|
175
127
|
|
|
176
|
-
|
|
|
177
|
-
|
|
178
|
-
| `
|
|
179
|
-
| `
|
|
180
|
-
| `sha2` | `sha2/index.ts` | `./embedded/sha2.js` |
|
|
181
|
-
| `sha3` | `sha3/index.ts` | `./embedded/sha3.js` |
|
|
128
|
+
| Path | Export | Used by |
|
|
129
|
+
|----------------------------------------|-----------------|-----------------------------|
|
|
130
|
+
| `src/ts/embedded/serpent.ts` | (raw blob) | Build artifact, gitignored |
|
|
131
|
+
| `src/ts/serpent/embedded.ts` | `serpentWasm` | Consumer import |
|
|
182
132
|
|
|
183
|
-
The
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
133
|
+
The per-module `embedded.ts` re-exports the generated blob as a named
|
|
134
|
+
export. Consumers import from the `/embedded` subpath:
|
|
135
|
+
```typescript
|
|
136
|
+
import { serpentWasm } from 'leviathan-crypto/serpent/embedded'
|
|
137
|
+
```
|
|
188
138
|
|
|
189
|
-
The `
|
|
139
|
+
The `src/ts/embedded/` directory is generated by `scripts/embed-wasm.ts`
|
|
140
|
+
and is gitignored. These files are not meant to be created or edited by hand.
|
|
190
141
|
|
|
191
|
-
|
|
192
|
-
(handles both browser `atob` and Node.js `Buffer` paths).
|
|
193
|
-
2. Decompresses the result using the platform `DecompressionStream('gzip')`.
|
|
194
|
-
This API is available in all runtimes that support WASM SIMD, which is
|
|
195
|
-
the library's minimum requirement.
|
|
142
|
+
### Embedded compression
|
|
196
143
|
|
|
197
|
-
The embedded files
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
to ~20 KB.
|
|
144
|
+
The embedded files contain gzip-compressed WASM encoded as base64.
|
|
145
|
+
Compression reduces the embedded footprint from ~198 KB to ~33 KB across
|
|
146
|
+
all four modules, with Serpent alone shrinking from ~167 KB to ~20 KB.
|
|
201
147
|
|
|
202
148
|
### Memory allocation
|
|
203
149
|
|
|
204
150
|
Every WASM instance receives a `WebAssembly.Memory` with exactly 3 pages
|
|
205
|
-
(192 KB total). The memory size is fixed
|
|
206
|
-
at runtime. This is a deliberate design choice: fixed memory prevents
|
|
151
|
+
(192 KB total). The memory size is fixed; modules do not grow their memory at runtime. This is a deliberate design choice: fixed memory prevents
|
|
207
152
|
unexpected allocations and makes the memory layout predictable and auditable.
|
|
208
153
|
|
|
209
154
|
---
|