@bcts/crypto 1.0.0-alpha.8 → 1.0.0-beta.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/dist/index.mjs CHANGED
@@ -1,86 +1,38 @@
1
- import { sha256 as sha256$1, sha512 as sha512$1 } from "@noble/hashes/sha2";
2
- import { hmac } from "@noble/hashes/hmac";
3
- import { pbkdf2 } from "@noble/hashes/pbkdf2";
4
- import { hkdf } from "@noble/hashes/hkdf";
5
- import { chacha20poly1305 } from "@noble/ciphers/chacha";
6
- import { ed25519, x25519 } from "@noble/curves/ed25519";
7
- import { schnorr, secp256k1 } from "@noble/curves/secp256k1";
1
+ import { t as __exportAll } from "./chunk-DQk6qfdC.mjs";
2
+ import { sha256 as sha256$1, sha512 as sha512$1 } from "@noble/hashes/sha2.js";
3
+ import { hmac } from "@noble/hashes/hmac.js";
4
+ import { pbkdf2 } from "@noble/hashes/pbkdf2.js";
5
+ import { hkdf } from "@noble/hashes/hkdf.js";
6
+ import { chacha20poly1305 } from "@noble/ciphers/chacha.js";
7
+ import { ed25519, x25519 } from "@noble/curves/ed25519.js";
8
+ import { schnorr, secp256k1 } from "@noble/curves/secp256k1.js";
8
9
  import { SecureRandomNumberGenerator } from "@bcts/rand";
9
- import { scrypt as scrypt$1 } from "@noble/hashes/scrypt";
10
- import { argon2id } from "@noble/hashes/argon2";
10
+ import { scrypt as scrypt$1 } from "@noble/hashes/scrypt.js";
11
+ import { argon2id as argon2id$1 } from "@noble/hashes/argon2.js";
11
12
 
12
- //#region src/error.ts
13
- /**
14
- * AEAD-specific error for authentication failures
15
- */
16
- var AeadError = class extends Error {
17
- constructor(message = "AEAD authentication failed") {
18
- super(message);
19
- this.name = "AeadError";
20
- }
21
- };
22
- /**
23
- * Generic crypto error type
24
- */
25
- var CryptoError = class CryptoError extends Error {
26
- cause;
27
- constructor(message, cause) {
28
- super(message);
29
- this.name = "CryptoError";
30
- this.cause = cause;
31
- }
32
- /**
33
- * Create a CryptoError for AEAD authentication failures.
34
- *
35
- * @param error - Optional underlying AeadError
36
- * @returns A CryptoError wrapping the AEAD error
37
- */
38
- static aead(error) {
39
- return new CryptoError("AEAD error", error ?? new AeadError());
40
- }
41
- /**
42
- * Create a CryptoError for invalid parameter values.
43
- *
44
- * @param message - Description of the invalid parameter
45
- * @returns A CryptoError describing the invalid parameter
46
- */
47
- static invalidParameter(message) {
48
- return new CryptoError(`Invalid parameter: ${message}`);
49
- }
50
- };
51
-
52
- //#endregion
53
- //#region src/memzero.ts
13
+ //#region src/hash.ts
54
14
  /**
55
- * Securely zero out a typed array.
15
+ * Copyright © 2023-2026 Blockchain Commons, LLC
16
+ * Copyright © 2025-2026 Parity Technologies
56
17
  *
57
- * **IMPORTANT: This is a best-effort implementation.** Unlike the Rust reference
58
- * implementation which uses `std::ptr::write_volatile()` for guaranteed volatile
59
- * writes, JavaScript engines and JIT compilers can still potentially optimize
60
- * away these zeroing operations. The check at the end helps prevent optimization,
61
- * but it is not foolproof.
62
- *
63
- * For truly sensitive cryptographic operations, consider using the Web Crypto API's
64
- * `crypto.subtle` with non-extractable keys when possible, as it provides stronger
65
- * guarantees than what can be achieved with pure JavaScript.
66
- *
67
- * This function attempts to prevent the compiler from optimizing away
68
- * the zeroing operation by using a verification check after the zeroing loop.
69
18
  */
