leviathan-crypto 1.3.1 → 2.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 +129 -76
- package/README.md +166 -221
- package/SECURITY.md +89 -37
- package/dist/chacha20/cipher-suite.d.ts +4 -0
- package/dist/chacha20/cipher-suite.js +78 -0
- package/dist/chacha20/embedded.d.ts +1 -0
- package/dist/chacha20/embedded.js +27 -0
- package/dist/chacha20/index.d.ts +20 -7
- package/dist/chacha20/index.js +41 -14
- 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 +320 -0
- package/dist/docs/architecture.md +419 -285
- package/dist/docs/argon2id.md +42 -30
- package/dist/docs/chacha20.md +218 -150
- package/dist/docs/exports.md +241 -0
- package/dist/docs/fortuna.md +65 -74
- package/dist/docs/init.md +172 -178
- package/dist/docs/loader.md +87 -132
- package/dist/docs/serpent.md +134 -565
- package/dist/docs/sha2.md +91 -103
- package/dist/docs/sha3.md +70 -36
- package/dist/docs/types.md +93 -16
- package/dist/docs/utils.md +114 -41
- package/dist/embedded/chacha20.d.ts +1 -1
- package/dist/embedded/chacha20.js +2 -1
- 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 +2 -1
- package/dist/embedded/sha2.d.ts +1 -1
- package/dist/embedded/sha2.js +2 -1
- package/dist/embedded/sha3.d.ts +1 -1
- package/dist/embedded/sha3.js +2 -1
- package/dist/errors.d.ts +10 -0
- package/dist/{serpent/seal.js → errors.js} +14 -46
- package/dist/fortuna.d.ts +2 -8
- package/dist/fortuna.js +11 -9
- 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 +93 -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 +19 -4
- package/dist/loader.js +91 -25
- package/dist/serpent/cipher-suite.d.ts +4 -0
- package/dist/serpent/cipher-suite.js +121 -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 +202 -0
- package/dist/serpent/serpent-cbc.d.ts +30 -0
- package/dist/serpent/serpent-cbc.js +136 -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 +391 -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 +24 -0
- package/dist/stream/types.js +26 -0
- package/dist/utils.d.ts +12 -7
- package/dist/utils.js +75 -19
- 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 -188
- package/dist/chacha20/pool.worker.js +0 -37
- 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/stream-pool.d.ts +0 -48
- package/dist/serpent/stream-pool.js +0 -285
- package/dist/serpent/stream-sealer.d.ts +0 -50
- package/dist/serpent/stream-sealer.js +0 -341
- 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/embedded/sha3.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const
|
|
1
|
+
export declare const WASM_GZ_BASE64 = "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";
|
package/dist/embedded/sha3.js
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
// Generated by scripts/embed-wasm.ts — do not edit
|
|
2
|
-
|
|
2
|
+
// gzip-compressed WASM binary, base64-encoded. Decoded and decompressed by loadEmbedded().
|
|
3
|
+
export const WASM_GZ_BASE64 = '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';
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thrown when AEAD authentication fails.
|
|
3
|
+
*
|
|
4
|
+
* `cipher` is the cipher name passed by the call site (e.g. `'serpent'`,
|
|
5
|
+
* `'chacha20-poly1305'`, `'xchacha20-poly1305'`). The class appends
|
|
6
|
+
* `': authentication failed'` — do not include that text in the cipher name.
|
|
7
|
+
*/
|
|
8
|
+
export declare class AuthenticationError extends Error {
|
|
9
|
+
constructor(cipher: string);
|
|
10
|
+
}
|
|
@@ -19,52 +19,20 @@
|
|
|
19
19
|
// ▀██████▀ ▀████▄▄▄████▀ for its {ab,mis,}use.
|
|
20
20
|
// ▀█████▀▀
|
|
21
21
|
//
|
|
22
|
-
// src/ts/
|
|
22
|
+
// src/ts/errors.ts
|
|
23
23
|
//
|
|
24
|
-
//
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
this.
|
|
36
|
-
this.
|
|
37
|
-
}
|
|
38
|
-
// _iv: test seam only — inject a fixed IV for deterministic KAT vectors
|
|
39
|
-
encrypt(key, plaintext, _iv) {
|
|
40
|
-
if (key.length !== 64)
|
|
41
|
-
throw new RangeError(`SerpentSeal key must be 64 bytes (got ${key.length})`);
|
|
42
|
-
const encKey = key.subarray(0, 32);
|
|
43
|
-
const macKey = key.subarray(32, 64);
|
|
44
|
-
const iv = (_iv && _iv.length === 16) ? _iv : new Uint8Array(16);
|
|
45
|
-
if (!_iv || _iv.length !== 16)
|
|
46
|
-
crypto.getRandomValues(iv);
|
|
47
|
-
const ciphertext = this._cbc.encrypt(encKey, iv, plaintext);
|
|
48
|
-
const tag = this._hmac.hash(macKey, concat(iv, ciphertext));
|
|
49
|
-
return concat(concat(iv, ciphertext), tag);
|
|
50
|
-
}
|
|
51
|
-
decrypt(key, data) {
|
|
52
|
-
if (key.length !== 64)
|
|
53
|
-
throw new RangeError(`SerpentSeal key must be 64 bytes (got ${key.length})`);
|
|
54
|
-
if (data.length < 64)
|
|
55
|
-
throw new RangeError('SerpentSeal ciphertext too short');
|
|
56
|
-
const encKey = key.subarray(0, 32);
|
|
57
|
-
const macKey = key.subarray(32, 64);
|
|
58
|
-
const iv = data.subarray(0, 16);
|
|
59
|
-
const tag = data.subarray(data.length - 32);
|
|
60
|
-
const ciphertext = data.subarray(16, data.length - 32);
|
|
61
|
-
const expectedTag = this._hmac.hash(macKey, concat(iv, ciphertext));
|
|
62
|
-
if (!constantTimeEqual(tag, expectedTag))
|
|
63
|
-
throw new Error('SerpentSeal: authentication failed');
|
|
64
|
-
return this._cbc.decrypt(encKey, iv, ciphertext);
|
|
65
|
-
}
|
|
66
|
-
dispose() {
|
|
67
|
-
this._cbc.dispose();
|
|
68
|
-
this._hmac.dispose();
|
|
24
|
+
// Typed error classes for leviathan-crypto.
|
|
25
|
+
/**
|
|
26
|
+
* Thrown when AEAD authentication fails.
|
|
27
|
+
*
|
|
28
|
+
* `cipher` is the cipher name passed by the call site (e.g. `'serpent'`,
|
|
29
|
+
* `'chacha20-poly1305'`, `'xchacha20-poly1305'`). The class appends
|
|
30
|
+
* `': authentication failed'` — do not include that text in the cipher name.
|
|
31
|
+
*/
|
|
32
|
+
export class AuthenticationError extends Error {
|
|
33
|
+
constructor(cipher) {
|
|
34
|
+
super(`${cipher}: authentication failed`);
|
|
35
|
+
this.name = 'AuthenticationError';
|
|
36
|
+
Object.setPrototypeOf(this, AuthenticationError.prototype);
|
|
69
37
|
}
|
|
70
38
|
}
|
package/dist/fortuna.d.ts
CHANGED
|
@@ -30,20 +30,14 @@ export declare class Fortuna {
|
|
|
30
30
|
entropy?: Uint8Array;
|
|
31
31
|
}): Promise<Fortuna>;
|
|
32
32
|
private constructor();
|
|
33
|
-
/** Get n random bytes.
|
|
34
|
-
get(length: number): Uint8Array
|
|
33
|
+
/** Get n random bytes. Always returns Uint8Array — instance is guaranteed seeded after create(). */
|
|
34
|
+
get(length: number): Uint8Array;
|
|
35
35
|
/** Add external entropy to the pools. */
|
|
36
36
|
addEntropy(entropy: Uint8Array): void;
|
|
37
37
|
/** Get estimated available entropy in bytes. */
|
|
38
38
|
getEntropy(): number;
|
|
39
39
|
/** Permanently dispose this instance. Wipes key material, stops all collectors. */
|
|
40
40
|
stop(): void;
|
|
41
|
-
/** @internal — exposed for testing key replacement */
|
|
42
|
-
_getGenKey(): Uint8Array;
|
|
43
|
-
/** @internal — exposed for testing pool state */
|
|
44
|
-
_getPoolEntropy(): number[];
|
|
45
|
-
/** @internal — exposed for testing reseed count */
|
|
46
|
-
_getReseedCnt(): number;
|
|
47
41
|
/** Generate n blocks of 16 bytes each. — spec §9.4 */
|
|
48
42
|
private generateBlocks;
|
|
49
43
|
/** Get length pseudo-random bytes. — spec §9.4 */
|
package/dist/fortuna.js
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
//
|
|
24
24
|
// Fortuna CSPRNG — Ferguson & Schneier, Practical Cryptography (2003), Chapter 9.
|
|
25
25
|
// Backed by WASM Serpent-256 ECB (generator) and WASM SHA-256 (accumulator pools).
|
|
26
|
-
// Requires init(
|
|
26
|
+
// Requires init({ serpent: ..., sha2: ... }) before Fortuna.create().
|
|
27
27
|
import { isInitialized } from './init.js';
|
|
28
28
|
import { Serpent } from './serpent/index.js';
|
|
29
29
|
import { SHA256 } from './sha2/index.js';
|
|
@@ -63,11 +63,15 @@ export class Fortuna {
|
|
|
63
63
|
// ── Static factory ────────────────────────────────────────────────────
|
|
64
64
|
static async create(opts) {
|
|
65
65
|
if (!isInitialized('serpent'))
|
|
66
|
-
throw new Error('leviathan-crypto: call init(
|
|
66
|
+
throw new Error('leviathan-crypto: call init({ serpent: ..., sha2: ... }) before using Fortuna');
|
|
67
67
|
if (!isInitialized('sha2'))
|
|
68
|
-
throw new Error('leviathan-crypto: call init(
|
|
68
|
+
throw new Error('leviathan-crypto: call init({ serpent: ..., sha2: ... }) before using Fortuna');
|
|
69
69
|
const f = new Fortuna(opts?.msPerReseed ?? Fortuna.MS_PER_RESEED);
|
|
70
70
|
f.initialize(opts?.entropy);
|
|
71
|
+
// Force the first reseed — pool[0] is saturated by initialize(),
|
|
72
|
+
// so this call triggers an immediate reseed and guarantees get() never
|
|
73
|
+
// returns undefined. The byte is discarded.
|
|
74
|
+
f.get(1);
|
|
71
75
|
return f;
|
|
72
76
|
}
|
|
73
77
|
constructor(msPerReseed) {
|
|
@@ -91,7 +95,7 @@ export class Fortuna {
|
|
|
91
95
|
}
|
|
92
96
|
}
|
|
93
97
|
// ── Public API ────────────────────────────────────────────────────────
|
|
94
|
-
/** Get n random bytes.
|
|
98
|
+
/** Get n random bytes. Always returns Uint8Array — instance is guaranteed seeded after create(). */
|
|
95
99
|
get(length) {
|
|
96
100
|
if (this.disposed)
|
|
97
101
|
throw new Error('Fortuna instance has been disposed');
|
|
@@ -117,8 +121,6 @@ export class Fortuna {
|
|
|
117
121
|
this.entropyLevel -= strength;
|
|
118
122
|
this.reseed(seed);
|
|
119
123
|
}
|
|
120
|
-
if (this.reseedCnt === 0)
|
|
121
|
-
return undefined;
|
|
122
124
|
return this.pseudoRandomData(length);
|
|
123
125
|
}
|
|
124
126
|
/** Add external entropy to the pools. */
|
|
@@ -171,8 +173,8 @@ export class Fortuna {
|
|
|
171
173
|
}
|
|
172
174
|
/** Get length pseudo-random bytes. — spec §9.4 */
|
|
173
175
|
pseudoRandomData(length) {
|
|
174
|
-
// Generate ceil(length/16)
|
|
175
|
-
const blocks = Math.ceil(length / 16)
|
|
176
|
+
// Generate ceil(length/16) blocks — spec §9.4
|
|
177
|
+
const blocks = Math.ceil(length / 16);
|
|
176
178
|
const raw = this.generateBlocks(blocks);
|
|
177
179
|
const output = raw.slice(0, length);
|
|
178
180
|
// Key replacement — mandatory forward secrecy (spec §9.4)
|
|
@@ -205,7 +207,7 @@ export class Fortuna {
|
|
|
205
207
|
id[3] = (this.eventId >>> 24) & 0xff;
|
|
206
208
|
this.eventId = (this.eventId + 1) >>> 0; // u32 wrap
|
|
207
209
|
// Chain: poolHash[i] = SHA256(poolHash[i] ‖ id ‖ data)
|
|
208
|
-
this.poolHash[poolIdx] = this.sha.hash(concat(
|
|
210
|
+
this.poolHash[poolIdx] = this.sha.hash(concat(this.poolHash[poolIdx], id, data));
|
|
209
211
|
this.poolEntropy[poolIdx] += entropyBits;
|
|
210
212
|
this.entropyLevel += entropyBits;
|
|
211
213
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,29 @@
|
|
|
1
|
-
import type { Module
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import type { Module } from './init.js';
|
|
2
|
+
import type { WasmSource } from './wasm-source.js';
|
|
3
|
+
/**
|
|
4
|
+
* Load one or more WASM modules. Each key is a module name; the value is the
|
|
5
|
+
* WasmSource to load it from (embedded blob, URL, ArrayBuffer, etc.).
|
|
6
|
+
*
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { init } from 'leviathan-crypto';
|
|
9
|
+
* import { serpentWasm } from 'leviathan-crypto/serpent/embedded';
|
|
10
|
+
* import { sha2Wasm } from 'leviathan-crypto/sha2/embedded';
|
|
11
|
+
* await init({ serpent: serpentWasm, sha2: sha2Wasm });
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export declare function init(sources: Partial<Record<Module, WasmSource>>): Promise<void>;
|
|
15
|
+
export type { Module, WasmSource };
|
|
16
|
+
export { isInitialized, _resetForTesting } from './init.js';
|
|
17
|
+
export { AuthenticationError } from './errors.js';
|
|
18
|
+
export { serpentInit, Serpent, SerpentCtr, SerpentCbc, SerpentCipher, _serpentReady } from './serpent/index.js';
|
|
19
|
+
export { chacha20Init, ChaCha20, Poly1305, ChaCha20Poly1305, XChaCha20Poly1305, XChaCha20Cipher, _chachaReady } from './chacha20/index.js';
|
|
9
20
|
export { sha2Init, SHA256, SHA512, SHA384, HMAC_SHA256, HMAC_SHA512, HMAC_SHA384, HKDF_SHA256, HKDF_SHA512, _sha2Ready } from './sha2/index.js';
|
|
10
21
|
export { sha3Init, SHA3_224, SHA3_256, SHA3_384, SHA3_512, SHAKE128, SHAKE256, _sha3Ready } from './sha3/index.js';
|
|
22
|
+
export { keccakInit } from './keccak/index.js';
|
|
23
|
+
export { kyberInit, MlKem512, MlKem768, MlKem1024, MlKemBase, KyberSuite, _kyberReady } from './kyber/index.js';
|
|
24
|
+
export type { KyberKeyPair, KyberEncapsulation, KyberParams } from './kyber/index.js';
|
|
25
|
+
export { SealStream, OpenStream, Seal, SealStreamPool, FLAG_FRAMED, TAG_DATA, TAG_FINAL, HEADER_SIZE, CHUNK_MIN, CHUNK_MAX } from './stream/index.js';
|
|
26
|
+
export type { CipherSuite, DerivedKeys, SealStreamOpts, PoolOpts } from './stream/index.js';
|
|
11
27
|
export { Fortuna } from './fortuna.js';
|
|
12
28
|
export type { Hash, KeyedHash, Blockcipher, Streamcipher, AEAD } from './types.js';
|
|
13
|
-
export { hexToBytes, bytesToHex, utf8ToBytes, bytesToUtf8, base64ToBytes, bytesToBase64, constantTimeEqual, wipe, xor, concat, randomBytes, } from './utils.js';
|
|
29
|
+
export { hexToBytes, bytesToHex, utf8ToBytes, bytesToUtf8, base64ToBytes, bytesToBase64, constantTimeEqual, CT_MAX_BYTES, wipe, xor, concat, randomBytes, hasSIMD, } from './utils.js';
|
package/dist/index.js
CHANGED
|
@@ -24,21 +24,50 @@ import { serpentInit } from './serpent/index.js';
|
|
|
24
24
|
import { chacha20Init } from './chacha20/index.js';
|
|
25
25
|
import { sha2Init } from './sha2/index.js';
|
|
26
26
|
import { sha3Init } from './sha3/index.js';
|
|
27
|
+
import { keccakInit } from './keccak/index.js';
|
|
28
|
+
import { kyberInit } from './kyber/index.js';
|
|
29
|
+
import { hasSIMD } from './utils.js';
|
|
27
30
|
const _dispatchers = {
|
|
28
31
|
serpent: serpentInit,
|
|
29
32
|
chacha20: chacha20Init,
|
|
30
33
|
sha2: sha2Init,
|
|
31
34
|
sha3: sha3Init,
|
|
35
|
+
keccak: keccakInit,
|
|
36
|
+
kyber: kyberInit,
|
|
32
37
|
};
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
38
|
+
/**
|
|
39
|
+
* Load one or more WASM modules. Each key is a module name; the value is the
|
|
40
|
+
* WasmSource to load it from (embedded blob, URL, ArrayBuffer, etc.).
|
|
41
|
+
*
|
|
42
|
+
* ```ts
|
|
43
|
+
* import { init } from 'leviathan-crypto';
|
|
44
|
+
* import { serpentWasm } from 'leviathan-crypto/serpent/embedded';
|
|
45
|
+
* import { sha2Wasm } from 'leviathan-crypto/sha2/embedded';
|
|
46
|
+
* await init({ serpent: serpentWasm, sha2: sha2Wasm });
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export async function init(sources) {
|
|
50
|
+
const entries = Object.entries(sources);
|
|
51
|
+
// SIMD preflight — serpent, chacha20, and kyber modules contain SIMD instructions
|
|
52
|
+
if (('serpent' in sources || 'chacha20' in sources || 'kyber' in sources) && !hasSIMD())
|
|
53
|
+
throw new Error('leviathan-crypto: serpent, chacha20, and kyber require WebAssembly SIMD — '
|
|
54
|
+
+ 'this runtime does not support it');
|
|
55
|
+
for (const [mod, src] of entries) {
|
|
56
|
+
if (!Object.hasOwn(_dispatchers, mod))
|
|
57
|
+
throw new Error(`leviathan-crypto: unknown module "${mod}" — expected one of: ${Object.keys(_dispatchers).join(', ')}`);
|
|
58
|
+
if (src == null)
|
|
59
|
+
throw new TypeError(`leviathan-crypto: source for "${mod}" is null or undefined`);
|
|
60
|
+
}
|
|
61
|
+
await Promise.all(entries.map(([mod, src]) => _dispatchers[mod](src)));
|
|
36
62
|
}
|
|
37
63
|
export { isInitialized, _resetForTesting } from './init.js';
|
|
38
|
-
export {
|
|
39
|
-
export {
|
|
40
|
-
export {
|
|
64
|
+
export { AuthenticationError } from './errors.js';
|
|
65
|
+
export { serpentInit, Serpent, SerpentCtr, SerpentCbc, SerpentCipher, _serpentReady } from './serpent/index.js';
|
|
66
|
+
export { chacha20Init, ChaCha20, Poly1305, ChaCha20Poly1305, XChaCha20Poly1305, XChaCha20Cipher, _chachaReady } from './chacha20/index.js';
|
|
41
67
|
export { sha2Init, SHA256, SHA512, SHA384, HMAC_SHA256, HMAC_SHA512, HMAC_SHA384, HKDF_SHA256, HKDF_SHA512, _sha2Ready } from './sha2/index.js';
|
|
42
68
|
export { sha3Init, SHA3_224, SHA3_256, SHA3_384, SHA3_512, SHAKE128, SHAKE256, _sha3Ready } from './sha3/index.js';
|
|
69
|
+
export { keccakInit } from './keccak/index.js';
|
|
70
|
+
export { kyberInit, MlKem512, MlKem768, MlKem1024, MlKemBase, KyberSuite, _kyberReady } from './kyber/index.js';
|
|
71
|
+
export { SealStream, OpenStream, Seal, SealStreamPool, FLAG_FRAMED, TAG_DATA, TAG_FINAL, HEADER_SIZE, CHUNK_MIN, CHUNK_MAX } from './stream/index.js';
|
|
43
72
|
export { Fortuna } from './fortuna.js';
|
|
44
|
-
export { hexToBytes, bytesToHex, utf8ToBytes, bytesToUtf8, base64ToBytes, bytesToBase64, constantTimeEqual, wipe, xor, concat, randomBytes, } from './utils.js';
|
|
73
|
+
export { hexToBytes, bytesToHex, utf8ToBytes, bytesToUtf8, base64ToBytes, bytesToBase64, constantTimeEqual, CT_MAX_BYTES, wipe, xor, concat, randomBytes, hasSIMD, } from './utils.js';
|
package/dist/init.d.ts
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
export type
|
|
3
|
-
export
|
|
4
|
-
wasmUrl?: URL | string;
|
|
5
|
-
wasmBinary?: Partial<Record<Module, Uint8Array | ArrayBuffer>>;
|
|
6
|
-
}
|
|
7
|
-
export declare function initModule(mod: Module, embeddedThunk: () => Promise<string>, mode?: Mode, opts?: InitOpts): Promise<void>;
|
|
1
|
+
import type { WasmSource } from './wasm-source.js';
|
|
2
|
+
export type Module = 'serpent' | 'chacha20' | 'sha2' | 'sha3' | 'keccak' | 'kyber';
|
|
3
|
+
export declare function initModule(mod: Module, source: WasmSource): Promise<void>;
|
|
8
4
|
export declare function getInstance(mod: Module): WebAssembly.Instance;
|
|
9
5
|
export declare function isInitialized(mod: Module): boolean;
|
|
10
6
|
/** Reset all cached instances — for testing only */
|
package/dist/init.js
CHANGED
|
@@ -1,47 +1,30 @@
|
|
|
1
|
-
|
|
1
|
+
import { loadWasm } from './loader.js';
|
|
2
|
+
import { hasSIMD } from './utils.js';
|
|
3
|
+
// 'keccak' is an alias for 'sha3' — same WASM binary, same instance slot
|
|
4
|
+
const ALIASES = { keccak: 'sha3' };
|
|
5
|
+
function resolve(mod) {
|
|
6
|
+
return ALIASES[mod] ?? mod;
|
|
7
|
+
}
|
|
8
|
+
// Module-scope cache: one WebAssembly.Instance per canonical module
|
|
2
9
|
const instances = new Map();
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
chacha20: 'chacha20.wasm',
|
|
7
|
-
sha2: 'sha2.wasm',
|
|
8
|
-
sha3: 'sha3.wasm',
|
|
9
|
-
};
|
|
10
|
-
export async function initModule(mod, embeddedThunk, mode = 'embedded', opts) {
|
|
11
|
-
if (instances.has(mod))
|
|
10
|
+
export async function initModule(mod, source) {
|
|
11
|
+
const resolved = resolve(mod);
|
|
12
|
+
if (instances.has(resolved))
|
|
12
13
|
return;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
else if (mode === 'streaming') {
|
|
19
|
-
if (!opts?.wasmUrl)
|
|
20
|
-
throw new Error('leviathan-crypto: streaming mode requires wasmUrl');
|
|
21
|
-
const { loadStreaming } = await import('./loader.js');
|
|
22
|
-
instance = await loadStreaming(mod, opts.wasmUrl, WASM_FILES[mod]);
|
|
23
|
-
}
|
|
24
|
-
else if (mode === 'manual') {
|
|
25
|
-
const binary = opts?.wasmBinary?.[mod];
|
|
26
|
-
if (!binary)
|
|
27
|
-
throw new Error(`leviathan-crypto: manual mode requires wasmBinary['${mod}']`);
|
|
28
|
-
const { loadManual } = await import('./loader.js');
|
|
29
|
-
instance = await loadManual(binary);
|
|
30
|
-
}
|
|
31
|
-
else {
|
|
32
|
-
throw new Error(`leviathan-crypto: unknown mode '${mode}'`);
|
|
33
|
-
}
|
|
34
|
-
instances.set(mod, instance);
|
|
14
|
+
if ((resolved === 'serpent' || resolved === 'chacha20' || resolved === 'kyber') && !hasSIMD())
|
|
15
|
+
throw new Error('leviathan-crypto: serpent, chacha20, and kyber require WebAssembly SIMD — '
|
|
16
|
+
+ 'this runtime does not support it');
|
|
17
|
+
instances.set(resolved, await loadWasm(source));
|
|
35
18
|
}
|
|
36
19
|
export function getInstance(mod) {
|
|
37
|
-
const inst = instances.get(mod);
|
|
20
|
+
const inst = instances.get(resolve(mod));
|
|
38
21
|
if (!inst) {
|
|
39
|
-
throw new Error(`leviathan-crypto: call init(
|
|
22
|
+
throw new Error(`leviathan-crypto: call init({ ${mod}: ... }) before using this class`);
|
|
40
23
|
}
|
|
41
24
|
return inst;
|
|
42
25
|
}
|
|
43
26
|
export function isInitialized(mod) {
|
|
44
|
-
return instances.has(mod);
|
|
27
|
+
return instances.has(resolve(mod));
|
|
45
28
|
}
|
|
46
29
|
/** Reset all cached instances — for testing only */
|
|
47
30
|
export function _resetForTesting() {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { WASM_GZ_BASE64 as keccakWasm } from '../embedded/sha3.js';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// ▄▄▄▄▄▄▄▄▄▄
|
|
2
|
+
// ▄████████████████████▄▄ ▒ ▄▀▀ ▒ ▒ █ ▄▀▄ ▀█▀ █ ▒ ▄▀▄ █▀▄
|
|
3
|
+
// ▄██████████████████████ ▀████▄ ▓ ▓▀ ▓ ▓ ▓ ▓▄▓ ▓ ▓▀▓ ▓▄▓ ▓ ▓
|
|
4
|
+
// ▄█████████▀▀▀ ▀███████▄▄███████▌ ▀▄ ▀▄▄ ▀▄▀ ▒ ▒ ▒ ▒ ▒ █ ▒ ▒ ▒ █
|
|
5
|
+
// ▐████████▀ ▄▄▄▄ ▀████████▀██▀█▌
|
|
6
|
+
// ████████ ███▀▀ ████▀ █▀ █▀ Leviathan Crypto Library
|
|
7
|
+
// ███████▌ ▀██▀ ███
|
|
8
|
+
// ███████ ▀███ ▀██ ▀█▄ Repository & Mirror:
|
|
9
|
+
// ▀██████ ▄▄██ ▀▀ ██▄ github.com/xero/leviathan-crypto
|
|
10
|
+
// ▀█████▄ ▄██▄ ▄▀▄▀ unpkg.com/leviathan-crypto
|
|
11
|
+
// ▀████▄ ▄██▄
|
|
12
|
+
// ▐████ ▐███ Author: xero (https://x-e.ro)
|
|
13
|
+
// ▄▄██████████ ▐███ ▄▄ License: MIT
|
|
14
|
+
// ▄██▀▀▀▀▀▀▀▀▀▀ ▄████ ▄██▀
|
|
15
|
+
// ▄▀ ▄▄█████████▄▄ ▀▀▀▀▀ ▄███ This file is provided completely
|
|
16
|
+
// ▄██████▀▀▀▀▀▀██████▄ ▀▄▄▄▄████▀ free, "as is", and without
|
|
17
|
+
// ████▀ ▄▄▄▄▄▄▄ ▀████▄ ▀█████▀ ▄▄▄▄ warranty of any kind. The author
|
|
18
|
+
// █████▄▄█████▀▀▀▀▀▀▄ ▀███▄ ▄████ assumes absolutely no liability
|
|
19
|
+
// ▀██████▀ ▀████▄▄▄████▀ for its {ab,mis,}use.
|
|
20
|
+
// ▀█████▀▀
|
|
21
|
+
//
|
|
22
|
+
// src/ts/keccak/embedded.ts
|
|
23
|
+
//
|
|
24
|
+
// Re-exports the sha3 WASM blob under the keccak name.
|
|
25
|
+
// The keccak alias shares the sha3 binary — no separate keccak.wasm exists.
|
|
26
|
+
// Import via `leviathan-crypto/keccak/embedded`.
|
|
27
|
+
export { WASM_GZ_BASE64 as keccakWasm } from '../embedded/sha3.js';
|
|
@@ -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/keccak/index.ts
|
|
23
|
+
//
|
|
24
|
+
// Keccak alias subpath — resolves to the sha3 WASM module slot.
|
|
25
|
+
// Consumers who prefer the Keccak name (e.g. Kyber/ML-KEM implementations)
|
|
26
|
+
// can import from `leviathan-crypto/keccak` instead of `leviathan-crypto/sha3`.
|
|
27
|
+
import { initModule } from '../init.js';
|
|
28
|
+
export async function keccakInit(source) {
|
|
29
|
+
return initModule('keccak', source);
|
|
30
|
+
}
|
|
31
|
+
export { SHA3_224, SHA3_256, SHA3_384, SHA3_512, SHAKE128, SHAKE256 } from '../sha3/index.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { WASM_GZ_BASE64 as kyberWasm } from '../embedded/kyber.js';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// ▄▄▄▄▄▄▄▄▄▄
|
|
2
|
+
// ▄████████████████████▄▄ ▒ ▄▀▀ ▒ ▒ █ ▄▀▄ ▀█▀ █ ▒ ▄▀▄ █▀▄
|
|
3
|
+
// ▄██████████████████████ ▀████▄ ▓ ▓▀ ▓ ▓ ▓ ▓▄▓ ▓ ▓▀▓ ▓▄▓ ▓ ▓
|
|
4
|
+
// ▄█████████▀▀▀ ▀███████▄▄███████▌ ▀▄ ▀▄▄ ▀▄▀ ▒ ▒ ▒ ▒ ▒ █ ▒ ▒ ▒ █
|
|
5
|
+
// ▐████████▀ ▄▄▄▄ ▀████████▀██▀█▌
|
|
6
|
+
// ████████ ███▀▀ ████▀ █▀ █▀ Leviathan Crypto Library
|
|
7
|
+
// ███████▌ ▀██▀ ███
|
|
8
|
+
// ███████ ▀███ ▀██ ▀█▄ Repository & Mirror:
|
|
9
|
+
// ▀██████ ▄▄██ ▀▀ ██▄ github.com/xero/leviathan-crypto
|
|
10
|
+
// ▀█████▄ ▄██▄ ▄▀▄▀ unpkg.com/leviathan-crypto
|
|
11
|
+
// ▀████▄ ▄██▄
|
|
12
|
+
// ▐████ ▐███ Author: xero (https://x-e.ro)
|
|
13
|
+
// ▄▄██████████ ▐███ ▄▄ License: MIT
|
|
14
|
+
// ▄██▀▀▀▀▀▀▀▀▀▀ ▄████ ▄██▀
|
|
15
|
+
// ▄▀ ▄▄█████████▄▄ ▀▀▀▀▀ ▄███ This file is provided completely
|
|
16
|
+
// ▄██████▀▀▀▀▀▀██████▄ ▀▄▄▄▄████▀ free, "as is", and without
|
|
17
|
+
// ████▀ ▄▄▄▄▄▄▄ ▀████▄ ▀█████▀ ▄▄▄▄ warranty of any kind. The author
|
|
18
|
+
// █████▄▄█████▀▀▀▀▀▀▄ ▀███▄ ▄████ assumes absolutely no liability
|
|
19
|
+
// ▀██████▀ ▀████▄▄▄████▀ for its {ab,mis,}use.
|
|
20
|
+
// ▀█████▀▀
|
|
21
|
+
//
|
|
22
|
+
// src/ts/kyber/embedded.ts
|
|
23
|
+
//
|
|
24
|
+
// Exports the gzip+base64 kyber WASM blob for use as a WasmSource.
|
|
25
|
+
// This is the only file in the kyber subpath that references the embedded blob.
|
|
26
|
+
// Import via `leviathan-crypto/kyber/embedded`.
|
|
27
|
+
export { WASM_GZ_BASE64 as kyberWasm } from '../embedded/kyber.js';
|
|
@@ -0,0 +1,49 @@
|
|
|
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;
|