leviathan-crypto 1.1.0 → 1.3.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 +19 -17
- package/README.md +153 -82
- package/SECURITY.md +100 -55
- package/dist/chacha.wasm +0 -0
- package/dist/chacha20/index.js +3 -1
- package/dist/chacha20/types.d.ts +2 -0
- package/dist/docs/architecture.md +4 -2
- package/dist/docs/serpent.md +38 -4
- package/dist/docs/utils.md +21 -0
- package/dist/embedded/chacha.d.ts +1 -1
- package/dist/embedded/chacha.js +1 -1
- package/dist/embedded/serpent.d.ts +1 -1
- package/dist/embedded/serpent.js +1 -1
- package/dist/embedded/sha2.d.ts +1 -1
- package/dist/embedded/sha2.js +1 -1
- package/dist/embedded/sha3.d.ts +1 -1
- package/dist/embedded/sha3.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/serpent/index.d.ts +0 -1
- package/dist/serpent/index.js +5 -4
- package/dist/serpent/stream-sealer.d.ts +18 -2
- package/dist/serpent/stream-sealer.js +122 -4
- package/dist/serpent.wasm +0 -0
- package/dist/sha2.wasm +0 -0
- package/dist/sha3.wasm +0 -0
- package/dist/utils.d.ts +5 -0
- package/dist/utils.js +25 -0
- package/package.json +1 -1
- package/dist/serpent/stream-encoder.d.ts +0 -20
- package/dist/serpent/stream-encoder.js +0 -167
package/SECURITY.md
CHANGED
|
@@ -1,18 +1,30 @@
|
|
|
1
1
|
# Leviathan Crypto Library Security Policy
|
|
2
2
|
|
|
3
|
+
<img src="https://github.com/xero/leviathan-crypto/raw/main/docs/logo.svg" alt="Leviathan logo" width="100" align="left">
|
|
4
|
+
|
|
5
|
+
- **[Version Support](#supported-versions)**
|
|
6
|
+
- **[Security Posture](#security-posture)**
|
|
7
|
+
- **[Cryptanalytic Audits](#cryptanalytic-reviews)**
|
|
8
|
+
- **[Vulnerability Reporting](#reporting-a-vulnerability)**
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
3
12
|
## Supported Versions
|
|
4
13
|
|
|
5
14
|
| Version | Supported |
|
|
6
15
|
|---------|-----------|
|
|
7
|
-
| v1.x
|
|
16
|
+
| v1.3.x | ︎✓ |
|
|
17
|
+
| v1.2.x | ✓ |
|
|
18
|
+
| v1.1.x | ✗ |
|
|
19
|
+
| v1.0.x | ✗ |
|
|
8
20
|
|
|
9
|
-
> [!
|
|
10
|
-
> v1.0.
|
|
11
|
-
>
|
|
21
|
+
> [!WARNING]
|
|
22
|
+
> v1.0.x does not zero intermediate key material in HMAC and HKDF operations.
|
|
23
|
+
> Upgrading to v1.1.0 or later is strongly recommended.
|
|
12
24
|
|
|
13
25
|
## Security Posture
|
|
14
26
|
|
|
15
|
-
leviathan-crypto is a cryptography library. Security is not an afterthought,
|
|
27
|
+
[`leviathan-crypto`](https://leviathan.3xi.club) is a cryptography library. Security is not an afterthought,
|
|
16
28
|
it is the primary design constraint at every layer of the stack.
|
|
17
29
|
|
|
18
30
|
### Algorithm Correctness
|
|
@@ -23,69 +35,84 @@ against the authoritative specification for that algorithm:
|
|
|
23
35
|
[RFC 8439][rfc8439] (ChaCha20-Poly1305), [RFC 2104][rfc2104] (HMAC),
|
|
24
36
|
[RFC 5869][rfc5869] (HKDF), and the original
|
|
25
37
|
[Serpent-256 specification][serpent] and S-box reference. No algorithm was
|
|
26
|
-
ported from an existing implementation
|
|
38
|
+
ported from an existing implementation. The specs are always the source of truth.
|
|
27
39
|
|
|
28
40
|
All implementations are verified against published known-answer test vectors
|
|
29
41
|
from NIST, RFC appendices, NESSIE, and the Argon2 reference suite. Vectors
|
|
30
42
|
are immutable: if an implementation produces incorrect output, the
|
|
31
|
-
implementation is fixed
|
|
43
|
+
implementation is fixed and vectors are never adjusted to match code.
|
|
32
44
|
|
|
33
45
|
### Side-Channel Resistance
|
|
34
46
|
|
|
35
|
-
Serpent's S-boxes are implemented as Boolean gate circuits
|
|
36
|
-
lookups, no data-dependent memory access, no data-dependent branches. Every
|
|
47
|
+
Serpent's S-boxes are implemented as Boolean gate circuits designed with no table
|
|
48
|
+
lookups, no data-dependent memory access, and no data-dependent branches. Every
|
|
37
49
|
bit is processed unconditionally on every block. This is the most
|
|
38
50
|
timing-safe cipher implementation approach available in a WASM runtime,
|
|
39
51
|
where JIT optimisation can otherwise introduce observable timing variation.
|
|
40
52
|
|
|
41
|
-
All security-sensitive comparisons (MAC verification, padding validation)
|
|
53
|
+
All security-sensitive comparisons (e.g. MAC verification, padding validation)
|
|
42
54
|
use XOR-accumulate patterns with no early return on mismatch.
|
|
43
55
|
[`constantTimeEqual`][utils] is the mandated comparison function throughout
|
|
44
|
-
the library and its demos.
|
|
56
|
+
the library and its [demos][demos].
|
|
45
57
|
|
|
46
58
|
### WASM Execution Model
|
|
47
59
|
|
|
48
60
|
All cryptographic computation runs in WebAssembly, isolated outside the
|
|
49
61
|
JavaScript JIT. WASM execution is deterministic and not subject to JIT
|
|
50
62
|
speculation or optimisation. Each primitive family compiles to its own
|
|
51
|
-
isolated binary with its own linear memory
|
|
52
|
-
module cannot interact with memory in the SHA-3 module
|
|
63
|
+
isolated binary with its own linear memory. For example, key material in
|
|
64
|
+
the Serpent module cannot interact with memory in the SHA-3 module,
|
|
65
|
+
even in principle.
|
|
53
66
|
|
|
54
|
-
### Cryptanalytic
|
|
67
|
+
### Cryptanalytic Reviews
|
|
68
|
+
|
|
69
|
+
All of our primitives undergo periodic cryptographic implementation reviews.
|
|
70
|
+
|
|
71
|
+
| Primitive | Audit Description |
|
|
72
|
+
|-----------|-------------------|
|
|
73
|
+
| [serpent_audit][serpent_audit] | Correctness verification, side-channel analysis, cryptanalytic attack paper review |
|
|
74
|
+
| [chacha_audit][chacha_audit] | XChaCha20-Poly1305 correctness, Poly1305 field arithmetic, HChaCha20 nonce extension |
|
|
75
|
+
| [sha2_audit][sha2_audit] | SHA-256/512/384 correctness, HMAC and HKDF composition, constant verification |
|
|
76
|
+
| [sha3_audit][sha3_audit] | Keccak permutation correctness, θ/ρ/π/χ/ι step verification, round constant derivation |
|
|
77
|
+
| [hmac_audit][hmac_audit] | HMAC-SHA256/512/384 construction, key processing, RFC 4231 vector coverage |
|
|
78
|
+
| [hkdf_audit][hkdf_audit] | HKDF extract-then-expand, info field domain separation, SerpentStream key derivation |
|
|
79
|
+
|
|
80
|
+
#### Additional Serpent-256 research
|
|
55
81
|
|
|
56
82
|
The security margin of Serpent-256 has been independently researched and
|
|
57
|
-
documented. The best known attack on the full 32-round cipher
|
|
58
|
-
cryptanalysis
|
|
83
|
+
documented. The best known attack on the full 32-round cipher, _"biclique
|
|
84
|
+
cryptanalysis"_, achieves a complexity of 2²⁵⁵·¹⁹ with 2⁴ chosen
|
|
59
85
|
ciphertexts. This provides less than one bit of advantage over exhaustive
|
|
60
86
|
key search and has zero practical impact. Independent research conducted
|
|
61
87
|
against this implementation improved on the published result by −0.20 bits
|
|
62
88
|
through systematic parameter search, confirming no structural weakness
|
|
63
89
|
beyond what the published literature describes.
|
|
64
90
|
|
|
65
|
-
See: [`xero/BicliqueFinder/biclique_research.md`][biclique]
|
|
66
|
-
[`leviathan-crypto/wiki/serpent_audit`][serpent-audit] for the full
|
|
67
|
-
analysis.
|
|
91
|
+
See: [`xero/BicliqueFinder/biclique_research.md`][biclique]
|
|
68
92
|
|
|
69
93
|
### Authenticated Encryption by Default
|
|
70
94
|
|
|
71
95
|
Raw unauthenticated cipher modes (`SerpentCbc`, `SerpentCtr`) are exposed
|
|
72
96
|
for power users but are not the recommended entry point. The primary API
|
|
73
97
|
surfaces — `SerpentSeal`, `SerpentStream`, `SerpentStreamSealer` — are
|
|
74
|
-
authenticated by construction.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
98
|
+
authenticated by construction.
|
|
99
|
+
|
|
100
|
+
**`SerpentStreamSealer` satisfies the _Cryptographic Doom Principle_:**
|
|
101
|
+
|
|
102
|
+
MAC verification is the unconditional gate on the open path,
|
|
103
|
+
decryption is unreachable until that gate clears, and per-chunk
|
|
104
|
+
HKDF key derivation with position-bound info extends this
|
|
78
105
|
guarantee to full stream integrity.
|
|
79
106
|
|
|
80
107
|
### Dependency Management
|
|
81
108
|
|
|
82
|
-
The library has
|
|
109
|
+
The library has **zero** runtime dependencies by design.
|
|
83
110
|
`sideEffects: false` is enforced in `package.json`. Argon2id integration
|
|
84
|
-
is documented as an
|
|
85
|
-
See:
|
|
111
|
+
is documented as an _optional_ external dependency.
|
|
112
|
+
See: [`leviathan-crypto/wiki/argon2id`][argon2id-wiki].
|
|
86
113
|
|
|
87
114
|
Build toolchain dependencies are pinned with exact version locks in
|
|
88
|
-
`bun.lock`. GitHub Actions workflows use SHA-pinned action references
|
|
115
|
+
`bun.lock`. GitHub Actions workflows use [SHA-pinned action references][workflows]
|
|
89
116
|
throughout with no floating tags. Supply chain integrity is treated as a
|
|
90
117
|
first-class concern for a cryptography library.
|
|
91
118
|
|
|
@@ -124,10 +151,13 @@ as the single source of authority.
|
|
|
124
151
|
Use GitHub's private vulnerability reporting form:
|
|
125
152
|
[https://github.com/xero/leviathan-crypto/security/advisories/new][advisory]
|
|
126
153
|
|
|
127
|
-
This opens a private channel between you and the maintainer
|
|
128
|
-
receive a response
|
|
129
|
-
|
|
130
|
-
|
|
154
|
+
This opens a private channel between you and the maintainer, and you will
|
|
155
|
+
receive a response promptly. If the vulnerability is confirmed,
|
|
156
|
+
we will collaborate to fully understand the issue, including a review of
|
|
157
|
+
proposed fixes, so you can track and validate firsthand. Before any public
|
|
158
|
+
advisory is published, we will agree on a coordinated disclosure timeline.
|
|
159
|
+
After disclosure, you are encouraged to publish your own write-up, blog post,
|
|
160
|
+
or research notes, for full hacker scene credit.
|
|
131
161
|
|
|
132
162
|
### Direct Contact
|
|
133
163
|
|
|
@@ -141,34 +171,49 @@ If you prefer to contact the maintainer directly:
|
|
|
141
171
|
|
|
142
172
|
### Scope
|
|
143
173
|
|
|
144
|
-
Reports are in scope for
|
|
174
|
+
**Reports are in scope for:**
|
|
145
175
|
|
|
146
|
-
- Correctness bugs in cryptographic implementations (wrong output against
|
|
147
|
-
test vectors)
|
|
148
|
-
- Side-channel vulnerabilities (timing, memory access patterns)
|
|
149
176
|
- Authentication bypass in AEAD constructions
|
|
150
177
|
- Key material exposure or improper zeroing
|
|
178
|
+
- Incorrect entropy or CSPRNG weaknesses in Fortuna
|
|
179
|
+
- Side-channel vulnerabilities (timing, memory access patterns)
|
|
180
|
+
- Correctness bugs in cryptographic implementations (wrong output against
|
|
181
|
+
test vectors)
|
|
182
|
+
- Platform-specific behavioral differences (WASM execution, binary output,
|
|
183
|
+
or timing characteristics that differ across operating systems or CPU
|
|
184
|
+
architectures)
|
|
151
185
|
- Supply chain issues (dependency tampering, workflow compromise)
|
|
186
|
+
- Improper scope of exported symbols
|
|
152
187
|
|
|
153
|
-
Out of scope
|
|
188
|
+
**Out of scope:**
|
|
154
189
|
|
|
155
|
-
-
|
|
156
|
-
|
|
190
|
+
- Vulnerabilities in third-party packages not maintained by this project.
|
|
191
|
+
This includes optional peer dependencies such as argon2id.
|
|
192
|
+
Please report those directly to their maintainers.
|
|
157
193
|
- Issues requiring physical access to the user's device
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
[
|
|
162
|
-
|
|
163
|
-
[
|
|
164
|
-
[
|
|
165
|
-
[
|
|
166
|
-
[
|
|
167
|
-
[
|
|
168
|
-
[
|
|
169
|
-
[
|
|
170
|
-
[
|
|
171
|
-
[
|
|
172
|
-
[
|
|
173
|
-
[
|
|
174
|
-
[
|
|
194
|
+
- Theoretical attacks with no practical exploit path (e.g. complexity
|
|
195
|
+
improvements that remain computationally infeasible)
|
|
196
|
+
- Issues in the demo applications that do not affect the core library.
|
|
197
|
+
Please open an issue in the [`leviathan-demos`][demos] repository instead.
|
|
198
|
+
|
|
199
|
+
[fips180]: https://csrc.nist.gov/publications/detail/fips/180/4/final
|
|
200
|
+
[fips202]: https://csrc.nist.gov/publications/detail/fips/202/final
|
|
201
|
+
[rfc8439]: https://www.rfc-editor.org/rfc/rfc8439
|
|
202
|
+
[rfc2104]: https://www.rfc-editor.org/rfc/rfc2104
|
|
203
|
+
[rfc5869]: https://www.rfc-editor.org/rfc/rfc5869
|
|
204
|
+
[serpent]: https://www.cl.cam.ac.uk/~rja14/Papers/serpent.pdf
|
|
205
|
+
[utils]: https://github.com/xero/leviathan-crypto/wiki/utils#constanttimeequal
|
|
206
|
+
[demos]: https://github.com/xero/leviathan-demos/
|
|
207
|
+
[serpent_audit]: https://github.com/xero/leviathan-crypto/wiki/serpent_audit
|
|
208
|
+
[chacha_audit]: https://github.com/xero/leviathan-crypto/wiki/chacha_audit
|
|
209
|
+
[sha2_audit]: https://github.com/xero/leviathan-crypto/wiki/sha2_audit
|
|
210
|
+
[sha3_audit]: https://github.com/xero/leviathan-crypto/wiki/sha3_audit
|
|
211
|
+
[hmac_audit]: https://github.com/xero/leviathan-crypto/wiki/hmac_audit
|
|
212
|
+
[hkdf_audit]: https://github.com/xero/leviathan-crypto/wiki/hkdf_audit
|
|
213
|
+
[biclique]: https://github.com/xero/BicliqueFinder/blob/main/biclique-research.md
|
|
214
|
+
[argon2id-wiki]: https://github.com/xero/leviathan-crypto/wiki/argon2id
|
|
215
|
+
[workflows]: https://github.com/xero/leviathan-crypto/blob/main/scripts/pin-actions.ts
|
|
216
|
+
[init]: https://github.com/xero/leviathan-crypto/wiki/init
|
|
217
|
+
[agents]: https://github.com/xero/leviathan-crypto/blob/main/AGENTS.md
|
|
218
|
+
[advisory]: https://github.com/xero/leviathan-crypto/security/advisories/new
|
|
219
|
+
[pgp]: https://0w.nz/pgp.pub
|
package/dist/chacha.wasm
CHANGED
|
Binary file
|
package/dist/chacha20/index.js
CHANGED
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
// Uses the init() module cache — call init('chacha20') before constructing.
|
|
26
26
|
import { getInstance, initModule } from '../init.js';
|
|
27
27
|
import { aeadEncrypt, aeadDecrypt, xcEncrypt, xcDecrypt } from './ops.js';
|
|
28
|
+
import { hasSIMD } from '../utils.js';
|
|
28
29
|
const _embedded = () => import('../embedded/chacha.js').then(m => m.WASM_BASE64);
|
|
29
30
|
export async function chacha20Init(mode = 'embedded', opts) {
|
|
30
31
|
return initModule('chacha20', _embedded, mode, opts);
|
|
@@ -57,7 +58,8 @@ export class ChaCha20 {
|
|
|
57
58
|
const ptOff = this.x.getChunkPtOffset();
|
|
58
59
|
const ctOff = this.x.getChunkCtOffset();
|
|
59
60
|
mem.set(chunk, ptOff);
|
|
60
|
-
this.x.chachaEncryptChunk
|
|
61
|
+
const fn = hasSIMD() ? this.x.chachaEncryptChunk_simd : this.x.chachaEncryptChunk;
|
|
62
|
+
fn(chunk.length);
|
|
61
63
|
return mem.slice(ctOff, ctOff + chunk.length);
|
|
62
64
|
}
|
|
63
65
|
beginDecrypt(key, nonce) {
|
package/dist/chacha20/types.d.ts
CHANGED
|
@@ -21,6 +21,8 @@ export interface ChaChaExports {
|
|
|
21
21
|
chachaResetCounter(): void;
|
|
22
22
|
chachaEncryptChunk(n: number): number;
|
|
23
23
|
chachaDecryptChunk(n: number): number;
|
|
24
|
+
chachaEncryptChunk_simd(n: number): number;
|
|
25
|
+
chachaDecryptChunk_simd(n: number): number;
|
|
24
26
|
chachaGenPolyKey(): void;
|
|
25
27
|
hchacha20(): void;
|
|
26
28
|
polyInit(): void;
|
|
@@ -676,9 +676,11 @@ Source: `src/asm/chacha/buffers.ts`
|
|
|
676
676
|
| 131492 | 16 | `POLY_S_BUFFER` — s pad: 4 × u32 |
|
|
677
677
|
| 131508 | 24 | `XCHACHA_NONCE_BUFFER` — full 24-byte XChaCha20 nonce |
|
|
678
678
|
| 131532 | 32 | `XCHACHA_SUBKEY_BUFFER` — HChaCha20 output (key material) |
|
|
679
|
-
| 131564 |
|
|
679
|
+
| 131564 | 4 | *(padding for 16-byte SIMD alignment)* |
|
|
680
|
+
| 131568 | 256 | `CHACHA_SIMD_WORK_BUFFER` — 4-wide inter-block keystream (4 × 64 bytes) |
|
|
681
|
+
| 131824 | — | END |
|
|
680
682
|
|
|
681
|
-
`wipeBuffers()` zeroes all
|
|
683
|
+
`wipeBuffers()` zeroes all 15 buffer regions (key, chacha nonce/ctr/block/state, chunk pt/ct, poly key/msg/buf/tag/h/r/rs/s, xchacha nonce/subkey, SIMD work).
|
|
682
684
|
|
|
683
685
|
### SHA-2 module — 3 pages (192 KB)
|
|
684
686
|
|
package/dist/docs/serpent.md
CHANGED
|
@@ -265,6 +265,12 @@ automatically.
|
|
|
265
265
|
- **chunk** -- any length up to the module's internal chunk buffer size. Throws
|
|
266
266
|
`RangeError` if the chunk exceeds the maximum size.
|
|
267
267
|
|
|
268
|
+
> [!NOTE]
|
|
269
|
+
> Automatically dispatches to the 4-wide SIMD path (`encryptChunk_simd`) when
|
|
270
|
+
> the runtime supports WebAssembly SIMD (`hasSIMD()` returns `true`), otherwise
|
|
271
|
+
> falls back to the scalar unrolled path. The dispatch is transparent — no API
|
|
272
|
+
> change required.
|
|
273
|
+
|
|
268
274
|
---
|
|
269
275
|
|
|
270
276
|
#### `beginDecrypt(key: Uint8Array, nonce: Uint8Array): void`
|
|
@@ -353,6 +359,12 @@ Decrypts Serpent CBC ciphertext and strips PKCS7 padding.
|
|
|
353
359
|
|
|
354
360
|
Returns the decrypted plaintext as a new `Uint8Array`.
|
|
355
361
|
|
|
362
|
+
> [!NOTE]
|
|
363
|
+
> Automatically dispatches to the 4-wide SIMD path (`cbcDecryptChunk_simd`) when
|
|
364
|
+
> the runtime supports WebAssembly SIMD (`hasSIMD()` returns `true`), otherwise
|
|
365
|
+
> falls back to the scalar unrolled path. CBC encryption has no SIMD variant —
|
|
366
|
+
> each ciphertext block depends on the previous one.
|
|
367
|
+
|
|
356
368
|
---
|
|
357
369
|
|
|
358
370
|
#### `dispose(): void`
|
|
@@ -535,7 +547,7 @@ and cross-stream splicing are all detected.
|
|
|
535
547
|
|
|
536
548
|
```typescript
|
|
537
549
|
class SerpentStreamSealer {
|
|
538
|
-
constructor(key: Uint8Array, chunkSize?: number)
|
|
550
|
+
constructor(key: Uint8Array, chunkSize?: number, opts?: { framed?: boolean })
|
|
539
551
|
header(): Uint8Array // call once before seal() — returns 20 bytes
|
|
540
552
|
seal(plaintext: Uint8Array): Uint8Array // exactly chunkSize bytes
|
|
541
553
|
final(plaintext: Uint8Array): Uint8Array // <= chunkSize bytes; wipes on return
|
|
@@ -543,8 +555,9 @@ class SerpentStreamSealer {
|
|
|
543
555
|
}
|
|
544
556
|
|
|
545
557
|
class SerpentStreamOpener {
|
|
546
|
-
constructor(key: Uint8Array, header: Uint8Array)
|
|
558
|
+
constructor(key: Uint8Array, header: Uint8Array, opts?: { framed?: boolean })
|
|
547
559
|
open(chunk: Uint8Array): Uint8Array // throws on auth failure or post-final
|
|
560
|
+
feed(bytes: Uint8Array): Uint8Array[] // framed mode only — accumulates and parses frames
|
|
548
561
|
dispose(): void
|
|
549
562
|
}
|
|
550
563
|
```
|
|
@@ -576,12 +589,18 @@ wipes its key material and transitions to `dead`. Subsequent `open()` calls thro
|
|
|
576
589
|
|
|
577
590
|
---
|
|
578
591
|
|
|
579
|
-
#### `constructor(key, chunkSize?)`
|
|
592
|
+
#### `constructor(key, chunkSize?, opts?)`
|
|
580
593
|
|
|
581
594
|
- **key** — 64-byte key. Throws `RangeError` if wrong length.
|
|
582
595
|
- **chunkSize** — bytes per chunk. Must be 1024–65536. Default: 65536. Throws
|
|
583
596
|
`RangeError` if out of range.
|
|
584
597
|
|
|
598
|
+
##### Options (`opts`)
|
|
599
|
+
|
|
600
|
+
| Option | Type | Default | Description |
|
|
601
|
+
|--------|------|---------|-------------|
|
|
602
|
+
| `framed` | `boolean` | `false` | Prepend `u32be(sealedLen)` to each `seal()`/`final()` output. Use for flat byte streams (files, pipes, TCP). Omit when the transport already frames messages (WebSocket, IPC). |
|
|
603
|
+
|
|
585
604
|
---
|
|
586
605
|
|
|
587
606
|
#### `header()`
|
|
@@ -615,12 +634,18 @@ Safe to call after `final()` — no-op if already dead.
|
|
|
615
634
|
|
|
616
635
|
---
|
|
617
636
|
|
|
618
|
-
#### `constructor(key, header)` (opener)
|
|
637
|
+
#### `constructor(key, header, opts?)` (opener)
|
|
619
638
|
|
|
620
639
|
- **key** — 64-byte key. Throws `RangeError` if wrong length.
|
|
621
640
|
- **header** — 20-byte stream header from `sealer.header()`. Throws `RangeError`
|
|
622
641
|
if wrong length.
|
|
623
642
|
|
|
643
|
+
##### Options (`opts`)
|
|
644
|
+
|
|
645
|
+
| Option | Type | Default | Description |
|
|
646
|
+
|--------|------|---------|-------------|
|
|
647
|
+
| `framed` | `boolean` | `false` | Enable byte-accumulation mode. Parses `u32be` length prefixes and dispatches complete frames to `open()` internally. Required to use `feed()`. |
|
|
648
|
+
|
|
624
649
|
---
|
|
625
650
|
|
|
626
651
|
#### `open(chunk)`
|
|
@@ -631,6 +656,15 @@ plaintext bytes (PKCS7 padding stripped).
|
|
|
631
656
|
|
|
632
657
|
---
|
|
633
658
|
|
|
659
|
+
#### `feed(bytes: Uint8Array): Uint8Array[]`
|
|
660
|
+
|
|
661
|
+
Only callable when constructed with `{ framed: true }`. Accumulates incoming bytes,
|
|
662
|
+
parses `u32be` length prefixes, dispatches complete frames to `open()` internally.
|
|
663
|
+
Returns an array of decrypted chunks — zero, one, or more per call depending on how
|
|
664
|
+
many complete frames were buffered. Throws if called on an unframed opener.
|
|
665
|
+
|
|
666
|
+
---
|
|
667
|
+
|
|
634
668
|
#### `dispose()` (opener)
|
|
635
669
|
|
|
636
670
|
Wipes key material. Safe to call at any point — use to abort opening a stream
|
package/dist/docs/utils.md
CHANGED
|
@@ -143,6 +143,26 @@ Returns `n` cryptographically secure random bytes via the Web Crypto API (`crypt
|
|
|
143
143
|
|
|
144
144
|
---
|
|
145
145
|
|
|
146
|
+
### hasSIMD
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
hasSIMD(): boolean
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Returns `true` if the current runtime supports WebAssembly SIMD (the `v128`
|
|
153
|
+
type and associated operations). The result is computed once on first call by
|
|
154
|
+
validating a minimal v128 WASM module, then cached for subsequent calls.
|
|
155
|
+
|
|
156
|
+
This function is called internally by `SerpentCtr.encryptChunk`,
|
|
157
|
+
`SerpentCbc.decrypt`, and `ChaCha20.encryptChunk` to select the fast SIMD path
|
|
158
|
+
at runtime. It is exported for informational purposes — you do not need to call
|
|
159
|
+
it yourself. SIMD dispatch is fully automatic.
|
|
160
|
+
|
|
161
|
+
Supported in all modern browsers and Node.js 16+. Returns `false` in older
|
|
162
|
+
environments, which fall back silently to the scalar path.
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
146
166
|
## Usage Examples
|
|
147
167
|
|
|
148
168
|
### Converting between formats
|
|
@@ -258,6 +278,7 @@ console.log(combined.length) // 32
|
|
|
258
278
|
| `constantTimeEqual` | Arrays differ in length | Returns `false` immediately |
|
|
259
279
|
| `xor` | Arrays differ in length | Throws `RangeError` |
|
|
260
280
|
| `randomBytes` | `crypto` not available | Throws (runtime-dependent) |
|
|
281
|
+
| `hasSIMD` | `WebAssembly` not available | Returns `false` |
|
|
261
282
|
|
|
262
283
|
---
|
|
263
284
|
|