70
- function memzero(data) {
71
- const len = data.length;
72
- for (let i = 0; i < len; i++) data[i] = 0;
73
- if (data.length > 0 && data[0] !== 0) throw new Error("memzero failed");
74
- }
75
- /**
76
- * Securely zero out an array of Uint8Arrays.
77
- */
78
- function memzeroVecVecU8(arrays) {
79
- for (const arr of arrays) memzero(arr);
80
- }
81
-
82
- //#endregion
83
- //#region src/hash.ts
19
+ var hash_exports = /* @__PURE__ */ __exportAll({
20
+ CRC32_SIZE: () => 4,
21
+ SHA256_SIZE: () => 32,
22
+ SHA512_SIZE: () => 64,
23
+ crc32: () => crc32,
24
+ crc32Data: () => crc32Data,
25
+ crc32DataOpt: () => crc32DataOpt,
26
+ doubleSha256: () => doubleSha256,
27
+ hkdfHmacSha256: () => hkdfHmacSha256,
28
+ hkdfHmacSha512: () => hkdfHmacSha512,
29
+ hmacSha256: () => hmacSha256,
30
+ hmacSha512: () => hmacSha512,
31
+ pbkdf2HmacSha256: () => pbkdf2HmacSha256,
32
+ pbkdf2HmacSha512: () => pbkdf2HmacSha512,
33
+ sha256: () => sha256,
34
+ sha512: () => sha512
35
+ });
84
36
  const CRC32_SIZE = 4;
85
37
  const SHA256_SIZE = 32;
86
38
  const SHA512_SIZE = 64;
@@ -177,8 +129,103 @@ function hkdfHmacSha512(keyMaterial, salt, keyLen) {
177
129
  return hkdf(sha512$1, keyMaterial, salt, void 0, keyLen);
178
130
  }
179
131
 
132
+ //#endregion
133
+ //#region src/error.ts
134
+ /**
135
+ * Copyright © 2023-2026 Blockchain Commons, LLC
136
+ * Copyright © 2025-2026 Parity Technologies
137
+ *
138
+ */
139
+ /**
140
+ * AEAD-specific error for authentication failures
141
+ */
142
+ var AeadError = class extends Error {
143
+ constructor(message = "AEAD authentication failed") {
144
+ super(message);
145
+ this.name = "AeadError";
146
+ }
147
+ };
148
+ /**
149
+ * Generic crypto error type
150
+ */
151
+ var CryptoError = class CryptoError extends Error {
152
+ cause;
153
+ constructor(message, cause) {
154
+ super(message);
155
+ this.name = "CryptoError";
156
+ this.cause = cause;
157
+ }
158
+ /**
159
+ * Create a CryptoError for AEAD authentication failures.
160
+ *
161
+ * @param error - Optional underlying AeadError
162
+ * @returns A CryptoError wrapping the AEAD error
163
+ */
164
+ static aead(error) {
165
+ return new CryptoError("AEAD error", error ?? new AeadError());
166
+ }
167
+ /**
168
+ * Create a CryptoError for invalid parameter values.
169
+ *
170
+ * **TS-specific.** Rust's `bc_crypto::Error` enum has no
171
+ * `InvalidParameter` variant; size validation in Rust is enforced at
172
+ * compile time via fixed-size array references (e.g. `&[u8; 32]`) or
173
+ * via `panic!`/`expect(...)` for runtime checks. The TS port has no
174
+ * fixed-size array types, so it surfaces those same conditions through
175
+ * a thrown `CryptoError.invalidParameter(...)`. Catching this is
176
+ * equivalent to defensive guards around an `expect`-style panic on the
177
+ * Rust side.
178
+ *
179
+ * @param message - Description of the invalid parameter
180
+ * @returns A CryptoError describing the invalid parameter
181
+ */
182
+ static invalidParameter(message) {
183
+ return new CryptoError(`Invalid parameter: ${message}`);
184
+ }
185
+ };
186
+
187
+ //#endregion
188
+ //#region src/memzero.ts
189
+ /**
190
+ * Securely zero out a typed array.
191
+ *
192
+ * Mirrors Rust `bc_crypto::memzero<T>(s: &mut [T])`. The Rust impl uses
193
+ * `std::ptr::write_volatile()` to guarantee the writes survive optimization;
194
+ * JavaScript has no equivalent primitive, so this is **best-effort** — JIT
195
+ * compilers may still elide the loop, though the post-hoc verification
196
+ * check forces the engine to keep the writes observable.
197
+ *
198
+ * For truly sensitive cryptographic operations, consider using the Web
199
+ * Crypto API's `crypto.subtle` with non-extractable keys when possible, as
200
+ * it provides stronger guarantees than what can be achieved with pure
201
+ * JavaScript.
202
+ *
203
+ * Accepts any of the standard numeric typed arrays — `Uint8Array`,
204
+ * `Uint8ClampedArray`, `Uint16Array`, `Uint32Array`, `Int8Array`,
205
+ * `Int16Array`, `Int32Array`, `Float32Array`, `Float64Array` — matching
206
+ * Rust's generic `&mut [T]`. (`BigInt64Array` / `BigUint64Array` are
207
+ * excluded because their elements are `bigint`, not `number`; if that
208
+ * support is needed, add a dedicated overload.)
209
+ */
210
+ function memzero(data) {
211
+ const len = data.length;
212
+ for (let i = 0; i < len; i++) data[i] = 0;
213
+ if (data.length > 0 && data[0] !== 0) throw new Error("memzero failed");
214
+ }
215
+ /**
216
+ * Securely zero out an array of Uint8Arrays.
217
+ */
218
+ function memzeroVecVecU8(arrays) {
219
+ for (const arr of arrays) memzero(arr);
220
+ }
221
+
180
222
  //#endregion
