leviathan-crypto 2.0.1 → 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 +88 -281
- package/LICENSE +4 -0
- package/README.md +275 -87
- 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.d.ts +10 -0
- package/dist/chacha20/cipher-suite.js +98 -13
- package/dist/chacha20/generator.d.ts +12 -0
- package/dist/chacha20/generator.js +91 -0
- package/dist/chacha20/index.d.ts +100 -3
- package/dist/chacha20/index.js +169 -35
- package/dist/chacha20/ops.d.ts +57 -6
- package/dist/chacha20/ops.js +107 -27
- package/dist/chacha20/pool-worker.js +14 -0
- package/dist/chacha20/types.d.ts +1 -32
- package/dist/cte-wasm.d.ts +1 -0
- package/dist/cte-wasm.js +3 -0
- package/dist/cte.wasm +0 -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 -0
- package/dist/embedded/chacha20-pool-worker.js +5 -0
- 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 -0
- package/dist/embedded/serpent-pool-worker.js +5 -0
- 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 +18 -12
- package/dist/fortuna.js +166 -99
- package/dist/index.d.ts +42 -11
- package/dist/index.js +65 -20
- package/dist/init.d.ts +1 -3
- package/dist/init.js +73 -7
- 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 -19
- package/dist/loader.js +26 -32
- 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 +48 -48
- package/dist/mlkem/index.d.ts +37 -0
- package/dist/{kyber → mlkem}/index.js +41 -31
- package/dist/mlkem/kem.d.ts +21 -0
- package/dist/{kyber → mlkem}/kem.js +48 -13
- 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 +4 -3
- package/dist/{kyber → mlkem}/types.js +1 -1
- package/dist/mlkem/validate.d.ts +23 -0
- package/dist/{kyber → mlkem}/validate.js +24 -20
- package/dist/{kyber.wasm → mlkem.wasm} +0 -0
- package/dist/p256.wasm +0 -0
- package/dist/ratchet/index.d.ts +8 -0
- package/dist/ratchet/index.js +38 -0
- package/dist/ratchet/kdf-chain.d.ts +13 -0
- package/dist/ratchet/kdf-chain.js +85 -0
- package/dist/ratchet/ratchet-keypair.d.ts +9 -0
- package/dist/ratchet/ratchet-keypair.js +61 -0
- package/dist/ratchet/root-kdf.d.ts +4 -0
- package/dist/ratchet/root-kdf.js +124 -0
- package/dist/ratchet/skipped-key-store.d.ts +14 -0
- package/dist/ratchet/skipped-key-store.js +154 -0
- package/dist/ratchet/types.d.ts +36 -0
- package/dist/ratchet/types.js +26 -0
- package/dist/serpent/cipher-suite.d.ts +10 -0
- package/dist/serpent/cipher-suite.js +144 -56
- package/dist/serpent/generator.d.ts +12 -0
- package/dist/serpent/generator.js +97 -0
- package/dist/serpent/index.d.ts +62 -1
- package/dist/serpent/index.js +97 -21
- package/dist/serpent/pool-worker.js +28 -102
- package/dist/serpent/serpent-cbc.d.ts +16 -6
- package/dist/serpent/serpent-cbc.js +58 -37
- package/dist/serpent/shared-ops.d.ts +63 -0
- package/dist/serpent/shared-ops.js +178 -0
- package/dist/serpent/types.d.ts +1 -5
- package/dist/serpent.wasm +0 -0
- package/dist/sha2/hash.d.ts +2 -0
- package/dist/sha2/hash.js +53 -0
- package/dist/sha2/hkdf.js +5 -5
- package/dist/sha2/index.d.ts +22 -1
- package/dist/sha2/index.js +80 -11
- package/dist/sha2/types.d.ts +41 -2
- package/dist/sha2.wasm +0 -0
- package/dist/sha3/hash.d.ts +2 -0
- package/dist/sha3/hash.js +53 -0
- package/dist/sha3/index.d.ts +87 -3
- package/dist/sha3/index.js +317 -19
- 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 +8 -8
- package/dist/stream/index.d.ts +1 -0
- package/dist/stream/index.js +1 -0
- package/dist/stream/open-stream.js +65 -22
- package/dist/stream/seal-stream-pool.d.ts +2 -0
- package/dist/stream/seal-stream-pool.js +100 -33
- package/dist/stream/seal-stream.d.ts +1 -1
- package/dist/stream/seal-stream.js +48 -19
- 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 +22 -1
- package/dist/types.js +1 -1
- package/dist/utils.d.ts +9 -10
- package/dist/utils.js +84 -59
- package/dist/wasm-source.d.ts +9 -8
- 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 +123 -64
- package/SECURITY.md +0 -276
- package/dist/ct-wasm.d.ts +0 -1
- package/dist/ct-wasm.js +0 -3
- package/dist/ct.wasm +0 -0
- package/dist/docs/aead.md +0 -323
- package/dist/docs/architecture.md +0 -932
- package/dist/docs/argon2id.md +0 -302
- package/dist/docs/chacha20.md +0 -674
- package/dist/docs/exports.md +0 -241
- package/dist/docs/fortuna.md +0 -313
- package/dist/docs/init.md +0 -302
- package/dist/docs/loader.md +0 -161
- package/dist/docs/serpent.md +0 -519
- package/dist/docs/sha2.md +0 -613
- package/dist/docs/sha3.md +0 -546
- package/dist/docs/types.md +0 -276
- package/dist/docs/utils.md +0 -367
- 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 -13
- package/dist/kyber/validate.d.ts +0 -19
|
@@ -21,56 +21,45 @@
|
|
|
21
21
|
//
|
|
22
22
|
// src/ts/serpent/serpent-cbc.ts
|
|
23
23
|
//
|
|
24
|
-
// SerpentCbc
|
|
24
|
+
// SerpentCbc, Serpent-256 CBC + PKCS7, internal module.
|
|
25
25
|
// Extracted to break the cipher-suite.ts ↔ index.ts circular dependency.
|
|
26
26
|
// Import from here directly; index.ts re-exports for the public API surface.
|
|
27
|
-
import { getInstance } from '../init.js';
|
|
27
|
+
import { getInstance, _acquireModule, _releaseModule } from '../init.js';
|
|
28
|
+
import { pkcs7Pad, pkcs7Strip, PKCS7_INVALID } from './shared-ops.js';
|
|
29
|
+
/** Returns the raw serpent WASM export object. @internal */
|
|
28
30
|
function getExports() {
|
|
29
31
|
return getInstance('serpent').exports;
|
|
30
32
|
}
|
|
31
|
-
// ── PKCS7 helpers
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
// pkcs7Strip is only called after HMAC authentication succeeds (verify-then-decrypt).
|
|
40
|
-
// The early throw on invalid padLen is not a padding oracle in this context —
|
|
41
|
-
// the HMAC check is the oracle gate and runs in constant time before this point.
|
|
42
|
-
// If you move this call to a pre-auth site, revisit the timing properties.
|
|
43
|
-
function pkcs7Strip(data) {
|
|
44
|
-
if (data.length === 0)
|
|
45
|
-
throw new RangeError('empty ciphertext');
|
|
46
|
-
const padLen = data[data.length - 1];
|
|
47
|
-
if (padLen === 0 || padLen > 16)
|
|
48
|
-
throw new RangeError(`invalid PKCS7 padding byte: ${padLen}`);
|
|
49
|
-
if (padLen > data.length)
|
|
50
|
-
throw new RangeError(`invalid PKCS7 padding: pad length ${padLen} exceeds data length ${data.length}`);
|
|
51
|
-
let bad = 0;
|
|
52
|
-
for (let i = data.length - padLen; i < data.length; i++)
|
|
53
|
-
bad |= data[i] ^ padLen;
|
|
54
|
-
if (bad !== 0)
|
|
55
|
-
throw new RangeError('invalid PKCS7 padding');
|
|
56
|
-
return data.subarray(0, data.length - padLen);
|
|
57
|
-
}
|
|
58
|
-
// ── SerpentCbc ───────────────────────────────────────────────────────────────
|
|
33
|
+
// ── PKCS7 helpers ───────────────────────────────────────────────────────────
|
|
34
|
+
//
|
|
35
|
+
// The canonical `pkcs7Pad` / `pkcs7Strip` live in `./shared-ops.ts`; this
|
|
36
|
+
// file re-uses them so the main-thread class and the pool worker share one
|
|
37
|
+
// implementation. See `shared-ops.ts` for the branch-free, Vaudenay-2002-
|
|
38
|
+
// closed padding check.
|
|
39
|
+
// ── SerpentCbc ──────────────────────────────────────────────────────────────
|
|
59
40
|
/**
|
|
60
41
|
* Serpent-256 in CBC mode with PKCS7 padding.
|
|
61
42
|
*
|
|
62
43
|
* **WARNING: CBC mode is unauthenticated.** Always authenticate the output
|
|
63
44
|
* with HMAC-SHA256 (Encrypt-then-MAC) or use `XChaCha20Poly1305` instead.
|
|
45
|
+
*
|
|
46
|
+
* Holds exclusive access to the `serpent` WASM module from construction
|
|
47
|
+
* until `dispose()`. Constructing a second SerpentCbc/SerpentCtr/
|
|
48
|
+
* SerpentCipher or any other serpent user while this instance is live
|
|
49
|
+
* throws. Call `dispose()` when done.
|
|
64
50
|
*/
|
|
65
51
|
export class SerpentCbc {
|
|
66
52
|
x;
|
|
53
|
+
_tok;
|
|
67
54
|
constructor(opts) {
|
|
68
55
|
if (!opts?.dangerUnauthenticated) {
|
|
69
|
-
throw new Error('leviathan-crypto: SerpentCbc is unauthenticated
|
|
56
|
+
throw new Error('leviathan-crypto: SerpentCbc is unauthenticated, use Seal with SerpentCipher instead. ' +
|
|
70
57
|
'To use SerpentCbc directly, pass { dangerUnauthenticated: true }.');
|
|
71
58
|
}
|
|
72
59
|
this.x = getExports();
|
|
60
|
+
this._tok = _acquireModule('serpent');
|
|
73
61
|
}
|
|
62
|
+
/** View over WASM linear memory. Rebind on every access, memory can be detached after grow. @internal */
|
|
74
63
|
get mem() {
|
|
75
64
|
return new Uint8Array(this.x.memory.buffer);
|
|
76
65
|
}
|
|
@@ -78,11 +67,13 @@ export class SerpentCbc {
|
|
|
78
67
|
* Encrypt plaintext with Serpent-256 CBC + PKCS7 padding.
|
|
79
68
|
*
|
|
80
69
|
* @param key 16, 24, or 32 bytes
|
|
81
|
-
* @param iv 16 bytes
|
|
82
|
-
* @param plaintext any length
|
|
70
|
+
* @param iv 16 bytes, must be random and unique per (key, message)
|
|
71
|
+
* @param plaintext any length, PKCS7 padding applied automatically
|
|
83
72
|
* @returns ciphertext (length = ceil((plaintext.length + 1) / 16) * 16)
|
|
84
73
|
*/
|
|
85
74
|
encrypt(key, iv, plaintext) {
|
|
75
|
+
if (this._tok === undefined)
|
|
76
|
+
throw new Error('SerpentCbc: instance has been disposed');
|
|
86
77
|
this._loadKey(key);
|
|
87
78
|
this._setIv(iv);
|
|
88
79
|
const padded = pkcs7Pad(plaintext);
|
|
@@ -103,11 +94,19 @@ export class SerpentCbc {
|
|
|
103
94
|
}
|
|
104
95
|
/**
|
|
105
96
|
* Decrypt Serpent-256 CBC + PKCS7.
|
|
106
|
-
*
|
|
97
|
+
*
|
|
98
|
+
* All failure modes, empty input, non-multiple-of-16 length, and any
|
|
99
|
+
* PKCS7 validation failure, throw the same generic `RangeError` with
|
|
100
|
+
* message `'invalid ciphertext'`. Padding validation runs branch-free
|
|
101
|
+
* over the last 16 bytes regardless of where the mismatch is, closing
|
|
102
|
+
* the Vaudenay 2002 padding-oracle surface for callers using
|
|
103
|
+
* `{ dangerUnauthenticated: true }` without an outer HMAC.
|
|
107
104
|
*/
|
|
108
105
|
decrypt(key, iv, ciphertext) {
|
|
106
|
+
if (this._tok === undefined)
|
|
107
|
+
throw new Error('SerpentCbc: instance has been disposed');
|
|
109
108
|
if (ciphertext.length === 0 || ciphertext.length % 16 !== 0)
|
|
110
|
-
throw new RangeError(
|
|
109
|
+
throw new RangeError(PKCS7_INVALID);
|
|
111
110
|
this._loadKey(key);
|
|
112
111
|
this._setIv(iv);
|
|
113
112
|
const output = new Uint8Array(ciphertext.length);
|
|
@@ -125,15 +124,37 @@ export class SerpentCbc {
|
|
|
125
124
|
}
|
|
126
125
|
return pkcs7Strip(output);
|
|
127
126
|
}
|
|
127
|
+
/** Wipe WASM state and release exclusive module access. Idempotent. */
|
|
128
128
|
dispose() {
|
|
129
|
-
this.
|
|
129
|
+
if (this._tok === undefined)
|
|
130
|
+
return;
|
|
131
|
+
try {
|
|
132
|
+
this.x.wipeBuffers();
|
|
133
|
+
}
|
|
134
|
+
finally {
|
|
135
|
+
_releaseModule('serpent', this._tok);
|
|
136
|
+
this._tok = undefined;
|
|
137
|
+
}
|
|
130
138
|
}
|
|
139
|
+
/**
|
|
140
|
+
* Validate and load `key` into the WASM key schedule.
|
|
141
|
+
* @param key 16, 24, or 32 bytes
|
|
142
|
+
* @internal
|
|
143
|
+
*/
|
|
131
144
|
_loadKey(key) {
|
|
132
145
|
if (key.length !== 16 && key.length !== 24 && key.length !== 32)
|
|
133
146
|
throw new RangeError(`Serpent key must be 16, 24, or 32 bytes (got ${key.length})`);
|
|
134
147
|
this.mem.set(key, this.x.getKeyOffset());
|
|
135
|
-
this.x.loadKey(key.length)
|
|
148
|
+
if (this.x.loadKey(key.length) !== 0) {
|
|
149
|
+
this.x.wipeBuffers();
|
|
150
|
+
throw new Error('SerpentCbc: loadKey failed');
|
|
151
|
+
}
|
|
136
152
|
}
|
|
153
|
+
/**
|
|
154
|
+
* Write `iv` into the WASM CBC IV buffer.
|
|
155
|
+
* @param iv 16 bytes
|
|
156
|
+
* @internal
|
|
157
|
+
*/
|
|
137
158
|
_setIv(iv) {
|
|
138
159
|
if (iv.length !== 16)
|
|
139
160
|
throw new RangeError(`CBC IV must be 16 bytes (got ${iv.length})`);
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
export { pkcs7Pad, pkcs7Strip, PKCS7_INVALID } from '../shared/pkcs7.js';
|
|
2
|
+
/** Subset of the sha2 WASM exports used by `hmacSha256`. */
|
|
3
|
+
export interface Sha2OpsExports {
|
|
4
|
+
memory: WebAssembly.Memory;
|
|
5
|
+
getSha256InputOffset: () => number;
|
|
6
|
+
getSha256OutOffset: () => number;
|
|
7
|
+
sha256Init: () => void;
|
|
8
|
+
sha256Update: (len: number) => void;
|
|
9
|
+
sha256Final: () => void;
|
|
10
|
+
hmac256Init: (keyLen: number) => void;
|
|
11
|
+
hmac256Update: (len: number) => void;
|
|
12
|
+
hmac256Final: () => void;
|
|
13
|
+
}
|
|
14
|
+
/** Subset of the serpent WASM exports used by `cbcEncryptChunk`/`cbcDecryptChunk`. */
|
|
15
|
+
export interface SerpentOpsExports {
|
|
16
|
+
memory: WebAssembly.Memory;
|
|
17
|
+
getKeyOffset: () => number;
|
|
18
|
+
getChunkPtOffset: () => number;
|
|
19
|
+
getChunkCtOffset: () => number;
|
|
20
|
+
getChunkSize: () => number;
|
|
21
|
+
getCbcIvOffset: () => number;
|
|
22
|
+
loadKey: (n: number) => number;
|
|
23
|
+
cbcEncryptChunk: (n: number) => number;
|
|
24
|
+
cbcDecryptChunk_simd: (n: number) => number;
|
|
25
|
+
wipeBuffers: () => void;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Compute HMAC-SHA-256 using raw WASM sha2 exports.
|
|
29
|
+
*
|
|
30
|
+
* Keys longer than 64 bytes are pre-hashed per RFC 2104 §3. The SHA-256
|
|
31
|
+
* input buffer is fed in 64-byte chunks to match the WASM block size.
|
|
32
|
+
* Does not call `_acquireModule`, callers must ensure no stateful instance
|
|
33
|
+
* owns the sha2 module before calling.
|
|
34
|
+
* @param sx sha2 WASM exports
|
|
35
|
+
* @param key HMAC key of any length
|
|
36
|
+
* @param msg Message to authenticate
|
|
37
|
+
* @returns 32-byte HMAC-SHA-256 tag
|
|
38
|
+
*/
|
|
39
|
+
export declare function hmacSha256(sx: Sha2OpsExports, key: Uint8Array, msg: Uint8Array): Uint8Array;
|
|
40
|
+
/**
|
|
41
|
+
* Encrypt one plaintext chunk with Serpent-256 CBC + PKCS7 padding.
|
|
42
|
+
*
|
|
43
|
+
* The padded chunk must fit within the WASM CHUNK_SIZE. Callers are
|
|
44
|
+
* responsible for splitting larger payloads before calling.
|
|
45
|
+
* @param kx Serpent WASM exports
|
|
46
|
+
* @param key 16, 24, or 32-byte key
|
|
47
|
+
* @param iv 16-byte CBC initialisation vector
|
|
48
|
+
* @param chunk Plaintext chunk (padded length must be ≤ WASM CHUNK_SIZE)
|
|
49
|
+
* @returns Ciphertext with PKCS7 padding applied
|
|
50
|
+
*/
|
|
51
|
+
export declare function cbcEncryptChunk(kx: SerpentOpsExports, key: Uint8Array, iv: Uint8Array, chunk: Uint8Array): Uint8Array;
|
|
52
|
+
/**
|
|
53
|
+
* Decrypt one Serpent-256 CBC chunk using the SIMD path and strip PKCS7 padding.
|
|
54
|
+
*
|
|
55
|
+
* Output matches `SerpentCbc.decrypt` byte-for-byte. Throws
|
|
56
|
+
* `RangeError('invalid ciphertext')` on any length or padding failure.
|
|
57
|
+
* @param kx Serpent WASM exports
|
|
58
|
+
* @param key 16, 24, or 32-byte key
|
|
59
|
+
* @param iv 16-byte CBC initialisation vector
|
|
60
|
+
* @param ct Ciphertext (must be non-empty and a multiple of 16 bytes)
|
|
61
|
+
* @returns Plaintext with PKCS7 padding removed
|
|
62
|
+
*/
|
|
63
|
+
export declare function cbcDecryptChunk(kx: SerpentOpsExports, key: Uint8Array, iv: Uint8Array, ct: Uint8Array): Uint8Array;
|
|
@@ -0,0 +1,178 @@
|
|
|
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/serpent/shared-ops.ts
|
|
23
|
+
//
|
|
24
|
+
// Pure-function primitives shared between the main-thread `SerpentCipher`
|
|
25
|
+
// (cipher-suite.ts) and the `SealStreamPool` worker (pool-worker.ts). Both
|
|
26
|
+
// call sites hold their own WASM exports, pool workers instantiate modules
|
|
27
|
+
// locally, the main thread fetches via `getInstance()`, so every function
|
|
28
|
+
// here takes the sha2/serpent exports as parameters. No dependency on
|
|
29
|
+
// `init.ts`, no module-level state, no instance wrappers.
|
|
30
|
+
//
|
|
31
|
+
// These helpers are strictly single-chunk: the caller already divided the
|
|
32
|
+
// payload into chunks ≤ WASM CHUNK_SIZE. For multi-chunk use, see
|
|
33
|
+
// `SerpentCbc.encrypt`/`decrypt`, which loop over the same WASM exports.
|
|
34
|
+
//
|
|
35
|
+
// `pkcs7Pad` / `pkcs7Strip` / `PKCS7_INVALID` live in `../shared/pkcs7.js`
|
|
36
|
+
// and are re-exported here so existing serpent-side imports keep working.
|
|
37
|
+
// A single source of truth keeps the branch-free, Vaudenay-2002-closed
|
|
38
|
+
// padding check identical across all CBC paths.
|
|
39
|
+
export { pkcs7Pad, pkcs7Strip, PKCS7_INVALID } from '../shared/pkcs7.js';
|
|
40
|
+
import { pkcs7Pad, pkcs7Strip, PKCS7_INVALID } from '../shared/pkcs7.js';
|
|
41
|
+
// ── HMAC-SHA-256 ────────────────────────────────────────────────────────────
|
|
42
|
+
/**
|
|
43
|
+
* Compute HMAC-SHA-256 using raw WASM sha2 exports.
|
|
44
|
+
*
|
|
45
|
+
* Keys longer than 64 bytes are pre-hashed per RFC 2104 §3. The SHA-256
|
|
46
|
+
* input buffer is fed in 64-byte chunks to match the WASM block size.
|
|
47
|
+
* Does not call `_acquireModule`, callers must ensure no stateful instance
|
|
48
|
+
* owns the sha2 module before calling.
|
|
49
|
+
* @param sx sha2 WASM exports
|
|
50
|
+
* @param key HMAC key of any length
|
|
51
|
+
* @param msg Message to authenticate
|
|
52
|
+
* @returns 32-byte HMAC-SHA-256 tag
|
|
53
|
+
*/
|
|
54
|
+
export function hmacSha256(sx, key, msg) {
|
|
55
|
+
const inOff = sx.getSha256InputOffset();
|
|
56
|
+
const outOff = sx.getSha256OutOffset();
|
|
57
|
+
let k = key;
|
|
58
|
+
if (k.length > 64) {
|
|
59
|
+
sx.sha256Init();
|
|
60
|
+
feedMemory(sx.memory, inOff, k, 64, sx.sha256Update);
|
|
61
|
+
sx.sha256Final();
|
|
62
|
+
k = new Uint8Array(sx.memory.buffer).slice(outOff, outOff + 32);
|
|
63
|
+
}
|
|
64
|
+
const mem = new Uint8Array(sx.memory.buffer);
|
|
65
|
+
mem.set(k, inOff);
|
|
66
|
+
sx.hmac256Init(k.length);
|
|
67
|
+
feedMemory(sx.memory, inOff, msg, 64, sx.hmac256Update);
|
|
68
|
+
sx.hmac256Final();
|
|
69
|
+
return new Uint8Array(sx.memory.buffer).slice(outOff, outOff + 32);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Copy `msg` into WASM linear memory at `inputOff` in `chunkSize`-byte
|
|
73
|
+
* increments, calling `update(n)` after each write.
|
|
74
|
+
* @param memory WASM memory object
|
|
75
|
+
* @param inputOff Byte offset of the WASM input buffer
|
|
76
|
+
* @param msg Data to feed
|
|
77
|
+
* @param chunkSize Maximum bytes per write (must match WASM buffer size)
|
|
78
|
+
* @param update WASM update function to call after each write
|
|
79
|
+
* @internal
|
|
80
|
+
*/
|
|
81
|
+
function feedMemory(memory, inputOff, msg, chunkSize, update) {
|
|
82
|
+
const mem = new Uint8Array(memory.buffer);
|
|
83
|
+
let pos = 0;
|
|
84
|
+
while (pos < msg.length) {
|
|
85
|
+
const n = Math.min(msg.length - pos, chunkSize);
|
|
86
|
+
mem.set(msg.subarray(pos, pos + n), inputOff);
|
|
87
|
+
update(n);
|
|
88
|
+
pos += n;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// ── Serpent-CBC (single chunk) ──────────────────────────────────────────────
|
|
92
|
+
/**
|
|
93
|
+
* Encrypt one plaintext chunk with Serpent-256 CBC + PKCS7 padding.
|
|
94
|
+
*
|
|
95
|
+
* The padded chunk must fit within the WASM CHUNK_SIZE. Callers are
|
|
96
|
+
* responsible for splitting larger payloads before calling.
|
|
97
|
+
* @param kx Serpent WASM exports
|
|
98
|
+
* @param key 16, 24, or 32-byte key
|
|
99
|
+
* @param iv 16-byte CBC initialisation vector
|
|
100
|
+
* @param chunk Plaintext chunk (padded length must be ≤ WASM CHUNK_SIZE)
|
|
101
|
+
* @returns Ciphertext with PKCS7 padding applied
|
|
102
|
+
*/
|
|
103
|
+
export function cbcEncryptChunk(kx, key, iv, chunk) {
|
|
104
|
+
loadKeyAndIv(kx, key, iv);
|
|
105
|
+
try {
|
|
106
|
+
const padded = pkcs7Pad(chunk);
|
|
107
|
+
const ptOff = kx.getChunkPtOffset();
|
|
108
|
+
const ctOff = kx.getChunkCtOffset();
|
|
109
|
+
const mem = new Uint8Array(kx.memory.buffer);
|
|
110
|
+
mem.set(padded, ptOff);
|
|
111
|
+
const ret = kx.cbcEncryptChunk(padded.length);
|
|
112
|
+
if (ret < 0)
|
|
113
|
+
throw new RangeError(`cbcEncryptChunk rejected len=${padded.length}` +
|
|
114
|
+
` (WASM CHUNK_SIZE=${kx.getChunkSize()})`);
|
|
115
|
+
return new Uint8Array(kx.memory.buffer).slice(ctOff, ctOff + padded.length);
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
// Length-error or any other throw past loadKeyAndIv leaves key+iv staged.
|
|
119
|
+
// Wipe before re-throwing, the cipher-suite caller may not call dispose.
|
|
120
|
+
kx.wipeBuffers();
|
|
121
|
+
throw err;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Decrypt one Serpent-256 CBC chunk using the SIMD path and strip PKCS7 padding.
|
|
126
|
+
*
|
|
127
|
+
* Output matches `SerpentCbc.decrypt` byte-for-byte. Throws
|
|
128
|
+
* `RangeError('invalid ciphertext')` on any length or padding failure.
|
|
129
|
+
* @param kx Serpent WASM exports
|
|
130
|
+
* @param key 16, 24, or 32-byte key
|
|
131
|
+
* @param iv 16-byte CBC initialisation vector
|
|
132
|
+
* @param ct Ciphertext (must be non-empty and a multiple of 16 bytes)
|
|
133
|
+
* @returns Plaintext with PKCS7 padding removed
|
|
134
|
+
*/
|
|
135
|
+
export function cbcDecryptChunk(kx, key, iv, ct) {
|
|
136
|
+
if (ct.length === 0 || ct.length % 16 !== 0)
|
|
137
|
+
throw new RangeError(PKCS7_INVALID);
|
|
138
|
+
loadKeyAndIv(kx, key, iv);
|
|
139
|
+
try {
|
|
140
|
+
const ctOff = kx.getChunkCtOffset();
|
|
141
|
+
const ptOff = kx.getChunkPtOffset();
|
|
142
|
+
const mem = new Uint8Array(kx.memory.buffer);
|
|
143
|
+
mem.set(ct, ctOff);
|
|
144
|
+
const ret = kx.cbcDecryptChunk_simd(ct.length);
|
|
145
|
+
if (ret < 0)
|
|
146
|
+
throw new RangeError(`cbcDecryptChunk_simd rejected len=${ct.length}` +
|
|
147
|
+
` (WASM CHUNK_SIZE=${kx.getChunkSize()})`);
|
|
148
|
+
const raw = new Uint8Array(kx.memory.buffer).slice(ptOff, ptOff + ct.length);
|
|
149
|
+
return pkcs7Strip(raw);
|
|
150
|
+
}
|
|
151
|
+
catch (err) {
|
|
152
|
+
// Length-error, padding mismatch, or any other throw past loadKeyAndIv
|
|
153
|
+
// leaves key+iv staged. Wipe before re-throwing, bad PKCS7 padding is
|
|
154
|
+
// a Vaudenay-attack signal; per-chunk staged key+iv must not survive it.
|
|
155
|
+
kx.wipeBuffers();
|
|
156
|
+
throw err;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Validate, then write `key` and `iv` into the WASM buffers and expand the key schedule.
|
|
161
|
+
* @param kx Serpent WASM exports
|
|
162
|
+
* @param key 16, 24, or 32-byte Serpent key
|
|
163
|
+
* @param iv 16-byte CBC initialisation vector
|
|
164
|
+
* @internal
|
|
165
|
+
*/
|
|
166
|
+
function loadKeyAndIv(kx, key, iv) {
|
|
167
|
+
if (key.length !== 16 && key.length !== 24 && key.length !== 32)
|
|
168
|
+
throw new RangeError(`Serpent key must be 16, 24, or 32 bytes (got ${key.length})`);
|
|
169
|
+
if (iv.length !== 16)
|
|
170
|
+
throw new RangeError(`CBC IV must be 16 bytes (got ${iv.length})`);
|
|
171
|
+
const mem = new Uint8Array(kx.memory.buffer);
|
|
172
|
+
mem.set(key, kx.getKeyOffset());
|
|
173
|
+
if (kx.loadKey(key.length) !== 0) {
|
|
174
|
+
kx.wipeBuffers();
|
|
175
|
+
throw new Error('Serpent shared-ops: loadKey failed');
|
|
176
|
+
}
|
|
177
|
+
mem.set(iv, kx.getCbcIvOffset());
|
|
178
|
+
}
|
package/dist/serpent/types.d.ts
CHANGED
package/dist/serpent.wasm
CHANGED
|
Binary file
|
|
@@ -0,0 +1,53 @@
|
|
|
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/sha2/hash.ts
|
|
23
|
+
//
|
|
24
|
+
// Stateless SHA-256 HashFn for Fortuna's accumulator and reseed slots.
|
|
25
|
+
import { _assertNotOwned, getInstance } from '../init.js';
|
|
26
|
+
export const SHA256Hash = {
|
|
27
|
+
outputSize: 32,
|
|
28
|
+
wasmModules: ['sha2'],
|
|
29
|
+
digest(msg) {
|
|
30
|
+
_assertNotOwned('sha2');
|
|
31
|
+
const x = getInstance('sha2').exports;
|
|
32
|
+
const mem = new Uint8Array(x.memory.buffer);
|
|
33
|
+
try {
|
|
34
|
+
x.sha256Init();
|
|
35
|
+
const inOff = x.getSha256InputOffset();
|
|
36
|
+
let pos = 0;
|
|
37
|
+
while (pos < msg.length) {
|
|
38
|
+
const n = Math.min(msg.length - pos, 64);
|
|
39
|
+
mem.set(msg.subarray(pos, pos + n), inOff);
|
|
40
|
+
x.sha256Update(n);
|
|
41
|
+
pos += n;
|
|
42
|
+
}
|
|
43
|
+
x.sha256Final();
|
|
44
|
+
const outOff = x.getSha256OutOffset();
|
|
45
|
+
return mem.slice(outOff, outOff + 32);
|
|
46
|
+
}
|
|
47
|
+
finally {
|
|
48
|
+
// Wipe the SHA-256 input/output/state scratch so secret-derived
|
|
49
|
+
// inputs (e.g. Fortuna pool entropy) do not outlive this call.
|
|
50
|
+
x.wipeBuffers();
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
};
|
package/dist/sha2/hkdf.js
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
//
|
|
22
22
|
// src/ts/sha2/hkdf.ts
|
|
23
23
|
//
|
|
24
|
-
// RFC 5869
|
|
24
|
+
// RFC 5869, HKDF (HMAC-based Extract-and-Expand Key Derivation Function)
|
|
25
25
|
// Pure TS composition over HMAC_SHA256 and HMAC_SHA512.
|
|
26
26
|
import { HMAC_SHA256, HMAC_SHA512 } from './index.js';
|
|
27
27
|
// ── HKDF_SHA256 ─────────────────────────────────────────────────────────────
|
|
@@ -30,12 +30,12 @@ export class HKDF_SHA256 {
|
|
|
30
30
|
constructor() {
|
|
31
31
|
this.hmac = new HMAC_SHA256();
|
|
32
32
|
}
|
|
33
|
-
// RFC 5869 §2.2
|
|
33
|
+
// RFC 5869 §2.2, Extract
|
|
34
34
|
extract(salt, ikm) {
|
|
35
35
|
const s = (!salt || salt.length === 0) ? new Uint8Array(32) : salt;
|
|
36
36
|
return this.hmac.hash(s, ikm);
|
|
37
37
|
}
|
|
38
|
-
// RFC 5869 §2.3
|
|
38
|
+
// RFC 5869 §2.3, Expand
|
|
39
39
|
expand(prk, info, length) {
|
|
40
40
|
if (prk.length !== 32)
|
|
41
41
|
throw new RangeError('HKDF expand: PRK must be 32 bytes');
|
|
@@ -79,12 +79,12 @@ export class HKDF_SHA512 {
|
|
|
79
79
|
constructor() {
|
|
80
80
|
this.hmac = new HMAC_SHA512();
|
|
81
81
|
}
|
|
82
|
-
// RFC 5869 §2.2
|
|
82
|
+
// RFC 5869 §2.2, Extract
|
|
83
83
|
extract(salt, ikm) {
|
|
84
84
|
const s = (!salt || salt.length === 0) ? new Uint8Array(64) : salt;
|
|
85
85
|
return this.hmac.hash(s, ikm);
|
|
86
86
|
}
|
|
87
|
-
// RFC 5869 §2.3
|
|
87
|
+
// RFC 5869 §2.3, Expand
|
|
88
88
|
expand(prk, info, length) {
|
|
89
89
|
if (prk.length !== 64)
|
|
90
90
|
throw new RangeError('HKDF expand: PRK must be 64 bytes');
|
package/dist/sha2/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { WasmSource } from '../wasm-source.js';
|
|
2
|
+
import type { Sha2Exports } from './types.js';
|
|
2
3
|
export declare function sha2Init(source: WasmSource): Promise<void>;
|
|
3
4
|
export type { WasmSource };
|
|
4
|
-
export
|
|
5
|
+
export type { Sha2Exports };
|
|
6
|
+
export { isInitialized } from '../init.js';
|
|
5
7
|
export declare class SHA256 {
|
|
6
8
|
private readonly x;
|
|
7
9
|
constructor();
|
|
@@ -20,6 +22,24 @@ export declare class SHA384 {
|
|
|
20
22
|
hash(msg: Uint8Array): Uint8Array;
|
|
21
23
|
dispose(): void;
|
|
22
24
|
}
|
|
25
|
+
export declare class SHA224 {
|
|
26
|
+
private readonly x;
|
|
27
|
+
constructor();
|
|
28
|
+
hash(msg: Uint8Array): Uint8Array;
|
|
29
|
+
dispose(): void;
|
|
30
|
+
}
|
|
31
|
+
export declare class SHA512_224 {
|
|
32
|
+
private readonly x;
|
|
33
|
+
constructor();
|
|
34
|
+
hash(msg: Uint8Array): Uint8Array;
|
|
35
|
+
dispose(): void;
|
|
36
|
+
}
|
|
37
|
+
export declare class SHA512_256 {
|
|
38
|
+
private readonly x;
|
|
39
|
+
constructor();
|
|
40
|
+
hash(msg: Uint8Array): Uint8Array;
|
|
41
|
+
dispose(): void;
|
|
42
|
+
}
|
|
23
43
|
export declare class HMAC_SHA256 {
|
|
24
44
|
private readonly x;
|
|
25
45
|
constructor();
|
|
@@ -39,3 +59,4 @@ export declare class HMAC_SHA384 {
|
|
|
39
59
|
dispose(): void;
|
|
40
60
|
}
|
|
41
61
|
export { HKDF_SHA256, HKDF_SHA512 } from './hkdf.js';
|
|
62
|
+
export { SHA256Hash } from './hash.js';
|