@enclave-technologies/pqc-primitives 0.1.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.
@@ -0,0 +1,218 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+
4
+ /**
5
+ * Canonical suite identifier matching the Rust crate (Category 5 algorithms).
6
+ */
7
+ export function ENCLAVE_PQ_SUITE_ID(): string;
8
+
9
+ /**
10
+ * Domain-separation prefix for the Enclave labeled KDF.
11
+ */
12
+ export function KDF_LABEL_PREFIX(): string;
13
+
14
+ /**
15
+ * Algorithm identifier (`"Argon2id"`).
16
+ */
17
+ export function PWHASH_ALGORITHM(): string;
18
+
19
+ /**
20
+ * Derived key length in bytes (matches AES-256-GCM key size).
21
+ */
22
+ export function PWHASH_OUTPUT_BYTES(): number;
23
+
24
+ /**
25
+ * Salt length in bytes produced by [`generate_salt`].
26
+ */
27
+ export function PWHASH_SALT_BYTES(): number;
28
+
29
+ /**
30
+ * OWASP baseline Argon2id params: `{ memoryCostKib, iterations, parallelism }`.
31
+ *
32
+ * Sourced from the OWASP Password Storage Cheat Sheet (19 MiB / t=2 / p=1).
33
+ * Slow and memory-hard by design — lowering these for login latency is a
34
+ * security tradeoff, not a free optimization.
35
+ */
36
+ export function RECOMMENDED_PARAMS(): any;
37
+
38
+ /**
39
+ * Decrypt AES-256-GCM ciphertext (including trailing tag).
40
+ *
41
+ * Throws on authentication failure (`AeadFailure: ...`).
42
+ */
43
+ export function aeadDecrypt(key: Uint8Array, nonce: Uint8Array, ciphertext: Uint8Array, aad: Uint8Array): Uint8Array;
44
+
45
+ /**
46
+ * Encrypt with AES-256-GCM under an explicit key and nonce.
47
+ *
48
+ * Returns `ciphertext || tag` (16-byte tag suffix). Callers must ensure
49
+ * `(key, nonce)` uniqueness.
50
+ */
51
+ export function aeadEncrypt(key: Uint8Array, nonce: Uint8Array, plaintext: Uint8Array, aad: Uint8Array): Uint8Array;
52
+
53
+ /**
54
+ * Cryptographically random 16-byte salt for Argon2id.
55
+ */
56
+ export function generateSalt(): Uint8Array;
57
+
58
+ /**
59
+ * Return the [`CryptoUsageRecord`] from the last WASM primitive call.
60
+ *
61
+ * Shape: `{ algorithm, suiteId, operation, crateVersion }`.
62
+ * Returns `undefined` if no operation has run yet in this WASM instance.
63
+ *
64
+ * This is the CBOM attach point for product layers (Encrypt, etc.). This
65
+ * binding does not persist or transmit the record.
66
+ */
67
+ export function getLastUsageRecord(): any;
68
+
69
+ /**
70
+ * SHAKE256 over UTF-8 string bytes.
71
+ */
72
+ export function hashUtf8(value: string, output_len: number): Uint8Array;
73
+
74
+ /**
75
+ * Decapsulate an ML-KEM-1024 ciphertext.
76
+ *
77
+ * `secret_key` may be a 64-byte seed or a 3168-byte expanded key.
78
+ */
79
+ export function kemDecapsulate(ciphertext: Uint8Array, secret_key: Uint8Array): Uint8Array;
80
+
81
+ /**
82
+ * Encapsulate a shared secret to an ML-KEM-1024 public key.
83
+ *
84
+ * Returns `{ ciphertext, sharedSecret }` (1568 / 32 bytes).
85
+ */
86
+ export function kemEncapsulate(public_key: Uint8Array): any;
87
+
88
+ /**
89
+ * Deterministic encapsulation for known-answer / KAT compliance.
90
+ *
91
+ * # Hazmat
92
+ *
93
+ * **KATs only.** Production code must call [`kem_encapsulate`].
94
+ */
95
+ export function kemEncapsulateDeterministic(public_key: Uint8Array, m: Uint8Array): any;
96
+
97
+ /**
98
+ * Expand a 64-byte seed-form secret key to the FIPS expanded encoding
99
+ * ([`kem::SECRET_KEY_BYTES`] bytes).
100
+ */
101
+ export function kemExpandedSecretKey(secret_key: Uint8Array): Uint8Array;
102
+
103
+ /**
104
+ * Generate a fresh ML-KEM-1024 keypair (includes PCT).
105
+ *
106
+ * Returns `{ publicKey, secretKey }` where `secretKey` is the preferred
107
+ * seed form ([`kem::SECRET_KEY_SEED_BYTES`] = 64). Expanded size is
108
+ * [`kem::SECRET_KEY_BYTES`] = 3168 — use [`kem_expanded_secret_key`].
109
+ *
110
+ * Throws `PairwiseConsistencyFailureError` if the PCT fails.
111
+ */
112
+ export function kemGenerateKeypair(): any;
113
+
114
+ /**
115
+ * Derive an ML-KEM-1024 keypair from a 64-byte seed (`d || z`). Includes PCT.
116
+ */
117
+ export function kemKeypairFromSeed(seed: Uint8Array): any;
118
+
119
+ /**
120
+ * Derive key material with `enclave-kdf-v1` labeled SHAKE256.
121
+ *
122
+ * Throws `InvalidParameter` on empty `label` or `length == 0`.
123
+ */
124
+ export function labeledKdf(label: string, ikm: Uint8Array, length: number): Uint8Array;
125
+
126
+ /**
127
+ * [`labeled_kdf`] with a 32-byte output.
128
+ */
129
+ export function labeledKdf32(label: string, ikm: Uint8Array): Uint8Array;
130
+
131
+ /**
132
+ * Derive a 32-byte key from a password + salt with Argon2id.
133
+ *
134
+ * `params` must be `{ memoryCostKib, iterations, parallelism }` (see
135
+ * [`recommended_params`]). Throws on empty password / wrong salt length /
136
+ * invalid costs.
137
+ *
138
+ * This call is intentionally slow (~tens–hundreds of ms depending on host).
139
+ * That cost is the offline brute-force defense — do not lower params casually.
140
+ */
141
+ export function pwhashDeriveKey(password: Uint8Array, salt: Uint8Array, params: any): Uint8Array;
142
+
143
+ /**
144
+ * Run known-answer CASTs for ML-KEM-1024, ML-DSA-87, and Argon2id.
145
+ *
146
+ * Throws `SelfTestFailureError` if any CAST fails. Pair-wise consistency is
147
+ * already enforced inside key generation — this is the power-on / module-entry
148
+ * known-answer path. The Argon2id CAST is slower (memory-hard by design).
149
+ */
150
+ export function runSelfTests(): void;
151
+
152
+ /**
153
+ * One-shot SHAKE256 hash of `input` into `output_len` bytes.
154
+ */
155
+ export function shake256(input: Uint8Array, output_len: number): Uint8Array;
156
+
157
+ /**
158
+ * Expand a 32-byte seed-form secret key to the FIPS expanded encoding
159
+ * ([`sig::SECRET_KEY_BYTES`] bytes).
160
+ */
161
+ export function sigExpandedSecretKey(secret_key: Uint8Array): Uint8Array;
162
+
163
+ /**
164
+ * Generate a fresh ML-DSA-87 keypair (includes PCT).
165
+ *
166
+ * Returns `{ publicKey, secretKey }` where `secretKey` is the preferred
167
+ * seed form ([`sig::SECRET_KEY_SEED_BYTES`] = 32). Expanded size is
168
+ * [`sig::SECRET_KEY_BYTES`] = 4896.
169
+ *
170
+ * Throws `PairwiseConsistencyFailureError` if the PCT fails.
171
+ */
172
+ export function sigGenerateKeypair(): any;
173
+
174
+ /**
175
+ * Derive an ML-DSA-87 keypair from a 32-byte seed. Includes PCT.
176
+ */
177
+ export function sigKeypairFromSeed(seed: Uint8Array): any;
178
+
179
+ /**
180
+ * Sign a message with empty context (deterministic ML-DSA-87).
181
+ *
182
+ * Empty `message` throws `InvalidLength` (matches Rust).
183
+ */
184
+ export function sigSign(secret_key: Uint8Array, message: Uint8Array): Uint8Array;
185
+
186
+ /**
187
+ * Deterministic ML-DSA.Sign with an explicit context (`context.len() <= 255`).
188
+ *
189
+ * Empty `message` or `context.len() > 255` throws (matches Rust).
190
+ */
191
+ export function sigSignWithContext(secret_key: Uint8Array, message: Uint8Array, context: Uint8Array): Uint8Array;
192
+
193
+ /**
194
+ * Verify an ML-DSA-87 signature (empty context).
195
+ *
196
+ * Returns `false` on a cryptographically invalid signature. Throws only for
197
+ * malformed input lengths / encodings.
198
+ */
199
+ export function sigVerify(public_key: Uint8Array, message: Uint8Array, signature: Uint8Array): boolean;
200
+
201
+ /**
202
+ * Verify an ML-DSA-87 signature with an explicit context.
203
+ *
204
+ * Returns `false` on cryptographic failure; throws on malformed lengths.
205
+ */
206
+ export function sigVerifyWithContext(public_key: Uint8Array, message: Uint8Array, signature: Uint8Array, context: Uint8Array): boolean;
207
+
208
+ /**
209
+ * Overwrite a JS `Uint8Array` in place with zeros.
210
+ *
211
+ * # Security note
212
+ *
213
+ * Rust-side secret keys are zeroized on `Drop`, but that guarantee **does not**
214
+ * cross the WASM boundary. Once secret material lives in a JS `Uint8Array`, the
215
+ * JS garbage collector will not zero it. Call this when you are finished with
216
+ * long-lived secret buffers.
217
+ */
218
+ export function zeroize(buf: Uint8Array): void;
@@ -0,0 +1,41 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+ export const memory: WebAssembly.Memory;
4
+ export const aeadDecrypt: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => [number, number, number, number];
5
+ export const aeadEncrypt: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => [number, number, number, number];
6
+ export const hashUtf8: (a: number, b: number, c: number) => [number, number, number, number];
7
+ export const shake256: (a: number, b: number, c: number) => [number, number, number, number];
8
+ export const sigExpandedSecretKey: (a: number, b: number) => [number, number, number, number];
9
+ export const sigGenerateKeypair: () => [number, number, number];
10
+ export const sigKeypairFromSeed: (a: number, b: number) => [number, number, number];
11
+ export const sigSign: (a: number, b: number, c: number, d: number) => [number, number, number, number];
12
+ export const sigSignWithContext: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number, number, number];
13
+ export const sigVerify: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number, number];
14
+ export const sigVerifyWithContext: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => [number, number, number];
15
+ export const PWHASH_ALGORITHM: () => [number, number];
16
+ export const PWHASH_OUTPUT_BYTES: () => number;
17
+ export const PWHASH_SALT_BYTES: () => number;
18
+ export const RECOMMENDED_PARAMS: () => [number, number, number];
19
+ export const generateSalt: () => [number, number, number, number];
20
+ export const kemDecapsulate: (a: number, b: number, c: number, d: number) => [number, number, number, number];
21
+ export const kemEncapsulate: (a: number, b: number) => [number, number, number];
22
+ export const kemEncapsulateDeterministic: (a: number, b: number, c: number, d: number) => [number, number, number];
23
+ export const kemExpandedSecretKey: (a: number, b: number) => [number, number, number, number];
24
+ export const kemGenerateKeypair: () => [number, number, number];
25
+ export const kemKeypairFromSeed: (a: number, b: number) => [number, number, number];
26
+ export const pwhashDeriveKey: (a: number, b: number, c: number, d: number, e: any) => [number, number, number, number];
27
+ export const ENCLAVE_PQ_SUITE_ID: () => [number, number];
28
+ export const KDF_LABEL_PREFIX: () => [number, number];
29
+ export const getLastUsageRecord: () => [number, number, number];
30
+ export const labeledKdf: (a: number, b: number, c: number, d: number, e: number) => [number, number, number, number];
31
+ export const labeledKdf32: (a: number, b: number, c: number, d: number) => [number, number, number, number];
32
+ export const runSelfTests: () => [number, number];
33
+ export const zeroize: (a: any) => void;
34
+ export const __wbindgen_exn_store: (a: number) => void;
35
+ export const __externref_table_alloc: () => number;
36
+ export const __wbindgen_externrefs: WebAssembly.Table;
37
+ export const __wbindgen_free: (a: number, b: number, c: number) => void;
38
+ export const __externref_table_dealloc: (a: number) => void;
39
+ export const __wbindgen_malloc: (a: number, b: number) => number;
40
+ export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
41
+ export const __wbindgen_start: () => void;
@@ -0,0 +1,157 @@
1
+ /** Category 5 sizes — must match Rust ENCLAVE_PQ_SUITE_v1. */
2
+ export declare const ENCLAVE_PQ_SUITE_ID: "ENCLAVE_PQ_SUITE_v1";
3
+ export declare const KDF_LABEL_PREFIX: "enclave-kdf-v1";
4
+ export declare const KEM: {
5
+ readonly ALGORITHM: "ML-KEM-1024";
6
+ readonly PUBLIC_KEY_BYTES: 1568;
7
+ readonly SECRET_KEY_SEED_BYTES: 64;
8
+ readonly SECRET_KEY_EXPANDED_BYTES: 3168;
9
+ readonly SECRET_KEY_BYTES: 3168;
10
+ readonly CIPHERTEXT_BYTES: 1568;
11
+ readonly SHARED_SECRET_BYTES: 32;
12
+ readonly ENCAP_RANDOMNESS_BYTES: 32;
13
+ };
14
+ export declare const SIG: {
15
+ readonly ALGORITHM: "ML-DSA-87";
16
+ readonly PUBLIC_KEY_BYTES: 2592;
17
+ readonly SECRET_KEY_SEED_BYTES: 32;
18
+ readonly SECRET_KEY_EXPANDED_BYTES: 4896;
19
+ readonly SECRET_KEY_BYTES: 4896;
20
+ readonly SIGNATURE_BYTES: 4627;
21
+ readonly MAX_CONTEXT_BYTES: 255;
22
+ };
23
+ export declare const AEAD: {
24
+ readonly ALGORITHM: "AES-256-GCM";
25
+ readonly KEY_BYTES: 32;
26
+ readonly NONCE_BYTES: 12;
27
+ readonly TAG_BYTES: 16;
28
+ };
29
+ export declare const HASH: {
30
+ readonly ALGORITHM: "SHAKE256";
31
+ readonly DEFAULT_OUTPUT_BYTES: 32;
32
+ };
33
+ export declare const PWHASH: {
34
+ readonly ALGORITHM: "Argon2id";
35
+ readonly SALT_BYTES: 16;
36
+ readonly OUTPUT_BYTES: 32;
37
+ readonly RECOMMENDED_PARAMS: {
38
+ readonly memoryCostKib: 19456;
39
+ readonly iterations: 2;
40
+ readonly parallelism: 1;
41
+ };
42
+ };
43
+
44
+ export type Argon2Params = {
45
+ memoryCostKib: number;
46
+ iterations: number;
47
+ parallelism: number;
48
+ };
49
+
50
+ export type KemKeypair = { publicKey: Uint8Array; secretKey: Uint8Array };
51
+ export type KemEncapsulation = {
52
+ ciphertext: Uint8Array;
53
+ sharedSecret: Uint8Array;
54
+ };
55
+ export type SigKeypair = { publicKey: Uint8Array; secretKey: Uint8Array };
56
+ export type CryptoUsageRecord = {
57
+ algorithm: string;
58
+ suiteId: string;
59
+ operation: string;
60
+ crateVersion: string;
61
+ };
62
+
63
+ export declare function isPairwiseConsistencyFailure(err: unknown): boolean;
64
+ export declare function isSelfTestFailure(err: unknown): boolean;
65
+
66
+ export declare function kemGenerateKeypair(): KemKeypair;
67
+ export declare function kemKeypairFromSeed(seed: Uint8Array): KemKeypair;
68
+ export declare function kemExpandedSecretKey(secretKey: Uint8Array): Uint8Array;
69
+ export declare function kemEncapsulate(publicKey: Uint8Array): KemEncapsulation;
70
+ /** Hazmat — KATs only. Prefer kemEncapsulate. */
71
+ export declare function kemEncapsulateDeterministic(
72
+ publicKey: Uint8Array,
73
+ m: Uint8Array,
74
+ ): KemEncapsulation;
75
+ export declare function kemDecapsulate(
76
+ ciphertext: Uint8Array,
77
+ secretKey: Uint8Array,
78
+ ): Uint8Array;
79
+
80
+ export declare function sigGenerateKeypair(): SigKeypair;
81
+ export declare function sigKeypairFromSeed(seed: Uint8Array): SigKeypair;
82
+ export declare function sigExpandedSecretKey(secretKey: Uint8Array): Uint8Array;
83
+ export declare function sigSign(
84
+ secretKey: Uint8Array,
85
+ message: Uint8Array,
86
+ ): Uint8Array;
87
+ export declare function sigSignWithContext(
88
+ secretKey: Uint8Array,
89
+ message: Uint8Array,
90
+ context: Uint8Array,
91
+ ): Uint8Array;
92
+ export declare function sigVerify(
93
+ publicKey: Uint8Array,
94
+ message: Uint8Array,
95
+ signature: Uint8Array,
96
+ ): boolean;
97
+ export declare function sigVerifyWithContext(
98
+ publicKey: Uint8Array,
99
+ message: Uint8Array,
100
+ signature: Uint8Array,
101
+ context: Uint8Array,
102
+ ): boolean;
103
+
104
+ export declare function aeadEncrypt(
105
+ key: Uint8Array,
106
+ nonce: Uint8Array,
107
+ plaintext: Uint8Array,
108
+ aad: Uint8Array,
109
+ ): Uint8Array;
110
+ export declare function aeadDecrypt(
111
+ key: Uint8Array,
112
+ nonce: Uint8Array,
113
+ ciphertext: Uint8Array,
114
+ aad: Uint8Array,
115
+ ): Uint8Array;
116
+
117
+ export declare function shake256(
118
+ input: Uint8Array,
119
+ outputLen: number,
120
+ ): Uint8Array;
121
+ export declare function hashUtf8(value: string, outputLen: number): Uint8Array;
122
+
123
+ export declare function labeledKdf(
124
+ label: string,
125
+ ikm: Uint8Array,
126
+ length: number,
127
+ ): Uint8Array;
128
+ export declare function labeledKdf32(
129
+ label: string,
130
+ ikm: Uint8Array,
131
+ ): Uint8Array;
132
+
133
+ /**
134
+ * Argon2id password → 32-byte key. Deliberately slow / memory-hard.
135
+ * Prefer PWHASH.RECOMMENDED_PARAMS unless you have measured otherwise.
136
+ */
137
+ export declare function pwhashDeriveKey(
138
+ password: Uint8Array,
139
+ salt: Uint8Array,
140
+ params: Argon2Params,
141
+ ): Uint8Array;
142
+ /** Cryptographically random 16-byte Argon2id salt. */
143
+ export declare function generateSalt(): Uint8Array;
144
+ /** Same values as PWHASH.RECOMMENDED_PARAMS (WASM mirror). */
145
+ export declare function RECOMMENDED_PARAMS(): Argon2Params;
146
+
147
+ /** CBOM attach point: usage from the last WASM primitive call, or undefined. */
148
+ export declare function getLastUsageRecord(): CryptoUsageRecord | undefined;
149
+
150
+ /** CAST self-tests; rejects with SelfTestFailureError (`err.name`). */
151
+ export declare function runSelfTests(): Promise<void>;
152
+
153
+ /**
154
+ * Overwrite buffer bytes in place. WASM Drop zeroization does not apply to
155
+ * secret material copied into JS Uint8Arrays — call this when finished.
156
+ */
157
+ export declare function zeroize(buf: Uint8Array): void;
@@ -0,0 +1,54 @@
1
+ /**
2
+ * @enclave-technologies/pqc-primitives — algorithm-only façade (nodejs).
3
+ *
4
+ * Category 5 exclusively (ML-KEM-1024 / ML-DSA-87). No suite parameter.
5
+ *
6
+ * Secret zeroization does NOT cross the WASM boundary. Call zeroize(buf) on
7
+ * long-lived secret Uint8Arrays when finished.
8
+ */
9
+ export {
10
+ AEAD,
11
+ ENCLAVE_PQ_SUITE_ID,
12
+ HASH,
13
+ KDF_LABEL_PREFIX,
14
+ KEM,
15
+ PWHASH,
16
+ SIG,
17
+ isPairwiseConsistencyFailure,
18
+ isSelfTestFailure,
19
+ } from "./constants.js";
20
+
21
+ import { createRequire } from "node:module";
22
+ const require = createRequire(import.meta.url);
23
+ const wasm = require("./enclave_pqc_primitives_wasm.cjs");
24
+
25
+ export const aeadDecrypt = wasm.aeadDecrypt;
26
+ export const aeadEncrypt = wasm.aeadEncrypt;
27
+ export const getLastUsageRecord = wasm.getLastUsageRecord;
28
+ export const hashUtf8 = wasm.hashUtf8;
29
+ export const kemDecapsulate = wasm.kemDecapsulate;
30
+ export const kemEncapsulate = wasm.kemEncapsulate;
31
+ /** Hazmat — KATs only. Prefer kemEncapsulate in production. */
32
+ export const kemEncapsulateDeterministic = wasm.kemEncapsulateDeterministic;
33
+ export const kemExpandedSecretKey = wasm.kemExpandedSecretKey;
34
+ export const kemGenerateKeypair = wasm.kemGenerateKeypair;
35
+ export const kemKeypairFromSeed = wasm.kemKeypairFromSeed;
36
+ export const labeledKdf = wasm.labeledKdf;
37
+ export const labeledKdf32 = wasm.labeledKdf32;
38
+ export const pwhashDeriveKey = wasm.pwhashDeriveKey;
39
+ export const generateSalt = wasm.generateSalt;
40
+ export const RECOMMENDED_PARAMS = wasm.RECOMMENDED_PARAMS;
41
+ export const shake256 = wasm.shake256;
42
+ export const sigExpandedSecretKey = wasm.sigExpandedSecretKey;
43
+ export const sigGenerateKeypair = wasm.sigGenerateKeypair;
44
+ export const sigKeypairFromSeed = wasm.sigKeypairFromSeed;
45
+ export const sigSign = wasm.sigSign;
46
+ export const sigSignWithContext = wasm.sigSignWithContext;
47
+ export const sigVerify = wasm.sigVerify;
48
+ export const sigVerifyWithContext = wasm.sigVerifyWithContext;
49
+ export const zeroize = wasm.zeroize;
50
+
51
+ /** Run CAST self-tests; throws SelfTestFailureError on failure. */
52
+ export async function runSelfTests() {
53
+ wasm.runSelfTests();
54
+ }
@@ -0,0 +1,63 @@
1
+ /** @type {const} */
2
+ export const ENCLAVE_PQ_SUITE_ID = "ENCLAVE_PQ_SUITE_v1";
3
+ /** @type {const} */
4
+ export const KDF_LABEL_PREFIX = "enclave-kdf-v1";
5
+ /** @type {const} */
6
+ export const KEM = Object.freeze({
7
+ ALGORITHM: "ML-KEM-1024",
8
+ PUBLIC_KEY_BYTES: 1568,
9
+ SECRET_KEY_SEED_BYTES: 64,
10
+ SECRET_KEY_EXPANDED_BYTES: 3168,
11
+ SECRET_KEY_BYTES: 3168,
12
+ CIPHERTEXT_BYTES: 1568,
13
+ SHARED_SECRET_BYTES: 32,
14
+ ENCAP_RANDOMNESS_BYTES: 32,
15
+ });
16
+ /** @type {const} */
17
+ export const SIG = Object.freeze({
18
+ ALGORITHM: "ML-DSA-87",
19
+ PUBLIC_KEY_BYTES: 2592,
20
+ SECRET_KEY_SEED_BYTES: 32,
21
+ SECRET_KEY_EXPANDED_BYTES: 4896,
22
+ SECRET_KEY_BYTES: 4896,
23
+ SIGNATURE_BYTES: 4627,
24
+ MAX_CONTEXT_BYTES: 255,
25
+ });
26
+ /** @type {const} */
27
+ export const AEAD = Object.freeze({
28
+ ALGORITHM: "AES-256-GCM",
29
+ KEY_BYTES: 32,
30
+ NONCE_BYTES: 12,
31
+ TAG_BYTES: 16,
32
+ });
33
+ /** @type {const} */
34
+ export const HASH = Object.freeze({
35
+ ALGORITHM: "SHAKE256",
36
+ DEFAULT_OUTPUT_BYTES: 32,
37
+ });
38
+ /** @type {const} */
39
+ export const PWHASH = Object.freeze({
40
+ ALGORITHM: "Argon2id",
41
+ SALT_BYTES: 16,
42
+ OUTPUT_BYTES: 32,
43
+ /**
44
+ * OWASP Password Storage Cheat Sheet baseline (verified 2026-07-14):
45
+ * m=19456 (19 MiB), t=2, p=1. Deliberately slow + memory-hard — do not
46
+ * lower these for login latency without treating that as a security tradeoff.
47
+ */
48
+ RECOMMENDED_PARAMS: Object.freeze({
49
+ memoryCostKib: 19456,
50
+ iterations: 2,
51
+ parallelism: 1,
52
+ }),
53
+ });
54
+
55
+ /** @param {unknown} err */
56
+ export function isPairwiseConsistencyFailure(err) {
57
+ return err instanceof Error && err.name === "PairwiseConsistencyFailureError";
58
+ }
59
+
60
+ /** @param {unknown} err */
61
+ export function isSelfTestFailure(err) {
62
+ return err instanceof Error && err.name === "SelfTestFailureError";
63
+ }