181
223
  //#region src/symmetric-encryption.ts
224
+ /**
225
+ * Copyright © 2023-2026 Blockchain Commons, LLC
226
+ * Copyright © 2025-2026 Parity Technologies
227
+ *
228
+ */
182
229
  const SYMMETRIC_KEY_SIZE = 32;
183
230
  const SYMMETRIC_NONCE_SIZE = 12;
184
231
  const SYMMETRIC_AUTH_SIZE = 16;
@@ -213,10 +260,10 @@ function aeadChaCha20Poly1305Encrypt(plaintext, key, nonce) {
213
260
  * @throws {CryptoError} If key is not 32 bytes or nonce is not 12 bytes
214
261
  */
215
262
  function aeadChaCha20Poly1305EncryptWithAad(plaintext, key, nonce, aad) {
216
- if (key.length !== SYMMETRIC_KEY_SIZE) throw CryptoError.invalidParameter(`Key must be ${SYMMETRIC_KEY_SIZE} bytes`);
217
- if (nonce.length !== SYMMETRIC_NONCE_SIZE) throw CryptoError.invalidParameter(`Nonce must be ${SYMMETRIC_NONCE_SIZE} bytes`);
263
+ if (key.length !== 32) throw CryptoError.invalidParameter(`Key must be ${32} bytes`);
264
+ if (nonce.length !== 12) throw CryptoError.invalidParameter(`Nonce must be ${12} bytes`);
218
265
  const sealed = chacha20poly1305(key, nonce, aad).encrypt(plaintext);
219
- return [sealed.slice(0, sealed.length - SYMMETRIC_AUTH_SIZE), sealed.slice(sealed.length - SYMMETRIC_AUTH_SIZE)];
266
+ return [sealed.slice(0, sealed.length - 16), sealed.slice(sealed.length - 16)];
220
267
  }
221
268
  /**
222
269
  * Decrypt data using ChaCha20-Poly1305 AEAD cipher.
@@ -245,9 +292,9 @@ function aeadChaCha20Poly1305Decrypt(ciphertext, key, nonce, authTag) {
245
292
  * @throws {CryptoError} If authentication fails (tampered data, wrong key/nonce, or AAD mismatch)
246
293
  */
247
294
  function aeadChaCha20Poly1305DecryptWithAad(ciphertext, key, nonce, aad, authTag) {
248
- if (key.length !== SYMMETRIC_KEY_SIZE) throw CryptoError.invalidParameter(`Key must be ${SYMMETRIC_KEY_SIZE} bytes`);
249
- if (nonce.length !== SYMMETRIC_NONCE_SIZE) throw CryptoError.invalidParameter(`Nonce must be ${SYMMETRIC_NONCE_SIZE} bytes`);
250
- if (authTag.length !== SYMMETRIC_AUTH_SIZE) throw CryptoError.invalidParameter(`Auth tag must be ${SYMMETRIC_AUTH_SIZE} bytes`);
295
+ if (key.length !== 32) throw CryptoError.invalidParameter(`Key must be ${32} bytes`);
296
+ if (nonce.length !== 12) throw CryptoError.invalidParameter(`Nonce must be ${12} bytes`);
297
+ if (authTag.length !== 16) throw CryptoError.invalidParameter(`Auth tag must be ${16} bytes`);
251
298
  const sealed = new Uint8Array(ciphertext.length + authTag.length);
252
299
  sealed.set(ciphertext);
253
300
  sealed.set(authTag, ciphertext.length);
@@ -261,8 +308,11 @@ function aeadChaCha20Poly1305DecryptWithAad(ciphertext, key, nonce, aad, authTag
261
308
 
262
309
  //#endregion
263
310
  //#region src/public-key-encryption.ts
264
- const GENERIC_PRIVATE_KEY_SIZE = 32;
265
- const GENERIC_PUBLIC_KEY_SIZE = 32;
311
+ /**
312
+ * Copyright © 2023-2026 Blockchain Commons, LLC
313
+ * Copyright © 2025-2026 Parity Technologies
314
+ *
315
+ */
266
316
  const X25519_PRIVATE_KEY_SIZE = 32;
267
317
  const X25519_PUBLIC_KEY_SIZE = 32;
268
318
  /**
@@ -270,7 +320,7 @@ const X25519_PUBLIC_KEY_SIZE = 32;
270
320
  * Uses HKDF with "agreement" as domain separation salt.
271
321
  */
272
322
  function deriveAgreementPrivateKey(keyMaterial) {
273
- return hkdfHmacSha256(keyMaterial, new TextEncoder().encode("agreement"), X25519_PRIVATE_KEY_SIZE);
323
+ return hkdfHmacSha256(keyMaterial, new TextEncoder().encode("agreement"), 32);
274
324
  }
275
325
  /**
276
326
  * Derive a signing private key from key material.
@@ -283,35 +333,52 @@ function deriveSigningPrivateKey(keyMaterial) {
283
333
  * Generate a new random X25519 private key.
284
334
  */
285
335
  function x25519NewPrivateKeyUsing(rng) {
286
- return rng.randomData(X25519_PRIVATE_KEY_SIZE);
336
+ return rng.randomData(32);
287
337
  }
288
338
  /**
289
339
  * Derive an X25519 public key from a private key.
290
340
  */
291
341
  function x25519PublicKeyFromPrivateKey(privateKey) {
292
- if (privateKey.length !== X25519_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${X25519_PRIVATE_KEY_SIZE} bytes`);
342
+ if (privateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
293
343
  return x25519.getPublicKey(privateKey);
294
344
  }
345
+ const SYMMETRIC_KEY_SIZE$1 = 32;
295
346
  /**
296
- * Compute a shared secret using X25519 key agreement (ECDH).
347
+ * Compute a shared symmetric key using X25519 key agreement (ECDH).
348
+ *
349
+ * This function performs X25519 Diffie-Hellman key agreement and then
350
+ * derives a symmetric key using HKDF-SHA256 with "agreement" as the salt.
351
+ * This matches the Rust bc-crypto implementation for cross-platform compatibility.
297
352
  *
298
- * **Security Note**: The resulting shared secret should be used with a KDF
299
- * (like HKDF) before using it as an encryption key. Never use the raw
300
- * shared secret directly for encryption.
353
+ * **Low-order public key handling.** The underlying `@noble/curves` X25519
354
+ * implementation rejects low-order public keys (where the u-coordinate is
355
+ * `0`) by throwing `'invalid private or public key received'`. Rust's
356
+ * `x25519-dalek` (v2.0-rc.2) instead silently produces the all-zero shared
357
+ * secret. This means an adversarial low-order public key fed in via TS
358
+ * surfaces as an exception, while in Rust it would yield an HKDF-derived
359
+ * key from a zero shared secret. For honest inputs both implementations
360
+ * produce byte-identical results; the TS port's stricter behaviour is a
361
+ * security improvement, not a parity bug.
301
362
  *
302
363
  * @param x25519Private - 32-byte X25519 private key
303
364
  * @param x25519Public - 32-byte X25519 public key from the other party
304
- * @returns 32-byte shared secret
365
+ * @returns 32-byte derived symmetric key
305
366
  * @throws {Error} If private key is not 32 bytes or public key is not 32 bytes
367
+ * @throws {Error} If the public key is low-order (`@noble/curves`-specific guard)
306
368
  */
307
369
  function x25519SharedKey(x25519Private, x25519Public) {
308
- if (x25519Private.length !== X25519_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${X25519_PRIVATE_KEY_SIZE} bytes`);
309
- if (x25519Public.length !== X25519_PUBLIC_KEY_SIZE) throw new Error(`Public key must be ${X25519_PUBLIC_KEY_SIZE} bytes`);
310
- return x25519.getSharedSecret(x25519Private, x25519Public);
370
+ if (x25519Private.length !== 32) throw new Error(`Private key must be ${32} bytes`);
371
+ if (x25519Public.length !== 32) throw new Error(`Public key must be ${32} bytes`);
372
+ return hkdfHmacSha256(x25519.getSharedSecret(x25519Private, x25519Public), new TextEncoder().encode("agreement"), SYMMETRIC_KEY_SIZE$1);
311
373
  }
312
374
 
313
375
  //#endregion
314
376
  //#region src/ecdsa-keys.ts
377
+ /**
378
+ * Copyright © 2023-2026 Blockchain Commons, LLC
379
+ * Copyright © 2025-2026 Parity Technologies
380
+ *
381
+ */
315
382
  const ECDSA_PRIVATE_KEY_SIZE = 32;
316
383
  const ECDSA_PUBLIC_KEY_SIZE = 33;
317
384
  const ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE = 65;
@@ -326,28 +393,28 @@ const SCHNORR_PUBLIC_KEY_SIZE = 32;
326
393
  * the key is used.
327
394
  */
328
395
  function ecdsaNewPrivateKeyUsing(rng) {
329
- return rng.randomData(ECDSA_PRIVATE_KEY_SIZE);
396
+ return rng.randomData(32);
330
397
  }
331
398
  /**
332
399
  * Derive a compressed ECDSA public key from a private key.
333
400
  */
334
401
  function ecdsaPublicKeyFromPrivateKey(privateKey) {
335
- if (privateKey.length !== ECDSA_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);
402
+ if (privateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
336
403
  return secp256k1.getPublicKey(privateKey, true);
337
404
  }
338
405
  /**
339
406
  * Decompress a compressed public key to uncompressed format.
340
407
  */
341
408
  function ecdsaDecompressPublicKey(compressed) {
342
- if (compressed.length !== ECDSA_PUBLIC_KEY_SIZE) throw new Error(`Compressed public key must be ${ECDSA_PUBLIC_KEY_SIZE} bytes`);
343
- return secp256k1.ProjectivePoint.fromHex(compressed).toRawBytes(false);
409
+ if (compressed.length !== 33) throw new Error(`Compressed public key must be ${33} bytes`);
410
+ return secp256k1.Point.fromBytes(compressed).toBytes(false);
344
411
  }
345
412
  /**
346
413
  * Compress an uncompressed public key.
347
414
  */
348
415
  function ecdsaCompressPublicKey(uncompressed) {
349
- if (uncompressed.length !== ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE) throw new Error(`Uncompressed public key must be ${ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE} bytes`);
350
- return secp256k1.ProjectivePoint.fromHex(uncompressed).toRawBytes(true);
416
+ if (uncompressed.length !== 65) throw new Error(`Uncompressed public key must be ${65} bytes`);
417
+ return secp256k1.Point.fromBytes(uncompressed).toBytes(true);
351
418
  }
352
419
  /**
353
420
  * Derive an ECDSA private key from key material using HKDF.
@@ -356,20 +423,25 @@ function ecdsaCompressPublicKey(uncompressed) {
356
423
  * matching the Rust reference implementation behavior.
357
424
  */
358
425
  function ecdsaDerivePrivateKey(keyMaterial) {
359
- return hkdfHmacSha256(keyMaterial, new TextEncoder().encode("signing"), ECDSA_PRIVATE_KEY_SIZE);
426
+ return hkdfHmacSha256(keyMaterial, new TextEncoder().encode("signing"), 32);
360
427
  }
361
428
  /**
362
429
  * Extract the x-only (Schnorr) public key from a private key.
363
430
  * This is used for BIP-340 Schnorr signatures.
364
431
  */
365
432
  function schnorrPublicKeyFromPrivateKey(privateKey) {
366
- if (privateKey.length !== ECDSA_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);
433
+ if (privateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
367
434
  return secp256k1.getPublicKey(privateKey, false).slice(1, 33);
368
435
  }
369
436
 
370
437
  //#endregion
371
438
  //#region src/ecdsa-signing.ts
372
439
  /**
440
+ * Copyright © 2023-2026 Blockchain Commons, LLC
441
+ * Copyright © 2025-2026 Parity Technologies
442
+ *
443
+ */
444
+ /**
373
445
  * Sign a message using ECDSA with secp256k1.
374
446
  *
375
447
  * The message is hashed with double SHA-256 before signing (Bitcoin standard).
@@ -384,9 +456,9 @@ function schnorrPublicKeyFromPrivateKey(privateKey) {
384
456
  * @throws {Error} If private key is not 32 bytes
385
457
  */
386
458
  function ecdsaSign(privateKey, message) {
387
- if (privateKey.length !== ECDSA_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);
459
+ if (privateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
388
460
  const messageHash = doubleSha256(message);
389
- return secp256k1.sign(messageHash, privateKey).toCompactRawBytes();
461
+ return secp256k1.sign(messageHash, privateKey, { prehash: false });
390
462
  }
391
463
  /**
392
464
  * Verify an ECDSA signature with secp256k1.
@@ -400,11 +472,11 @@ function ecdsaSign(privateKey, message) {
400
472
  * @throws {Error} If public key is not 33 bytes or signature is not 64 bytes
401
473
  */
402
474
  function ecdsaVerify(publicKey, signature, message) {
403
- if (publicKey.length !== ECDSA_PUBLIC_KEY_SIZE) throw new Error(`Public key must be ${ECDSA_PUBLIC_KEY_SIZE} bytes`);
404
- if (signature.length !== ECDSA_SIGNATURE_SIZE) throw new Error(`Signature must be ${ECDSA_SIGNATURE_SIZE} bytes`);
475
+ if (publicKey.length !== 33) throw new Error(`Public key must be ${33} bytes`);
476
+ if (signature.length !== 64) throw new Error(`Signature must be ${64} bytes`);
405
477
  try {
406
478
  const messageHash = doubleSha256(message);
407
- return secp256k1.verify(signature, messageHash, publicKey);
479
+ return secp256k1.verify(signature, messageHash, publicKey, { prehash: false });
408
480
  } catch {
409
481
  return false;
410
482
  }
@@ -412,6 +484,11 @@ function ecdsaVerify(publicKey, signature, message) {
412
484
 
413
485
  //#endregion
414
486
  //#region src/schnorr-signing.ts
487
+ /**
488
+ * Copyright © 2023-2026 Blockchain Commons, LLC
489
+ * Copyright © 2025-2026 Parity Technologies
490
+ *
491
+ */
415
492
  const SCHNORR_SIGNATURE_SIZE = 64;
416
493
  /**
417
494
  * Sign a message using Schnorr signature (BIP-340).
@@ -445,7 +522,7 @@ function schnorrSignUsing(ecdsaPrivateKey, message, rng) {
445
522
  * @returns 64-byte Schnorr signature
446
523
  */
447
524
  function schnorrSignWithAuxRand(ecdsaPrivateKey, message, auxRand) {
448
- if (ecdsaPrivateKey.length !== ECDSA_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);
525
+ if (ecdsaPrivateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
449
526
  if (auxRand.length !== 32) throw new Error("Auxiliary randomness must be 32 bytes");
450
527
  return schnorr.sign(message, ecdsaPrivateKey, auxRand);
451
528
  }
@@ -458,8 +535,8 @@ function schnorrSignWithAuxRand(ecdsaPrivateKey, message, auxRand) {
458
535
  * @returns true if signature is valid
459
536
  */
460
537
  function schnorrVerify(schnorrPublicKey, signature, message) {
461
- if (schnorrPublicKey.length !== SCHNORR_PUBLIC_KEY_SIZE) throw new Error(`Public key must be ${SCHNORR_PUBLIC_KEY_SIZE} bytes`);
462
- if (signature.length !== SCHNORR_SIGNATURE_SIZE) throw new Error(`Signature must be ${SCHNORR_SIGNATURE_SIZE} bytes`);
538
+ if (schnorrPublicKey.length !== 32) throw new Error(`Public key must be ${32} bytes`);
539
+ if (signature.length !== 64) throw new Error(`Signature must be ${64} bytes`);
463
540
  try {
464
541
  return schnorr.verify(signature, message, schnorrPublicKey);
465
542
  } catch {
@@ -469,6 +546,11 @@ function schnorrVerify(schnorrPublicKey, signature, message) {
469
546
 
470
547
  //#endregion
471
548
  //#region src/ed25519-signing.ts
549
+ /**
550
+ * Copyright © 2023-2026 Blockchain Commons, LLC
551
+ * Copyright © 2025-2026 Parity Technologies
552
+ *
553
+ */
472
554
  const ED25519_PUBLIC_KEY_SIZE = 32;
473
555
  const ED25519_PRIVATE_KEY_SIZE = 32;
474
556
  const ED25519_SIGNATURE_SIZE = 64;
@@ -476,13 +558,13 @@ const ED25519_SIGNATURE_SIZE = 64;
476
558
  * Generate a new random Ed25519 private key.
477
559
  */
478
560
  function ed25519NewPrivateKeyUsing(rng) {
479
- return rng.randomData(ED25519_PRIVATE_KEY_SIZE);
561
+ return rng.randomData(32);
480
562
  }
481
563
  /**
482
564
  * Derive an Ed25519 public key from a private key.
483
565
  */
484
566
  function ed25519PublicKeyFromPrivateKey(privateKey) {
485
- if (privateKey.length !== ED25519_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${ED25519_PRIVATE_KEY_SIZE} bytes`);
567
+ if (privateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
486
568
  return ed25519.getPublicKey(privateKey);
487
569
  }
488
570
  /**
@@ -497,7 +579,7 @@ function ed25519PublicKeyFromPrivateKey(privateKey) {
497
579
  * @throws {Error} If private key is not 32 bytes
498
580
  */
499
581
  function ed25519Sign(privateKey, message) {
500
- if (privateKey.length !== ED25519_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${ED25519_PRIVATE_KEY_SIZE} bytes`);
582
+ if (privateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
501
583
  return ed25519.sign(message, privateKey);
502
584
  }
503
585
  /**
@@ -510,8 +592,8 @@ function ed25519Sign(privateKey, message) {
510
592
  * @throws {Error} If public key is not 32 bytes or signature is not 64 bytes
511
593
  */
512
594
  function ed25519Verify(publicKey, message, signature) {
513
- if (publicKey.length !== ED25519_PUBLIC_KEY_SIZE) throw new Error(`Public key must be ${ED25519_PUBLIC_KEY_SIZE} bytes`);
514
- if (signature.length !== ED25519_SIGNATURE_SIZE) throw new Error(`Signature must be ${ED25519_SIGNATURE_SIZE} bytes`);
595
+ if (publicKey.length !== 32) throw new Error(`Public key must be ${32} bytes`);
596
+ if (signature.length !== 64) throw new Error(`Signature must be ${64} bytes`);
515
597
  try {
516
598
  return ed25519.verify(signature, message, publicKey);
517
599
  } catch {
@@ -522,8 +604,16 @@ function ed25519Verify(publicKey, message, signature) {
522
604
  //#endregion
523
605
  //#region src/scrypt.ts
524
606
  /**
607
+ * Copyright © 2023-2026 Blockchain Commons, LLC
608
+ * Copyright © 2025-2026 Parity Technologies
609
+ *
610
+ */
611
+ /**
525
612
  * Derive a key using Scrypt with recommended parameters.
526
- * Uses N=2^15 (32768), r=8, p=1 as recommended defaults.
613
+ *
614
+ * Mirrors Rust `bc_crypto::scrypt` which calls `scrypt::Params::recommended()`.
615
+ * The recommended parameters per the upstream `scrypt` crate are
616
+ * `log_n = 17` (N = 2^17 = 131072), `r = 8`, `p = 1`.
527
617
  *
528
618
  * @param password - Password or passphrase
529
619
  * @param salt - Salt value
@@ -531,7 +621,7 @@ function ed25519Verify(publicKey, message, signature) {
531
621
  * @returns Derived key
532
622
  */
533
623
  function scrypt(password, salt, outputLen) {
534
- return scryptOpt(password, salt, outputLen, 15, 8, 1);
624
+ return scryptOpt(password, salt, outputLen, 17, 8, 1);
535
625
  }
536
626
  /**
537
627
  * Derive a key using Scrypt with custom parameters.
@@ -559,15 +649,24 @@ function scryptOpt(password, salt, outputLen, logN, r, p) {
559
649
  //#endregion
560
650
  //#region src/argon.ts
561
651
  /**
652
+ * Copyright © 2023-2026 Blockchain Commons, LLC
653
+ * Copyright © 2025-2026 Parity Technologies
654
+ *
655
+ */
656
+ /**
562
657
  * Derive a key using Argon2id with default parameters.
563
658
  *
659
+ * Mirrors Rust `bc_crypto::argon2id` which calls `Argon2::default()`. The
660
+ * upstream `argon2` crate's defaults are `t = 2` iterations, `m = 19 * 1024
661
+ * = 19456` KiB of memory, `p = 1` lane (per `argon2-0.5.x/src/params.rs`).
662
+ *
564
663
  * @param password - Password or passphrase
565
664
  * @param salt - Salt value (must be at least 8 bytes)
566
665
  * @param outputLen - Desired output length
567
666
  * @returns Derived key
568
667
  */
569
- function argon2idHash(password, salt, outputLen) {
570
- return argon2idHashOpt(password, salt, outputLen, 3, 65536, 4);
668
+ function argon2id(password, salt, outputLen) {
669
+ return argon2idHashOpt(password, salt, outputLen, 2, 19456, 1);
571
670
  }
572
671
  /**
573
672
  * Derive a key using Argon2id with custom parameters.
@@ -581,7 +680,7 @@ function argon2idHash(password, salt, outputLen) {
581
680
  * @returns Derived key
582
681
  */
583
682
  function argon2idHashOpt(password, salt, outputLen, iterations, memory, parallelism) {
584
- return argon2id(password, salt, {
683
+ return argon2id$1(password, salt, {
585
684
  t: iterations,
586
685
  m: memory,
587
686
  p: parallelism,
@@ -590,5 +689,5 @@ function argon2idHashOpt(password, salt, outputLen, iterations, memory, parallel
590
689
  }
591
690
 
592
691
  //#endregion
593
- export { AeadError, CRC32_SIZE, CryptoError, ECDSA_MESSAGE_HASH_SIZE, ECDSA_PRIVATE_KEY_SIZE, ECDSA_PUBLIC_KEY_SIZE, ECDSA_SIGNATURE_SIZE, ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE, ED25519_PRIVATE_KEY_SIZE, ED25519_PUBLIC_KEY_SIZE, ED25519_SIGNATURE_SIZE, GENERIC_PRIVATE_KEY_SIZE, GENERIC_PUBLIC_KEY_SIZE, SCHNORR_PUBLIC_KEY_SIZE, SCHNORR_SIGNATURE_SIZE, SHA256_SIZE, SHA512_SIZE, SYMMETRIC_AUTH_SIZE, SYMMETRIC_KEY_SIZE, SYMMETRIC_NONCE_SIZE, X25519_PRIVATE_KEY_SIZE, X25519_PUBLIC_KEY_SIZE, aeadChaCha20Poly1305Decrypt, aeadChaCha20Poly1305DecryptWithAad, aeadChaCha20Poly1305Encrypt, aeadChaCha20Poly1305EncryptWithAad, argon2idHash, argon2idHashOpt, crc32, crc32Data, crc32DataOpt, deriveAgreementPrivateKey, deriveSigningPrivateKey, doubleSha256, ecdsaCompressPublicKey, ecdsaDecompressPublicKey, ecdsaDerivePrivateKey, ecdsaNewPrivateKeyUsing, ecdsaPublicKeyFromPrivateKey, ecdsaSign, ecdsaVerify, ed25519NewPrivateKeyUsing, ed25519PublicKeyFromPrivateKey, ed25519Sign, ed25519Verify, hkdfHmacSha256, hkdfHmacSha512, hmacSha256, hmacSha512, memzero, memzeroVecVecU8, pbkdf2HmacSha256, pbkdf2HmacSha512, schnorrPublicKeyFromPrivateKey, schnorrSign, schnorrSignUsing, schnorrSignWithAuxRand, schnorrVerify, scrypt, scryptOpt, sha256, sha512, x25519NewPrivateKeyUsing, x25519PublicKeyFromPrivateKey, x25519SharedKey };
692
+ export { AeadError, CRC32_SIZE, CryptoError, ECDSA_MESSAGE_HASH_SIZE, ECDSA_PRIVATE_KEY_SIZE, ECDSA_PUBLIC_KEY_SIZE, ECDSA_SIGNATURE_SIZE, ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE, ED25519_PRIVATE_KEY_SIZE, ED25519_PUBLIC_KEY_SIZE, ED25519_SIGNATURE_SIZE, SCHNORR_PUBLIC_KEY_SIZE, SCHNORR_SIGNATURE_SIZE, SHA256_SIZE, SHA512_SIZE, SYMMETRIC_AUTH_SIZE, SYMMETRIC_KEY_SIZE, SYMMETRIC_NONCE_SIZE, X25519_PRIVATE_KEY_SIZE, X25519_PUBLIC_KEY_SIZE, aeadChaCha20Poly1305Decrypt, aeadChaCha20Poly1305DecryptWithAad, aeadChaCha20Poly1305Encrypt, aeadChaCha20Poly1305EncryptWithAad, argon2id, deriveAgreementPrivateKey, deriveSigningPrivateKey, doubleSha256, ecdsaCompressPublicKey, ecdsaDecompressPublicKey, ecdsaDerivePrivateKey, ecdsaNewPrivateKeyUsing, ecdsaPublicKeyFromPrivateKey, ecdsaSign, ecdsaVerify, ed25519NewPrivateKeyUsing, ed25519PublicKeyFromPrivateKey, ed25519Sign, ed25519Verify, hash_exports as hash, hkdfHmacSha256, hmacSha256, hmacSha512, memzero, memzeroVecVecU8, pbkdf2HmacSha256, schnorrPublicKeyFromPrivateKey, schnorrSign, schnorrSignUsing, schnorrSignWithAuxRand, schnorrVerify, scrypt, scryptOpt, sha256, sha512, x25519NewPrivateKeyUsing, x25519PublicKeyFromPrivateKey, x25519SharedKey };
594
693
  //# sourceMappingURL=index.mjs.map