@bcts/crypto 1.0.0-alpha.22 → 1.0.0-alpha.23

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.cjs CHANGED
@@ -234,10 +234,10 @@ function aeadChaCha20Poly1305Encrypt(plaintext, key, nonce) {
234
234
  * @throws {CryptoError} If key is not 32 bytes or nonce is not 12 bytes
235
235
  */
236
236
  function aeadChaCha20Poly1305EncryptWithAad(plaintext, key, nonce, aad) {
237
- if (key.length !== SYMMETRIC_KEY_SIZE) throw CryptoError.invalidParameter(`Key must be ${SYMMETRIC_KEY_SIZE} bytes`);
238
- if (nonce.length !== SYMMETRIC_NONCE_SIZE) throw CryptoError.invalidParameter(`Nonce must be ${SYMMETRIC_NONCE_SIZE} bytes`);
237
+ if (key.length !== 32) throw CryptoError.invalidParameter(`Key must be ${32} bytes`);
238
+ if (nonce.length !== 12) throw CryptoError.invalidParameter(`Nonce must be ${12} bytes`);
239
239
  const sealed = (0, _noble_ciphers_chacha_js.chacha20poly1305)(key, nonce, aad).encrypt(plaintext);
240
- return [sealed.slice(0, sealed.length - SYMMETRIC_AUTH_SIZE), sealed.slice(sealed.length - SYMMETRIC_AUTH_SIZE)];
240
+ return [sealed.slice(0, sealed.length - 16), sealed.slice(sealed.length - 16)];
241
241
  }
242
242
  /**
243
243
  * Decrypt data using ChaCha20-Poly1305 AEAD cipher.
@@ -266,9 +266,9 @@ function aeadChaCha20Poly1305Decrypt(ciphertext, key, nonce, authTag) {
266
266
  * @throws {CryptoError} If authentication fails (tampered data, wrong key/nonce, or AAD mismatch)
267
267
  */
268
268
  function aeadChaCha20Poly1305DecryptWithAad(ciphertext, key, nonce, aad, authTag) {
269
- if (key.length !== SYMMETRIC_KEY_SIZE) throw CryptoError.invalidParameter(`Key must be ${SYMMETRIC_KEY_SIZE} bytes`);
270
- if (nonce.length !== SYMMETRIC_NONCE_SIZE) throw CryptoError.invalidParameter(`Nonce must be ${SYMMETRIC_NONCE_SIZE} bytes`);
271
- if (authTag.length !== SYMMETRIC_AUTH_SIZE) throw CryptoError.invalidParameter(`Auth tag must be ${SYMMETRIC_AUTH_SIZE} bytes`);
269
+ if (key.length !== 32) throw CryptoError.invalidParameter(`Key must be ${32} bytes`);
270
+ if (nonce.length !== 12) throw CryptoError.invalidParameter(`Nonce must be ${12} bytes`);
271
+ if (authTag.length !== 16) throw CryptoError.invalidParameter(`Auth tag must be ${16} bytes`);
272
272
  const sealed = new Uint8Array(ciphertext.length + authTag.length);
273
273
  sealed.set(ciphertext);
274
274
  sealed.set(authTag, ciphertext.length);
@@ -296,7 +296,7 @@ const X25519_PUBLIC_KEY_SIZE = 32;
296
296
  * Uses HKDF with "agreement" as domain separation salt.
297
297
  */
298
298
  function deriveAgreementPrivateKey(keyMaterial) {
299
- return hkdfHmacSha256(keyMaterial, new TextEncoder().encode("agreement"), X25519_PRIVATE_KEY_SIZE);
299
+ return hkdfHmacSha256(keyMaterial, new TextEncoder().encode("agreement"), 32);
300
300
  }
301
301
  /**
302
302
  * Derive a signing private key from key material.
@@ -309,13 +309,13 @@ function deriveSigningPrivateKey(keyMaterial) {
309
309
  * Generate a new random X25519 private key.
310
310
  */
311
311
  function x25519NewPrivateKeyUsing(rng) {
312
- return rng.randomData(X25519_PRIVATE_KEY_SIZE);
312
+ return rng.randomData(32);
313
313
  }
314
314
  /**
315
315
  * Derive an X25519 public key from a private key.
316
316
  */
317
317
  function x25519PublicKeyFromPrivateKey(privateKey) {
318
- if (privateKey.length !== X25519_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${X25519_PRIVATE_KEY_SIZE} bytes`);
318
+ if (privateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
319
319
  return _noble_curves_ed25519_js.x25519.getPublicKey(privateKey);
320
320
  }
321
321
  const SYMMETRIC_KEY_SIZE$1 = 32;
@@ -332,8 +332,8 @@ const SYMMETRIC_KEY_SIZE$1 = 32;
332
332
  * @throws {Error} If private key is not 32 bytes or public key is not 32 bytes
333
333
  */
334
334
  function x25519SharedKey(x25519Private, x25519Public) {
335
- if (x25519Private.length !== X25519_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${X25519_PRIVATE_KEY_SIZE} bytes`);
336
- if (x25519Public.length !== X25519_PUBLIC_KEY_SIZE) throw new Error(`Public key must be ${X25519_PUBLIC_KEY_SIZE} bytes`);
335
+ if (x25519Private.length !== 32) throw new Error(`Private key must be ${32} bytes`);
336
+ if (x25519Public.length !== 32) throw new Error(`Public key must be ${32} bytes`);
337
337
  return hkdfHmacSha256(_noble_curves_ed25519_js.x25519.getSharedSecret(x25519Private, x25519Public), new TextEncoder().encode("agreement"), SYMMETRIC_KEY_SIZE$1);
338
338
  }
339
339
 
@@ -358,27 +358,27 @@ const SCHNORR_PUBLIC_KEY_SIZE = 32;
358
358
  * the key is used.
359
359
  */
360
360
  function ecdsaNewPrivateKeyUsing(rng) {
361
- return rng.randomData(ECDSA_PRIVATE_KEY_SIZE);
361
+ return rng.randomData(32);
362
362
  }
363
363
  /**
364
364
  * Derive a compressed ECDSA public key from a private key.
365
365
  */
366
366
  function ecdsaPublicKeyFromPrivateKey(privateKey) {
367
- if (privateKey.length !== ECDSA_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);
367
+ if (privateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
368
368
  return _noble_curves_secp256k1_js.secp256k1.getPublicKey(privateKey, true);
369
369
  }
370
370
  /**
371
371
  * Decompress a compressed public key to uncompressed format.
372
372
  */
373
373
  function ecdsaDecompressPublicKey(compressed) {
374
- if (compressed.length !== ECDSA_PUBLIC_KEY_SIZE) throw new Error(`Compressed public key must be ${ECDSA_PUBLIC_KEY_SIZE} bytes`);
374
+ if (compressed.length !== 33) throw new Error(`Compressed public key must be ${33} bytes`);
375
375
  return _noble_curves_secp256k1_js.secp256k1.Point.fromBytes(compressed).toBytes(false);
376
376
  }
377
377
  /**
378
378
  * Compress an uncompressed public key.
379
379
  */
380
380
  function ecdsaCompressPublicKey(uncompressed) {
381
- if (uncompressed.length !== ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE) throw new Error(`Uncompressed public key must be ${ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE} bytes`);
381
+ if (uncompressed.length !== 65) throw new Error(`Uncompressed public key must be ${65} bytes`);
382
382
  return _noble_curves_secp256k1_js.secp256k1.Point.fromBytes(uncompressed).toBytes(true);
383
383
  }
384
384
  /**
@@ -388,14 +388,14 @@ function ecdsaCompressPublicKey(uncompressed) {
388
388
  * matching the Rust reference implementation behavior.
389
389
  */
390
390
  function ecdsaDerivePrivateKey(keyMaterial) {
391
- return hkdfHmacSha256(keyMaterial, new TextEncoder().encode("signing"), ECDSA_PRIVATE_KEY_SIZE);
391
+ return hkdfHmacSha256(keyMaterial, new TextEncoder().encode("signing"), 32);
392
392
  }
393
393
  /**
394
394
  * Extract the x-only (Schnorr) public key from a private key.
395
395
  * This is used for BIP-340 Schnorr signatures.
396
396
  */
397
397
  function schnorrPublicKeyFromPrivateKey(privateKey) {
398
- if (privateKey.length !== ECDSA_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);
398
+ if (privateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
399
399
  return _noble_curves_secp256k1_js.secp256k1.getPublicKey(privateKey, false).slice(1, 33);
400
400
  }
401
401
 
@@ -421,7 +421,7 @@ function schnorrPublicKeyFromPrivateKey(privateKey) {
421
421
  * @throws {Error} If private key is not 32 bytes
422
422
  */
423
423
  function ecdsaSign(privateKey, message) {
424
- if (privateKey.length !== ECDSA_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);
424
+ if (privateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
425
425
  const messageHash = doubleSha256(message);
426
426
  return _noble_curves_secp256k1_js.secp256k1.sign(messageHash, privateKey, { prehash: false });
427
427
  }
@@ -437,8 +437,8 @@ function ecdsaSign(privateKey, message) {
437
437
  * @throws {Error} If public key is not 33 bytes or signature is not 64 bytes
438
438
  */
439
439
  function ecdsaVerify(publicKey, signature, message) {
440
- if (publicKey.length !== ECDSA_PUBLIC_KEY_SIZE) throw new Error(`Public key must be ${ECDSA_PUBLIC_KEY_SIZE} bytes`);
441
- if (signature.length !== ECDSA_SIGNATURE_SIZE) throw new Error(`Signature must be ${ECDSA_SIGNATURE_SIZE} bytes`);
440
+ if (publicKey.length !== 33) throw new Error(`Public key must be ${33} bytes`);
441
+ if (signature.length !== 64) throw new Error(`Signature must be ${64} bytes`);
442
442
  try {
443
443
  const messageHash = doubleSha256(message);
444
444
  return _noble_curves_secp256k1_js.secp256k1.verify(signature, messageHash, publicKey, { prehash: false });
@@ -487,7 +487,7 @@ function schnorrSignUsing(ecdsaPrivateKey, message, rng) {
487
487
  * @returns 64-byte Schnorr signature
488
488
  */
489
489
  function schnorrSignWithAuxRand(ecdsaPrivateKey, message, auxRand) {
490
- if (ecdsaPrivateKey.length !== ECDSA_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);
490
+ if (ecdsaPrivateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
491
491
  if (auxRand.length !== 32) throw new Error("Auxiliary randomness must be 32 bytes");
492
492
  return _noble_curves_secp256k1_js.schnorr.sign(message, ecdsaPrivateKey, auxRand);
493
493
  }
@@ -500,8 +500,8 @@ function schnorrSignWithAuxRand(ecdsaPrivateKey, message, auxRand) {
500
500
  * @returns true if signature is valid
501
501
  */
502
502
  function schnorrVerify(schnorrPublicKey, signature, message) {
503
- if (schnorrPublicKey.length !== SCHNORR_PUBLIC_KEY_SIZE) throw new Error(`Public key must be ${SCHNORR_PUBLIC_KEY_SIZE} bytes`);
504
- if (signature.length !== SCHNORR_SIGNATURE_SIZE) throw new Error(`Signature must be ${SCHNORR_SIGNATURE_SIZE} bytes`);
503
+ if (schnorrPublicKey.length !== 32) throw new Error(`Public key must be ${32} bytes`);
504
+ if (signature.length !== 64) throw new Error(`Signature must be ${64} bytes`);
505
505
  try {
506
506
  return _noble_curves_secp256k1_js.schnorr.verify(signature, message, schnorrPublicKey);
507
507
  } catch {
@@ -523,13 +523,13 @@ const ED25519_SIGNATURE_SIZE = 64;
523
523
  * Generate a new random Ed25519 private key.
524
524
  */
525
525
  function ed25519NewPrivateKeyUsing(rng) {
526
- return rng.randomData(ED25519_PRIVATE_KEY_SIZE);
526
+ return rng.randomData(32);
527
527
  }
528
528
  /**
529
529
  * Derive an Ed25519 public key from a private key.
530
530
  */
531
531
  function ed25519PublicKeyFromPrivateKey(privateKey) {
532
- if (privateKey.length !== ED25519_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${ED25519_PRIVATE_KEY_SIZE} bytes`);
532
+ if (privateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
533
533
  return _noble_curves_ed25519_js.ed25519.getPublicKey(privateKey);
534
534
  }
535
535
  /**
@@ -544,7 +544,7 @@ function ed25519PublicKeyFromPrivateKey(privateKey) {
544
544
  * @throws {Error} If private key is not 32 bytes
545
545
  */
546
546
  function ed25519Sign(privateKey, message) {
547
- if (privateKey.length !== ED25519_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${ED25519_PRIVATE_KEY_SIZE} bytes`);
547
+ if (privateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
548
548
  return _noble_curves_ed25519_js.ed25519.sign(message, privateKey);
549
549
  }
550
550
  /**
@@ -557,8 +557,8 @@ function ed25519Sign(privateKey, message) {
557
557
  * @throws {Error} If public key is not 32 bytes or signature is not 64 bytes
558
558
  */
559
559
  function ed25519Verify(publicKey, message, signature) {
560
- if (publicKey.length !== ED25519_PUBLIC_KEY_SIZE) throw new Error(`Public key must be ${ED25519_PUBLIC_KEY_SIZE} bytes`);
561
- if (signature.length !== ED25519_SIGNATURE_SIZE) throw new Error(`Signature must be ${ED25519_SIGNATURE_SIZE} bytes`);
560
+ if (publicKey.length !== 32) throw new Error(`Public key must be ${32} bytes`);
561
+ if (signature.length !== 64) throw new Error(`Signature must be ${64} bytes`);
562
562
  try {
563
563
  return _noble_curves_ed25519_js.ed25519.verify(signature, message, publicKey);
564
564
  } catch {
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["nobleSha256","nobleSha512","x25519","SYMMETRIC_KEY_SIZE","secp256k1","secp256k1","SecureRandomNumberGenerator","schnorr","ed25519"],"sources":["../src/error.ts","../src/memzero.ts","../src/hash.ts","../src/symmetric-encryption.ts","../src/public-key-encryption.ts","../src/ecdsa-keys.ts","../src/ecdsa-signing.ts","../src/schnorr-signing.ts","../src/ed25519-signing.ts","../src/scrypt.ts","../src/argon.ts"],"sourcesContent":["/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/error.rs\n\n/**\n * AEAD-specific error for authentication failures\n */\nexport class AeadError extends Error {\n constructor(message = \"AEAD authentication failed\") {\n super(message);\n this.name = \"AeadError\";\n }\n}\n\n/**\n * Generic crypto error type\n */\nexport class CryptoError extends Error {\n override readonly cause?: Error | undefined;\n\n constructor(message: string, cause?: Error) {\n super(message);\n this.name = \"CryptoError\";\n this.cause = cause;\n }\n\n /**\n * Create a CryptoError for AEAD authentication failures.\n *\n * @param error - Optional underlying AeadError\n * @returns A CryptoError wrapping the AEAD error\n */\n static aead(error?: AeadError): CryptoError {\n return new CryptoError(\"AEAD error\", error ?? new AeadError());\n }\n\n /**\n * Create a CryptoError for invalid parameter values.\n *\n * @param message - Description of the invalid parameter\n * @returns A CryptoError describing the invalid parameter\n */\n static invalidParameter(message: string): CryptoError {\n return new CryptoError(`Invalid parameter: ${message}`);\n }\n}\n\n/**\n * Result type for crypto operations (using standard Error)\n */\nexport type CryptoResult<T> = T;\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/memzero.rs\n\n/**\n * Securely zero out a typed array.\n *\n * **IMPORTANT: This is a best-effort implementation.** Unlike the Rust reference\n * implementation which uses `std::ptr::write_volatile()` for guaranteed volatile\n * writes, JavaScript engines and JIT compilers can still potentially optimize\n * away these zeroing operations. The check at the end helps prevent optimization,\n * but it is not foolproof.\n *\n * For truly sensitive cryptographic operations, consider using the Web Crypto API's\n * `crypto.subtle` with non-extractable keys when possible, as it provides stronger\n * guarantees than what can be achieved with pure JavaScript.\n *\n * This function attempts to prevent the compiler from optimizing away\n * the zeroing operation by using a verification check after the zeroing loop.\n */\nexport function memzero(data: Uint8Array | Uint32Array): void {\n const len = data.length;\n for (let i = 0; i < len; i++) {\n data[i] = 0;\n }\n // Force a side effect to prevent optimization\n if (data.length > 0 && data[0] !== 0) {\n throw new Error(\"memzero failed\");\n }\n}\n\n/**\n * Securely zero out an array of Uint8Arrays.\n */\nexport function memzeroVecVecU8(arrays: Uint8Array[]): void {\n for (const arr of arrays) {\n memzero(arr);\n }\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/hash.rs\n\nimport { sha256 as nobleSha256, sha512 as nobleSha512 } from \"@noble/hashes/sha2.js\";\nimport { hmac } from \"@noble/hashes/hmac.js\";\nimport { pbkdf2 } from \"@noble/hashes/pbkdf2.js\";\nimport { hkdf } from \"@noble/hashes/hkdf.js\";\n\n// Constants\nexport const CRC32_SIZE = 4;\nexport const SHA256_SIZE = 32;\nexport const SHA512_SIZE = 64;\n\n// CRC-32 lookup table (IEEE polynomial 0xedb88320)\nconst CRC32_TABLE = new Uint32Array(256);\nfor (let i = 0; i < 256; i++) {\n let crc = i;\n for (let j = 0; j < 8; j++) {\n crc = (crc & 1) !== 0 ? (crc >>> 1) ^ 0xedb88320 : crc >>> 1;\n }\n CRC32_TABLE[i] = crc >>> 0;\n}\n\n/**\n * Calculate CRC-32 checksum\n */\nexport function crc32(data: Uint8Array): number {\n let crc = 0xffffffff;\n for (const byte of data) {\n crc = CRC32_TABLE[(crc ^ byte) & 0xff] ^ (crc >>> 8);\n }\n return (crc ^ 0xffffffff) >>> 0;\n}\n\n/**\n * Calculate CRC-32 checksum and return as a 4-byte big-endian array\n */\nexport function crc32Data(data: Uint8Array): Uint8Array {\n return crc32DataOpt(data, false);\n}\n\n/**\n * Calculate CRC-32 checksum and return as a 4-byte array\n * @param data - Input data\n * @param littleEndian - If true, returns little-endian; otherwise big-endian\n */\nexport function crc32DataOpt(data: Uint8Array, littleEndian: boolean): Uint8Array {\n const checksum = crc32(data);\n const result = new Uint8Array(4);\n const view = new DataView(result.buffer);\n view.setUint32(0, checksum, littleEndian);\n return result;\n}\n\n/**\n * Calculate SHA-256 hash\n */\nexport function sha256(data: Uint8Array): Uint8Array {\n return nobleSha256(data);\n}\n\n/**\n * Calculate double SHA-256 hash (SHA-256 of SHA-256)\n * This is the standard Bitcoin hashing function\n */\nexport function doubleSha256(message: Uint8Array): Uint8Array {\n return sha256(sha256(message));\n}\n\n/**\n * Calculate SHA-512 hash\n */\nexport function sha512(data: Uint8Array): Uint8Array {\n return nobleSha512(data);\n}\n\n/**\n * Calculate HMAC-SHA-256\n */\nexport function hmacSha256(key: Uint8Array, message: Uint8Array): Uint8Array {\n return hmac(nobleSha256, key, message);\n}\n\n/**\n * Calculate HMAC-SHA-512\n */\nexport function hmacSha512(key: Uint8Array, message: Uint8Array): Uint8Array {\n return hmac(nobleSha512, key, message);\n}\n\n/**\n * Derive a key using PBKDF2 with HMAC-SHA-256\n */\nexport function pbkdf2HmacSha256(\n password: Uint8Array,\n salt: Uint8Array,\n iterations: number,\n keyLen: number,\n): Uint8Array {\n return pbkdf2(nobleSha256, password, salt, { c: iterations, dkLen: keyLen });\n}\n\n/**\n * Derive a key using PBKDF2 with HMAC-SHA-512\n */\nexport function pbkdf2HmacSha512(\n password: Uint8Array,\n salt: Uint8Array,\n iterations: number,\n keyLen: number,\n): Uint8Array {\n return pbkdf2(nobleSha512, password, salt, { c: iterations, dkLen: keyLen });\n}\n\n/**\n * Derive a key using HKDF with HMAC-SHA-256\n */\nexport function hkdfHmacSha256(\n keyMaterial: Uint8Array,\n salt: Uint8Array,\n keyLen: number,\n): Uint8Array {\n return hkdf(nobleSha256, keyMaterial, salt, undefined, keyLen);\n}\n\n/**\n * Derive a key using HKDF with HMAC-SHA-512\n */\nexport function hkdfHmacSha512(\n keyMaterial: Uint8Array,\n salt: Uint8Array,\n keyLen: number,\n): Uint8Array {\n return hkdf(nobleSha512, keyMaterial, salt, undefined, keyLen);\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/symmetric_encryption.rs\n\nimport { chacha20poly1305 } from \"@noble/ciphers/chacha.js\";\nimport { CryptoError, AeadError } from \"./error.js\";\n\n// Constants\nexport const SYMMETRIC_KEY_SIZE = 32;\nexport const SYMMETRIC_NONCE_SIZE = 12;\nexport const SYMMETRIC_AUTH_SIZE = 16;\n\n/**\n * Encrypt data using ChaCha20-Poly1305 AEAD cipher.\n *\n * **Security Warning**: The nonce MUST be unique for every encryption operation\n * with the same key. Reusing a nonce completely breaks the security of the\n * encryption scheme and can reveal plaintext.\n *\n * @param plaintext - The data to encrypt\n * @param key - 32-byte encryption key\n * @param nonce - 12-byte nonce (MUST be unique per encryption with the same key)\n * @returns Tuple of [ciphertext, authTag] where authTag is 16 bytes\n * @throws {CryptoError} If key is not 32 bytes or nonce is not 12 bytes\n */\nexport function aeadChaCha20Poly1305Encrypt(\n plaintext: Uint8Array,\n key: Uint8Array,\n nonce: Uint8Array,\n): [Uint8Array, Uint8Array] {\n return aeadChaCha20Poly1305EncryptWithAad(plaintext, key, nonce, new Uint8Array(0));\n}\n\n/**\n * Encrypt data using ChaCha20-Poly1305 AEAD cipher with additional authenticated data.\n *\n * **Security Warning**: The nonce MUST be unique for every encryption operation\n * with the same key. Reusing a nonce completely breaks the security of the\n * encryption scheme and can reveal plaintext.\n *\n * @param plaintext - The data to encrypt\n * @param key - 32-byte encryption key\n * @param nonce - 12-byte nonce (MUST be unique per encryption with the same key)\n * @param aad - Additional authenticated data (not encrypted, but integrity-protected)\n * @returns Tuple of [ciphertext, authTag] where authTag is 16 bytes\n * @throws {CryptoError} If key is not 32 bytes or nonce is not 12 bytes\n */\nexport function aeadChaCha20Poly1305EncryptWithAad(\n plaintext: Uint8Array,\n key: Uint8Array,\n nonce: Uint8Array,\n aad: Uint8Array,\n): [Uint8Array, Uint8Array] {\n if (key.length !== SYMMETRIC_KEY_SIZE) {\n throw CryptoError.invalidParameter(`Key must be ${SYMMETRIC_KEY_SIZE} bytes`);\n }\n if (nonce.length !== SYMMETRIC_NONCE_SIZE) {\n throw CryptoError.invalidParameter(`Nonce must be ${SYMMETRIC_NONCE_SIZE} bytes`);\n }\n\n const cipher = chacha20poly1305(key, nonce, aad);\n const sealed = cipher.encrypt(plaintext);\n\n // The sealed output contains ciphertext + 16-byte auth tag\n const ciphertext = sealed.slice(0, sealed.length - SYMMETRIC_AUTH_SIZE);\n const authTag = sealed.slice(sealed.length - SYMMETRIC_AUTH_SIZE);\n\n return [ciphertext, authTag];\n}\n\n/**\n * Decrypt data using ChaCha20-Poly1305 AEAD cipher.\n *\n * @param ciphertext - The encrypted data\n * @param key - 32-byte encryption key (must match key used for encryption)\n * @param nonce - 12-byte nonce (must match nonce used for encryption)\n * @param authTag - 16-byte authentication tag from encryption\n * @returns Decrypted plaintext\n * @throws {CryptoError} If key/nonce/authTag sizes are invalid\n * @throws {CryptoError} If authentication fails (tampered data or wrong key/nonce)\n */\nexport function aeadChaCha20Poly1305Decrypt(\n ciphertext: Uint8Array,\n key: Uint8Array,\n nonce: Uint8Array,\n authTag: Uint8Array,\n): Uint8Array {\n return aeadChaCha20Poly1305DecryptWithAad(ciphertext, key, nonce, new Uint8Array(0), authTag);\n}\n\n/**\n * Decrypt data using ChaCha20-Poly1305 AEAD cipher with additional authenticated data.\n *\n * @param ciphertext - The encrypted data\n * @param key - 32-byte encryption key (must match key used for encryption)\n * @param nonce - 12-byte nonce (must match nonce used for encryption)\n * @param aad - Additional authenticated data (must exactly match AAD used for encryption)\n * @param authTag - 16-byte authentication tag from encryption\n * @returns Decrypted plaintext\n * @throws {CryptoError} If key/nonce/authTag sizes are invalid\n * @throws {CryptoError} If authentication fails (tampered data, wrong key/nonce, or AAD mismatch)\n */\nexport function aeadChaCha20Poly1305DecryptWithAad(\n ciphertext: Uint8Array,\n key: Uint8Array,\n nonce: Uint8Array,\n aad: Uint8Array,\n authTag: Uint8Array,\n): Uint8Array {\n if (key.length !== SYMMETRIC_KEY_SIZE) {\n throw CryptoError.invalidParameter(`Key must be ${SYMMETRIC_KEY_SIZE} bytes`);\n }\n if (nonce.length !== SYMMETRIC_NONCE_SIZE) {\n throw CryptoError.invalidParameter(`Nonce must be ${SYMMETRIC_NONCE_SIZE} bytes`);\n }\n if (authTag.length !== SYMMETRIC_AUTH_SIZE) {\n throw CryptoError.invalidParameter(`Auth tag must be ${SYMMETRIC_AUTH_SIZE} bytes`);\n }\n\n // Combine ciphertext and auth tag for decryption\n const sealed = new Uint8Array(ciphertext.length + authTag.length);\n sealed.set(ciphertext);\n sealed.set(authTag, ciphertext.length);\n\n try {\n const cipher = chacha20poly1305(key, nonce, aad);\n return cipher.decrypt(sealed);\n } catch (error) {\n // Preserve the original error for debugging while wrapping in our error type\n const aeadError = new AeadError(\n `Decryption failed: ${error instanceof Error ? error.message : \"authentication error\"}`,\n );\n throw CryptoError.aead(aeadError);\n }\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/public_key_encryption.rs\n\nimport { x25519 } from \"@noble/curves/ed25519.js\";\nimport type { RandomNumberGenerator } from \"@bcts/rand\";\nimport { hkdfHmacSha256 } from \"./hash.js\";\n\n// Constants\nexport const GENERIC_PRIVATE_KEY_SIZE = 32;\nexport const GENERIC_PUBLIC_KEY_SIZE = 32;\nexport const X25519_PRIVATE_KEY_SIZE = 32;\nexport const X25519_PUBLIC_KEY_SIZE = 32;\n\n/**\n * Derive an X25519 agreement private key from key material.\n * Uses HKDF with \"agreement\" as domain separation salt.\n */\nexport function deriveAgreementPrivateKey(keyMaterial: Uint8Array): Uint8Array {\n const salt = new TextEncoder().encode(\"agreement\");\n return hkdfHmacSha256(keyMaterial, salt, X25519_PRIVATE_KEY_SIZE);\n}\n\n/**\n * Derive a signing private key from key material.\n * Uses HKDF with \"signing\" as domain separation salt.\n */\nexport function deriveSigningPrivateKey(keyMaterial: Uint8Array): Uint8Array {\n const salt = new TextEncoder().encode(\"signing\");\n return hkdfHmacSha256(keyMaterial, salt, 32);\n}\n\n/**\n * Generate a new random X25519 private key.\n */\nexport function x25519NewPrivateKeyUsing(rng: RandomNumberGenerator): Uint8Array {\n return rng.randomData(X25519_PRIVATE_KEY_SIZE);\n}\n\n/**\n * Derive an X25519 public key from a private key.\n */\nexport function x25519PublicKeyFromPrivateKey(privateKey: Uint8Array): Uint8Array {\n if (privateKey.length !== X25519_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${X25519_PRIVATE_KEY_SIZE} bytes`);\n }\n return x25519.getPublicKey(privateKey);\n}\n\n// Symmetric key size for the derived shared key\nconst SYMMETRIC_KEY_SIZE = 32;\n\n/**\n * Compute a shared symmetric key using X25519 key agreement (ECDH).\n *\n * This function performs X25519 Diffie-Hellman key agreement and then\n * derives a symmetric key using HKDF-SHA256 with \"agreement\" as the salt.\n * This matches the Rust bc-crypto implementation for cross-platform compatibility.\n *\n * @param x25519Private - 32-byte X25519 private key\n * @param x25519Public - 32-byte X25519 public key from the other party\n * @returns 32-byte derived symmetric key\n * @throws {Error} If private key is not 32 bytes or public key is not 32 bytes\n */\nexport function x25519SharedKey(x25519Private: Uint8Array, x25519Public: Uint8Array): Uint8Array {\n if (x25519Private.length !== X25519_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${X25519_PRIVATE_KEY_SIZE} bytes`);\n }\n if (x25519Public.length !== X25519_PUBLIC_KEY_SIZE) {\n throw new Error(`Public key must be ${X25519_PUBLIC_KEY_SIZE} bytes`);\n }\n // Perform raw X25519 Diffie-Hellman\n const rawSharedSecret = x25519.getSharedSecret(x25519Private, x25519Public);\n // Derive symmetric key using HKDF with \"agreement\" salt (matches Rust implementation)\n const salt = new TextEncoder().encode(\"agreement\");\n return hkdfHmacSha256(rawSharedSecret, salt, SYMMETRIC_KEY_SIZE);\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/ecdsa_keys.rs\n\nimport { secp256k1 } from \"@noble/curves/secp256k1.js\";\nimport type { RandomNumberGenerator } from \"@bcts/rand\";\nimport { hkdfHmacSha256 } from \"./hash.js\";\n\n// Constants\nexport const ECDSA_PRIVATE_KEY_SIZE = 32;\nexport const ECDSA_PUBLIC_KEY_SIZE = 33; // Compressed\nexport const ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE = 65;\nexport const ECDSA_MESSAGE_HASH_SIZE = 32;\nexport const ECDSA_SIGNATURE_SIZE = 64;\nexport const SCHNORR_PUBLIC_KEY_SIZE = 32; // x-only\n\n/**\n * Generate a new random ECDSA private key using secp256k1.\n *\n * Note: Unlike some implementations, this directly returns the random bytes\n * without validation. The secp256k1 library will handle any edge cases when\n * the key is used.\n */\nexport function ecdsaNewPrivateKeyUsing(rng: RandomNumberGenerator): Uint8Array {\n return rng.randomData(ECDSA_PRIVATE_KEY_SIZE);\n}\n\n/**\n * Derive a compressed ECDSA public key from a private key.\n */\nexport function ecdsaPublicKeyFromPrivateKey(privateKey: Uint8Array): Uint8Array {\n if (privateKey.length !== ECDSA_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);\n }\n return secp256k1.getPublicKey(privateKey, true); // true = compressed\n}\n\n/**\n * Decompress a compressed public key to uncompressed format.\n */\nexport function ecdsaDecompressPublicKey(compressed: Uint8Array): Uint8Array {\n if (compressed.length !== ECDSA_PUBLIC_KEY_SIZE) {\n throw new Error(`Compressed public key must be ${ECDSA_PUBLIC_KEY_SIZE} bytes`);\n }\n const point = secp256k1.Point.fromBytes(compressed);\n return point.toBytes(false); // false = uncompressed\n}\n\n/**\n * Compress an uncompressed public key.\n */\nexport function ecdsaCompressPublicKey(uncompressed: Uint8Array): Uint8Array {\n if (uncompressed.length !== ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE) {\n throw new Error(`Uncompressed public key must be ${ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE} bytes`);\n }\n const point = secp256k1.Point.fromBytes(uncompressed);\n return point.toBytes(true); // true = compressed\n}\n\n/**\n * Derive an ECDSA private key from key material using HKDF.\n *\n * Note: This directly returns the HKDF output without validation,\n * matching the Rust reference implementation behavior.\n */\nexport function ecdsaDerivePrivateKey(keyMaterial: Uint8Array): Uint8Array {\n const salt = new TextEncoder().encode(\"signing\");\n return hkdfHmacSha256(keyMaterial, salt, ECDSA_PRIVATE_KEY_SIZE);\n}\n\n/**\n * Extract the x-only (Schnorr) public key from a private key.\n * This is used for BIP-340 Schnorr signatures.\n */\nexport function schnorrPublicKeyFromPrivateKey(privateKey: Uint8Array): Uint8Array {\n if (privateKey.length !== ECDSA_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);\n }\n // Get the full public key and extract just the x-coordinate\n const fullPubKey = secp256k1.getPublicKey(privateKey, false); // uncompressed\n // Skip the 0x04 prefix and take only x-coordinate (first 32 bytes after prefix)\n return fullPubKey.slice(1, 33);\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/ecdsa_signing.rs\n\nimport { secp256k1 } from \"@noble/curves/secp256k1.js\";\nimport { doubleSha256 } from \"./hash.js\";\nimport {\n ECDSA_PRIVATE_KEY_SIZE,\n ECDSA_PUBLIC_KEY_SIZE,\n ECDSA_SIGNATURE_SIZE,\n} from \"./ecdsa-keys.js\";\n\n/**\n * Sign a message using ECDSA with secp256k1.\n *\n * The message is hashed with double SHA-256 before signing (Bitcoin standard).\n *\n * **Security Note**: The private key must be kept secret. ECDSA requires\n * cryptographically secure random nonces internally; this is handled by\n * the underlying library using RFC 6979 deterministic nonces.\n *\n * @param privateKey - 32-byte secp256k1 private key\n * @param message - Message to sign (any length, will be double-SHA256 hashed)\n * @returns 64-byte compact signature (r || s format)\n * @throws {Error} If private key is not 32 bytes\n */\nexport function ecdsaSign(privateKey: Uint8Array, message: Uint8Array): Uint8Array {\n if (privateKey.length !== ECDSA_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);\n }\n\n const messageHash = doubleSha256(message);\n // prehash: false because we already hashed the message with doubleSha256\n return secp256k1.sign(messageHash, privateKey, { prehash: false });\n}\n\n/**\n * Verify an ECDSA signature with secp256k1.\n *\n * The message is hashed with double SHA-256 before verification (Bitcoin standard).\n *\n * @param publicKey - 33-byte compressed secp256k1 public key\n * @param signature - 64-byte compact signature (r || s format)\n * @param message - Original message that was signed\n * @returns `true` if signature is valid, `false` if signature verification fails\n * @throws {Error} If public key is not 33 bytes or signature is not 64 bytes\n */\nexport function ecdsaVerify(\n publicKey: Uint8Array,\n signature: Uint8Array,\n message: Uint8Array,\n): boolean {\n if (publicKey.length !== ECDSA_PUBLIC_KEY_SIZE) {\n throw new Error(`Public key must be ${ECDSA_PUBLIC_KEY_SIZE} bytes`);\n }\n if (signature.length !== ECDSA_SIGNATURE_SIZE) {\n throw new Error(`Signature must be ${ECDSA_SIGNATURE_SIZE} bytes`);\n }\n\n try {\n const messageHash = doubleSha256(message);\n // prehash: false because we already hashed the message with doubleSha256\n return secp256k1.verify(signature, messageHash, publicKey, { prehash: false });\n } catch {\n return false;\n }\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/schnorr_signing.rs\n\nimport { schnorr } from \"@noble/curves/secp256k1.js\";\nimport type { RandomNumberGenerator } from \"@bcts/rand\";\nimport { SecureRandomNumberGenerator } from \"@bcts/rand\";\nimport { ECDSA_PRIVATE_KEY_SIZE, SCHNORR_PUBLIC_KEY_SIZE } from \"./ecdsa-keys.js\";\n\n// Constants\nexport const SCHNORR_SIGNATURE_SIZE = 64;\n\n/**\n * Sign a message using Schnorr signature (BIP-340).\n * Uses secure random auxiliary randomness.\n *\n * @param ecdsaPrivateKey - 32-byte private key\n * @param message - Message to sign (not pre-hashed, per BIP-340)\n * @returns 64-byte Schnorr signature\n */\nexport function schnorrSign(ecdsaPrivateKey: Uint8Array, message: Uint8Array): Uint8Array {\n const rng = new SecureRandomNumberGenerator();\n return schnorrSignUsing(ecdsaPrivateKey, message, rng);\n}\n\n/**\n * Sign a message using Schnorr signature with a custom RNG.\n *\n * @param ecdsaPrivateKey - 32-byte private key\n * @param message - Message to sign\n * @param rng - Random number generator for auxiliary randomness\n * @returns 64-byte Schnorr signature\n */\nexport function schnorrSignUsing(\n ecdsaPrivateKey: Uint8Array,\n message: Uint8Array,\n rng: RandomNumberGenerator,\n): Uint8Array {\n const auxRand = rng.randomData(32);\n return schnorrSignWithAuxRand(ecdsaPrivateKey, message, auxRand);\n}\n\n/**\n * Sign a message using Schnorr signature with specific auxiliary randomness.\n * This is useful for deterministic signing in tests.\n *\n * @param ecdsaPrivateKey - 32-byte private key\n * @param message - Message to sign\n * @param auxRand - 32-byte auxiliary randomness (per BIP-340)\n * @returns 64-byte Schnorr signature\n */\nexport function schnorrSignWithAuxRand(\n ecdsaPrivateKey: Uint8Array,\n message: Uint8Array,\n auxRand: Uint8Array,\n): Uint8Array {\n if (ecdsaPrivateKey.length !== ECDSA_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);\n }\n if (auxRand.length !== 32) {\n throw new Error(\"Auxiliary randomness must be 32 bytes\");\n }\n\n return schnorr.sign(message, ecdsaPrivateKey, auxRand);\n}\n\n/**\n * Verify a Schnorr signature (BIP-340).\n *\n * @param schnorrPublicKey - 32-byte x-only public key\n * @param signature - 64-byte Schnorr signature\n * @param message - Original message\n * @returns true if signature is valid\n */\nexport function schnorrVerify(\n schnorrPublicKey: Uint8Array,\n signature: Uint8Array,\n message: Uint8Array,\n): boolean {\n if (schnorrPublicKey.length !== SCHNORR_PUBLIC_KEY_SIZE) {\n throw new Error(`Public key must be ${SCHNORR_PUBLIC_KEY_SIZE} bytes`);\n }\n if (signature.length !== SCHNORR_SIGNATURE_SIZE) {\n throw new Error(`Signature must be ${SCHNORR_SIGNATURE_SIZE} bytes`);\n }\n\n try {\n return schnorr.verify(signature, message, schnorrPublicKey);\n } catch {\n return false;\n }\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/ed25519_signing.rs\n\nimport { ed25519 } from \"@noble/curves/ed25519.js\";\nimport type { RandomNumberGenerator } from \"@bcts/rand\";\n\n// Constants\nexport const ED25519_PUBLIC_KEY_SIZE = 32;\nexport const ED25519_PRIVATE_KEY_SIZE = 32;\nexport const ED25519_SIGNATURE_SIZE = 64;\n\n/**\n * Generate a new random Ed25519 private key.\n */\nexport function ed25519NewPrivateKeyUsing(rng: RandomNumberGenerator): Uint8Array {\n return rng.randomData(ED25519_PRIVATE_KEY_SIZE);\n}\n\n/**\n * Derive an Ed25519 public key from a private key.\n */\nexport function ed25519PublicKeyFromPrivateKey(privateKey: Uint8Array): Uint8Array {\n if (privateKey.length !== ED25519_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ED25519_PRIVATE_KEY_SIZE} bytes`);\n }\n return ed25519.getPublicKey(privateKey);\n}\n\n/**\n * Sign a message using Ed25519.\n *\n * **Security Note**: The private key must be kept secret. The same private key\n * can safely sign multiple messages.\n *\n * @param privateKey - 32-byte Ed25519 private key\n * @param message - Message to sign (any length)\n * @returns 64-byte Ed25519 signature\n * @throws {Error} If private key is not 32 bytes\n */\nexport function ed25519Sign(privateKey: Uint8Array, message: Uint8Array): Uint8Array {\n if (privateKey.length !== ED25519_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ED25519_PRIVATE_KEY_SIZE} bytes`);\n }\n return ed25519.sign(message, privateKey);\n}\n\n/**\n * Verify an Ed25519 signature.\n *\n * @param publicKey - 32-byte Ed25519 public key\n * @param message - Original message that was signed\n * @param signature - 64-byte Ed25519 signature\n * @returns `true` if signature is valid, `false` if signature verification fails\n * @throws {Error} If public key is not 32 bytes or signature is not 64 bytes\n */\nexport function ed25519Verify(\n publicKey: Uint8Array,\n message: Uint8Array,\n signature: Uint8Array,\n): boolean {\n if (publicKey.length !== ED25519_PUBLIC_KEY_SIZE) {\n throw new Error(`Public key must be ${ED25519_PUBLIC_KEY_SIZE} bytes`);\n }\n if (signature.length !== ED25519_SIGNATURE_SIZE) {\n throw new Error(`Signature must be ${ED25519_SIGNATURE_SIZE} bytes`);\n }\n\n try {\n return ed25519.verify(signature, message, publicKey);\n } catch {\n return false;\n }\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/scrypt.rs\n\nimport { scrypt as nobleScrypt } from \"@noble/hashes/scrypt.js\";\n\n/**\n * Derive a key using Scrypt with recommended parameters.\n * Uses N=2^15 (32768), r=8, p=1 as recommended defaults.\n *\n * @param password - Password or passphrase\n * @param salt - Salt value\n * @param outputLen - Desired output length\n * @returns Derived key\n */\nexport function scrypt(password: Uint8Array, salt: Uint8Array, outputLen: number): Uint8Array {\n return scryptOpt(password, salt, outputLen, 15, 8, 1);\n}\n\n/**\n * Derive a key using Scrypt with custom parameters.\n *\n * @param password - Password or passphrase\n * @param salt - Salt value\n * @param outputLen - Desired output length\n * @param logN - Log2 of the CPU/memory cost parameter N (must be <64)\n * @param r - Block size parameter (must be >0)\n * @param p - Parallelization parameter (must be >0)\n * @returns Derived key\n */\nexport function scryptOpt(\n password: Uint8Array,\n salt: Uint8Array,\n outputLen: number,\n logN: number,\n r: number,\n p: number,\n): Uint8Array {\n if (logN >= 64) {\n throw new Error(\"logN must be <64\");\n }\n if (r === 0) {\n throw new Error(\"r must be >0\");\n }\n if (p === 0) {\n throw new Error(\"p must be >0\");\n }\n\n const N = 1 << logN; // 2^logN\n\n return nobleScrypt(password, salt, { N, r, p, dkLen: outputLen });\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/argon.rs\n\nimport { argon2id as nobleArgon2id } from \"@noble/hashes/argon2.js\";\n\n/**\n * Derive a key using Argon2id with default parameters.\n * This matches the Rust `argon2id` function signature.\n *\n * @param password - Password or passphrase\n * @param salt - Salt value (must be at least 8 bytes)\n * @param outputLen - Desired output length\n * @returns Derived key\n */\nexport function argon2id(password: Uint8Array, salt: Uint8Array, outputLen: number): Uint8Array {\n // Use default parameters matching Argon2::default() in Rust\n return argon2idHashOpt(password, salt, outputLen, 3, 65536, 4);\n}\n\n/**\n * Derive a key using Argon2id with custom parameters.\n *\n * @param password - Password or passphrase\n * @param salt - Salt value (must be at least 8 bytes)\n * @param outputLen - Desired output length\n * @param iterations - Number of iterations (t)\n * @param memory - Memory in KiB (m)\n * @param parallelism - Degree of parallelism (p)\n * @returns Derived key\n */\nexport function argon2idHashOpt(\n password: Uint8Array,\n salt: Uint8Array,\n outputLen: number,\n iterations: number,\n memory: number,\n parallelism: number,\n): Uint8Array {\n return nobleArgon2id(password, salt, {\n t: iterations,\n m: memory,\n p: parallelism,\n dkLen: outputLen,\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["nobleSha256","nobleSha512","x25519","SYMMETRIC_KEY_SIZE","secp256k1","secp256k1","SecureRandomNumberGenerator","schnorr","ed25519"],"sources":["../src/error.ts","../src/memzero.ts","../src/hash.ts","../src/symmetric-encryption.ts","../src/public-key-encryption.ts","../src/ecdsa-keys.ts","../src/ecdsa-signing.ts","../src/schnorr-signing.ts","../src/ed25519-signing.ts","../src/scrypt.ts","../src/argon.ts"],"sourcesContent":["/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/error.rs\n\n/**\n * AEAD-specific error for authentication failures\n */\nexport class AeadError extends Error {\n constructor(message = \"AEAD authentication failed\") {\n super(message);\n this.name = \"AeadError\";\n }\n}\n\n/**\n * Generic crypto error type\n */\nexport class CryptoError extends Error {\n override readonly cause?: Error | undefined;\n\n constructor(message: string, cause?: Error) {\n super(message);\n this.name = \"CryptoError\";\n this.cause = cause;\n }\n\n /**\n * Create a CryptoError for AEAD authentication failures.\n *\n * @param error - Optional underlying AeadError\n * @returns A CryptoError wrapping the AEAD error\n */\n static aead(error?: AeadError): CryptoError {\n return new CryptoError(\"AEAD error\", error ?? new AeadError());\n }\n\n /**\n * Create a CryptoError for invalid parameter values.\n *\n * @param message - Description of the invalid parameter\n * @returns A CryptoError describing the invalid parameter\n */\n static invalidParameter(message: string): CryptoError {\n return new CryptoError(`Invalid parameter: ${message}`);\n }\n}\n\n/**\n * Result type for crypto operations (using standard Error)\n */\nexport type CryptoResult<T> = T;\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/memzero.rs\n\n/**\n * Securely zero out a typed array.\n *\n * **IMPORTANT: This is a best-effort implementation.** Unlike the Rust reference\n * implementation which uses `std::ptr::write_volatile()` for guaranteed volatile\n * writes, JavaScript engines and JIT compilers can still potentially optimize\n * away these zeroing operations. The check at the end helps prevent optimization,\n * but it is not foolproof.\n *\n * For truly sensitive cryptographic operations, consider using the Web Crypto API's\n * `crypto.subtle` with non-extractable keys when possible, as it provides stronger\n * guarantees than what can be achieved with pure JavaScript.\n *\n * This function attempts to prevent the compiler from optimizing away\n * the zeroing operation by using a verification check after the zeroing loop.\n */\nexport function memzero(data: Uint8Array | Uint32Array): void {\n const len = data.length;\n for (let i = 0; i < len; i++) {\n data[i] = 0;\n }\n // Force a side effect to prevent optimization\n if (data.length > 0 && data[0] !== 0) {\n throw new Error(\"memzero failed\");\n }\n}\n\n/**\n * Securely zero out an array of Uint8Arrays.\n */\nexport function memzeroVecVecU8(arrays: Uint8Array[]): void {\n for (const arr of arrays) {\n memzero(arr);\n }\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/hash.rs\n\nimport { sha256 as nobleSha256, sha512 as nobleSha512 } from \"@noble/hashes/sha2.js\";\nimport { hmac } from \"@noble/hashes/hmac.js\";\nimport { pbkdf2 } from \"@noble/hashes/pbkdf2.js\";\nimport { hkdf } from \"@noble/hashes/hkdf.js\";\n\n// Constants\nexport const CRC32_SIZE = 4;\nexport const SHA256_SIZE = 32;\nexport const SHA512_SIZE = 64;\n\n// CRC-32 lookup table (IEEE polynomial 0xedb88320)\nconst CRC32_TABLE = new Uint32Array(256);\nfor (let i = 0; i < 256; i++) {\n let crc = i;\n for (let j = 0; j < 8; j++) {\n crc = (crc & 1) !== 0 ? (crc >>> 1) ^ 0xedb88320 : crc >>> 1;\n }\n CRC32_TABLE[i] = crc >>> 0;\n}\n\n/**\n * Calculate CRC-32 checksum\n */\nexport function crc32(data: Uint8Array): number {\n let crc = 0xffffffff;\n for (const byte of data) {\n crc = CRC32_TABLE[(crc ^ byte) & 0xff] ^ (crc >>> 8);\n }\n return (crc ^ 0xffffffff) >>> 0;\n}\n\n/**\n * Calculate CRC-32 checksum and return as a 4-byte big-endian array\n */\nexport function crc32Data(data: Uint8Array): Uint8Array {\n return crc32DataOpt(data, false);\n}\n\n/**\n * Calculate CRC-32 checksum and return as a 4-byte array\n * @param data - Input data\n * @param littleEndian - If true, returns little-endian; otherwise big-endian\n */\nexport function crc32DataOpt(data: Uint8Array, littleEndian: boolean): Uint8Array {\n const checksum = crc32(data);\n const result = new Uint8Array(4);\n const view = new DataView(result.buffer);\n view.setUint32(0, checksum, littleEndian);\n return result;\n}\n\n/**\n * Calculate SHA-256 hash\n */\nexport function sha256(data: Uint8Array): Uint8Array {\n return nobleSha256(data);\n}\n\n/**\n * Calculate double SHA-256 hash (SHA-256 of SHA-256)\n * This is the standard Bitcoin hashing function\n */\nexport function doubleSha256(message: Uint8Array): Uint8Array {\n return sha256(sha256(message));\n}\n\n/**\n * Calculate SHA-512 hash\n */\nexport function sha512(data: Uint8Array): Uint8Array {\n return nobleSha512(data);\n}\n\n/**\n * Calculate HMAC-SHA-256\n */\nexport function hmacSha256(key: Uint8Array, message: Uint8Array): Uint8Array {\n return hmac(nobleSha256, key, message);\n}\n\n/**\n * Calculate HMAC-SHA-512\n */\nexport function hmacSha512(key: Uint8Array, message: Uint8Array): Uint8Array {\n return hmac(nobleSha512, key, message);\n}\n\n/**\n * Derive a key using PBKDF2 with HMAC-SHA-256\n */\nexport function pbkdf2HmacSha256(\n password: Uint8Array,\n salt: Uint8Array,\n iterations: number,\n keyLen: number,\n): Uint8Array {\n return pbkdf2(nobleSha256, password, salt, { c: iterations, dkLen: keyLen });\n}\n\n/**\n * Derive a key using PBKDF2 with HMAC-SHA-512\n */\nexport function pbkdf2HmacSha512(\n password: Uint8Array,\n salt: Uint8Array,\n iterations: number,\n keyLen: number,\n): Uint8Array {\n return pbkdf2(nobleSha512, password, salt, { c: iterations, dkLen: keyLen });\n}\n\n/**\n * Derive a key using HKDF with HMAC-SHA-256\n */\nexport function hkdfHmacSha256(\n keyMaterial: Uint8Array,\n salt: Uint8Array,\n keyLen: number,\n): Uint8Array {\n return hkdf(nobleSha256, keyMaterial, salt, undefined, keyLen);\n}\n\n/**\n * Derive a key using HKDF with HMAC-SHA-512\n */\nexport function hkdfHmacSha512(\n keyMaterial: Uint8Array,\n salt: Uint8Array,\n keyLen: number,\n): Uint8Array {\n return hkdf(nobleSha512, keyMaterial, salt, undefined, keyLen);\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/symmetric_encryption.rs\n\nimport { chacha20poly1305 } from \"@noble/ciphers/chacha.js\";\nimport { CryptoError, AeadError } from \"./error.js\";\n\n// Constants\nexport const SYMMETRIC_KEY_SIZE = 32;\nexport const SYMMETRIC_NONCE_SIZE = 12;\nexport const SYMMETRIC_AUTH_SIZE = 16;\n\n/**\n * Encrypt data using ChaCha20-Poly1305 AEAD cipher.\n *\n * **Security Warning**: The nonce MUST be unique for every encryption operation\n * with the same key. Reusing a nonce completely breaks the security of the\n * encryption scheme and can reveal plaintext.\n *\n * @param plaintext - The data to encrypt\n * @param key - 32-byte encryption key\n * @param nonce - 12-byte nonce (MUST be unique per encryption with the same key)\n * @returns Tuple of [ciphertext, authTag] where authTag is 16 bytes\n * @throws {CryptoError} If key is not 32 bytes or nonce is not 12 bytes\n */\nexport function aeadChaCha20Poly1305Encrypt(\n plaintext: Uint8Array,\n key: Uint8Array,\n nonce: Uint8Array,\n): [Uint8Array, Uint8Array] {\n return aeadChaCha20Poly1305EncryptWithAad(plaintext, key, nonce, new Uint8Array(0));\n}\n\n/**\n * Encrypt data using ChaCha20-Poly1305 AEAD cipher with additional authenticated data.\n *\n * **Security Warning**: The nonce MUST be unique for every encryption operation\n * with the same key. Reusing a nonce completely breaks the security of the\n * encryption scheme and can reveal plaintext.\n *\n * @param plaintext - The data to encrypt\n * @param key - 32-byte encryption key\n * @param nonce - 12-byte nonce (MUST be unique per encryption with the same key)\n * @param aad - Additional authenticated data (not encrypted, but integrity-protected)\n * @returns Tuple of [ciphertext, authTag] where authTag is 16 bytes\n * @throws {CryptoError} If key is not 32 bytes or nonce is not 12 bytes\n */\nexport function aeadChaCha20Poly1305EncryptWithAad(\n plaintext: Uint8Array,\n key: Uint8Array,\n nonce: Uint8Array,\n aad: Uint8Array,\n): [Uint8Array, Uint8Array] {\n if (key.length !== SYMMETRIC_KEY_SIZE) {\n throw CryptoError.invalidParameter(`Key must be ${SYMMETRIC_KEY_SIZE} bytes`);\n }\n if (nonce.length !== SYMMETRIC_NONCE_SIZE) {\n throw CryptoError.invalidParameter(`Nonce must be ${SYMMETRIC_NONCE_SIZE} bytes`);\n }\n\n const cipher = chacha20poly1305(key, nonce, aad);\n const sealed = cipher.encrypt(plaintext);\n\n // The sealed output contains ciphertext + 16-byte auth tag\n const ciphertext = sealed.slice(0, sealed.length - SYMMETRIC_AUTH_SIZE);\n const authTag = sealed.slice(sealed.length - SYMMETRIC_AUTH_SIZE);\n\n return [ciphertext, authTag];\n}\n\n/**\n * Decrypt data using ChaCha20-Poly1305 AEAD cipher.\n *\n * @param ciphertext - The encrypted data\n * @param key - 32-byte encryption key (must match key used for encryption)\n * @param nonce - 12-byte nonce (must match nonce used for encryption)\n * @param authTag - 16-byte authentication tag from encryption\n * @returns Decrypted plaintext\n * @throws {CryptoError} If key/nonce/authTag sizes are invalid\n * @throws {CryptoError} If authentication fails (tampered data or wrong key/nonce)\n */\nexport function aeadChaCha20Poly1305Decrypt(\n ciphertext: Uint8Array,\n key: Uint8Array,\n nonce: Uint8Array,\n authTag: Uint8Array,\n): Uint8Array {\n return aeadChaCha20Poly1305DecryptWithAad(ciphertext, key, nonce, new Uint8Array(0), authTag);\n}\n\n/**\n * Decrypt data using ChaCha20-Poly1305 AEAD cipher with additional authenticated data.\n *\n * @param ciphertext - The encrypted data\n * @param key - 32-byte encryption key (must match key used for encryption)\n * @param nonce - 12-byte nonce (must match nonce used for encryption)\n * @param aad - Additional authenticated data (must exactly match AAD used for encryption)\n * @param authTag - 16-byte authentication tag from encryption\n * @returns Decrypted plaintext\n * @throws {CryptoError} If key/nonce/authTag sizes are invalid\n * @throws {CryptoError} If authentication fails (tampered data, wrong key/nonce, or AAD mismatch)\n */\nexport function aeadChaCha20Poly1305DecryptWithAad(\n ciphertext: Uint8Array,\n key: Uint8Array,\n nonce: Uint8Array,\n aad: Uint8Array,\n authTag: Uint8Array,\n): Uint8Array {\n if (key.length !== SYMMETRIC_KEY_SIZE) {\n throw CryptoError.invalidParameter(`Key must be ${SYMMETRIC_KEY_SIZE} bytes`);\n }\n if (nonce.length !== SYMMETRIC_NONCE_SIZE) {\n throw CryptoError.invalidParameter(`Nonce must be ${SYMMETRIC_NONCE_SIZE} bytes`);\n }\n if (authTag.length !== SYMMETRIC_AUTH_SIZE) {\n throw CryptoError.invalidParameter(`Auth tag must be ${SYMMETRIC_AUTH_SIZE} bytes`);\n }\n\n // Combine ciphertext and auth tag for decryption\n const sealed = new Uint8Array(ciphertext.length + authTag.length);\n sealed.set(ciphertext);\n sealed.set(authTag, ciphertext.length);\n\n try {\n const cipher = chacha20poly1305(key, nonce, aad);\n return cipher.decrypt(sealed);\n } catch (error) {\n // Preserve the original error for debugging while wrapping in our error type\n const aeadError = new AeadError(\n `Decryption failed: ${error instanceof Error ? error.message : \"authentication error\"}`,\n );\n throw CryptoError.aead(aeadError);\n }\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/public_key_encryption.rs\n\nimport { x25519 } from \"@noble/curves/ed25519.js\";\nimport type { RandomNumberGenerator } from \"@bcts/rand\";\nimport { hkdfHmacSha256 } from \"./hash.js\";\n\n// Constants\nexport const GENERIC_PRIVATE_KEY_SIZE = 32;\nexport const GENERIC_PUBLIC_KEY_SIZE = 32;\nexport const X25519_PRIVATE_KEY_SIZE = 32;\nexport const X25519_PUBLIC_KEY_SIZE = 32;\n\n/**\n * Derive an X25519 agreement private key from key material.\n * Uses HKDF with \"agreement\" as domain separation salt.\n */\nexport function deriveAgreementPrivateKey(keyMaterial: Uint8Array): Uint8Array {\n const salt = new TextEncoder().encode(\"agreement\");\n return hkdfHmacSha256(keyMaterial, salt, X25519_PRIVATE_KEY_SIZE);\n}\n\n/**\n * Derive a signing private key from key material.\n * Uses HKDF with \"signing\" as domain separation salt.\n */\nexport function deriveSigningPrivateKey(keyMaterial: Uint8Array): Uint8Array {\n const salt = new TextEncoder().encode(\"signing\");\n return hkdfHmacSha256(keyMaterial, salt, 32);\n}\n\n/**\n * Generate a new random X25519 private key.\n */\nexport function x25519NewPrivateKeyUsing(rng: RandomNumberGenerator): Uint8Array {\n return rng.randomData(X25519_PRIVATE_KEY_SIZE);\n}\n\n/**\n * Derive an X25519 public key from a private key.\n */\nexport function x25519PublicKeyFromPrivateKey(privateKey: Uint8Array): Uint8Array {\n if (privateKey.length !== X25519_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${X25519_PRIVATE_KEY_SIZE} bytes`);\n }\n return x25519.getPublicKey(privateKey);\n}\n\n// Symmetric key size for the derived shared key\nconst SYMMETRIC_KEY_SIZE = 32;\n\n/**\n * Compute a shared symmetric key using X25519 key agreement (ECDH).\n *\n * This function performs X25519 Diffie-Hellman key agreement and then\n * derives a symmetric key using HKDF-SHA256 with \"agreement\" as the salt.\n * This matches the Rust bc-crypto implementation for cross-platform compatibility.\n *\n * @param x25519Private - 32-byte X25519 private key\n * @param x25519Public - 32-byte X25519 public key from the other party\n * @returns 32-byte derived symmetric key\n * @throws {Error} If private key is not 32 bytes or public key is not 32 bytes\n */\nexport function x25519SharedKey(x25519Private: Uint8Array, x25519Public: Uint8Array): Uint8Array {\n if (x25519Private.length !== X25519_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${X25519_PRIVATE_KEY_SIZE} bytes`);\n }\n if (x25519Public.length !== X25519_PUBLIC_KEY_SIZE) {\n throw new Error(`Public key must be ${X25519_PUBLIC_KEY_SIZE} bytes`);\n }\n // Perform raw X25519 Diffie-Hellman\n const rawSharedSecret = x25519.getSharedSecret(x25519Private, x25519Public);\n // Derive symmetric key using HKDF with \"agreement\" salt (matches Rust implementation)\n const salt = new TextEncoder().encode(\"agreement\");\n return hkdfHmacSha256(rawSharedSecret, salt, SYMMETRIC_KEY_SIZE);\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/ecdsa_keys.rs\n\nimport { secp256k1 } from \"@noble/curves/secp256k1.js\";\nimport type { RandomNumberGenerator } from \"@bcts/rand\";\nimport { hkdfHmacSha256 } from \"./hash.js\";\n\n// Constants\nexport const ECDSA_PRIVATE_KEY_SIZE = 32;\nexport const ECDSA_PUBLIC_KEY_SIZE = 33; // Compressed\nexport const ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE = 65;\nexport const ECDSA_MESSAGE_HASH_SIZE = 32;\nexport const ECDSA_SIGNATURE_SIZE = 64;\nexport const SCHNORR_PUBLIC_KEY_SIZE = 32; // x-only\n\n/**\n * Generate a new random ECDSA private key using secp256k1.\n *\n * Note: Unlike some implementations, this directly returns the random bytes\n * without validation. The secp256k1 library will handle any edge cases when\n * the key is used.\n */\nexport function ecdsaNewPrivateKeyUsing(rng: RandomNumberGenerator): Uint8Array {\n return rng.randomData(ECDSA_PRIVATE_KEY_SIZE);\n}\n\n/**\n * Derive a compressed ECDSA public key from a private key.\n */\nexport function ecdsaPublicKeyFromPrivateKey(privateKey: Uint8Array): Uint8Array {\n if (privateKey.length !== ECDSA_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);\n }\n return secp256k1.getPublicKey(privateKey, true); // true = compressed\n}\n\n/**\n * Decompress a compressed public key to uncompressed format.\n */\nexport function ecdsaDecompressPublicKey(compressed: Uint8Array): Uint8Array {\n if (compressed.length !== ECDSA_PUBLIC_KEY_SIZE) {\n throw new Error(`Compressed public key must be ${ECDSA_PUBLIC_KEY_SIZE} bytes`);\n }\n const point = secp256k1.Point.fromBytes(compressed);\n return point.toBytes(false); // false = uncompressed\n}\n\n/**\n * Compress an uncompressed public key.\n */\nexport function ecdsaCompressPublicKey(uncompressed: Uint8Array): Uint8Array {\n if (uncompressed.length !== ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE) {\n throw new Error(`Uncompressed public key must be ${ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE} bytes`);\n }\n const point = secp256k1.Point.fromBytes(uncompressed);\n return point.toBytes(true); // true = compressed\n}\n\n/**\n * Derive an ECDSA private key from key material using HKDF.\n *\n * Note: This directly returns the HKDF output without validation,\n * matching the Rust reference implementation behavior.\n */\nexport function ecdsaDerivePrivateKey(keyMaterial: Uint8Array): Uint8Array {\n const salt = new TextEncoder().encode(\"signing\");\n return hkdfHmacSha256(keyMaterial, salt, ECDSA_PRIVATE_KEY_SIZE);\n}\n\n/**\n * Extract the x-only (Schnorr) public key from a private key.\n * This is used for BIP-340 Schnorr signatures.\n */\nexport function schnorrPublicKeyFromPrivateKey(privateKey: Uint8Array): Uint8Array {\n if (privateKey.length !== ECDSA_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);\n }\n // Get the full public key and extract just the x-coordinate\n const fullPubKey = secp256k1.getPublicKey(privateKey, false); // uncompressed\n // Skip the 0x04 prefix and take only x-coordinate (first 32 bytes after prefix)\n return fullPubKey.slice(1, 33);\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/ecdsa_signing.rs\n\nimport { secp256k1 } from \"@noble/curves/secp256k1.js\";\nimport { doubleSha256 } from \"./hash.js\";\nimport {\n ECDSA_PRIVATE_KEY_SIZE,\n ECDSA_PUBLIC_KEY_SIZE,\n ECDSA_SIGNATURE_SIZE,\n} from \"./ecdsa-keys.js\";\n\n/**\n * Sign a message using ECDSA with secp256k1.\n *\n * The message is hashed with double SHA-256 before signing (Bitcoin standard).\n *\n * **Security Note**: The private key must be kept secret. ECDSA requires\n * cryptographically secure random nonces internally; this is handled by\n * the underlying library using RFC 6979 deterministic nonces.\n *\n * @param privateKey - 32-byte secp256k1 private key\n * @param message - Message to sign (any length, will be double-SHA256 hashed)\n * @returns 64-byte compact signature (r || s format)\n * @throws {Error} If private key is not 32 bytes\n */\nexport function ecdsaSign(privateKey: Uint8Array, message: Uint8Array): Uint8Array {\n if (privateKey.length !== ECDSA_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);\n }\n\n const messageHash = doubleSha256(message);\n // prehash: false because we already hashed the message with doubleSha256\n return secp256k1.sign(messageHash, privateKey, { prehash: false });\n}\n\n/**\n * Verify an ECDSA signature with secp256k1.\n *\n * The message is hashed with double SHA-256 before verification (Bitcoin standard).\n *\n * @param publicKey - 33-byte compressed secp256k1 public key\n * @param signature - 64-byte compact signature (r || s format)\n * @param message - Original message that was signed\n * @returns `true` if signature is valid, `false` if signature verification fails\n * @throws {Error} If public key is not 33 bytes or signature is not 64 bytes\n */\nexport function ecdsaVerify(\n publicKey: Uint8Array,\n signature: Uint8Array,\n message: Uint8Array,\n): boolean {\n if (publicKey.length !== ECDSA_PUBLIC_KEY_SIZE) {\n throw new Error(`Public key must be ${ECDSA_PUBLIC_KEY_SIZE} bytes`);\n }\n if (signature.length !== ECDSA_SIGNATURE_SIZE) {\n throw new Error(`Signature must be ${ECDSA_SIGNATURE_SIZE} bytes`);\n }\n\n try {\n const messageHash = doubleSha256(message);\n // prehash: false because we already hashed the message with doubleSha256\n return secp256k1.verify(signature, messageHash, publicKey, { prehash: false });\n } catch {\n return false;\n }\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/schnorr_signing.rs\n\nimport { schnorr } from \"@noble/curves/secp256k1.js\";\nimport type { RandomNumberGenerator } from \"@bcts/rand\";\nimport { SecureRandomNumberGenerator } from \"@bcts/rand\";\nimport { ECDSA_PRIVATE_KEY_SIZE, SCHNORR_PUBLIC_KEY_SIZE } from \"./ecdsa-keys.js\";\n\n// Constants\nexport const SCHNORR_SIGNATURE_SIZE = 64;\n\n/**\n * Sign a message using Schnorr signature (BIP-340).\n * Uses secure random auxiliary randomness.\n *\n * @param ecdsaPrivateKey - 32-byte private key\n * @param message - Message to sign (not pre-hashed, per BIP-340)\n * @returns 64-byte Schnorr signature\n */\nexport function schnorrSign(ecdsaPrivateKey: Uint8Array, message: Uint8Array): Uint8Array {\n const rng = new SecureRandomNumberGenerator();\n return schnorrSignUsing(ecdsaPrivateKey, message, rng);\n}\n\n/**\n * Sign a message using Schnorr signature with a custom RNG.\n *\n * @param ecdsaPrivateKey - 32-byte private key\n * @param message - Message to sign\n * @param rng - Random number generator for auxiliary randomness\n * @returns 64-byte Schnorr signature\n */\nexport function schnorrSignUsing(\n ecdsaPrivateKey: Uint8Array,\n message: Uint8Array,\n rng: RandomNumberGenerator,\n): Uint8Array {\n const auxRand = rng.randomData(32);\n return schnorrSignWithAuxRand(ecdsaPrivateKey, message, auxRand);\n}\n\n/**\n * Sign a message using Schnorr signature with specific auxiliary randomness.\n * This is useful for deterministic signing in tests.\n *\n * @param ecdsaPrivateKey - 32-byte private key\n * @param message - Message to sign\n * @param auxRand - 32-byte auxiliary randomness (per BIP-340)\n * @returns 64-byte Schnorr signature\n */\nexport function schnorrSignWithAuxRand(\n ecdsaPrivateKey: Uint8Array,\n message: Uint8Array,\n auxRand: Uint8Array,\n): Uint8Array {\n if (ecdsaPrivateKey.length !== ECDSA_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);\n }\n if (auxRand.length !== 32) {\n throw new Error(\"Auxiliary randomness must be 32 bytes\");\n }\n\n return schnorr.sign(message, ecdsaPrivateKey, auxRand);\n}\n\n/**\n * Verify a Schnorr signature (BIP-340).\n *\n * @param schnorrPublicKey - 32-byte x-only public key\n * @param signature - 64-byte Schnorr signature\n * @param message - Original message\n * @returns true if signature is valid\n */\nexport function schnorrVerify(\n schnorrPublicKey: Uint8Array,\n signature: Uint8Array,\n message: Uint8Array,\n): boolean {\n if (schnorrPublicKey.length !== SCHNORR_PUBLIC_KEY_SIZE) {\n throw new Error(`Public key must be ${SCHNORR_PUBLIC_KEY_SIZE} bytes`);\n }\n if (signature.length !== SCHNORR_SIGNATURE_SIZE) {\n throw new Error(`Signature must be ${SCHNORR_SIGNATURE_SIZE} bytes`);\n }\n\n try {\n return schnorr.verify(signature, message, schnorrPublicKey);\n } catch {\n return false;\n }\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/ed25519_signing.rs\n\nimport { ed25519 } from \"@noble/curves/ed25519.js\";\nimport type { RandomNumberGenerator } from \"@bcts/rand\";\n\n// Constants\nexport const ED25519_PUBLIC_KEY_SIZE = 32;\nexport const ED25519_PRIVATE_KEY_SIZE = 32;\nexport const ED25519_SIGNATURE_SIZE = 64;\n\n/**\n * Generate a new random Ed25519 private key.\n */\nexport function ed25519NewPrivateKeyUsing(rng: RandomNumberGenerator): Uint8Array {\n return rng.randomData(ED25519_PRIVATE_KEY_SIZE);\n}\n\n/**\n * Derive an Ed25519 public key from a private key.\n */\nexport function ed25519PublicKeyFromPrivateKey(privateKey: Uint8Array): Uint8Array {\n if (privateKey.length !== ED25519_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ED25519_PRIVATE_KEY_SIZE} bytes`);\n }\n return ed25519.getPublicKey(privateKey);\n}\n\n/**\n * Sign a message using Ed25519.\n *\n * **Security Note**: The private key must be kept secret. The same private key\n * can safely sign multiple messages.\n *\n * @param privateKey - 32-byte Ed25519 private key\n * @param message - Message to sign (any length)\n * @returns 64-byte Ed25519 signature\n * @throws {Error} If private key is not 32 bytes\n */\nexport function ed25519Sign(privateKey: Uint8Array, message: Uint8Array): Uint8Array {\n if (privateKey.length !== ED25519_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ED25519_PRIVATE_KEY_SIZE} bytes`);\n }\n return ed25519.sign(message, privateKey);\n}\n\n/**\n * Verify an Ed25519 signature.\n *\n * @param publicKey - 32-byte Ed25519 public key\n * @param message - Original message that was signed\n * @param signature - 64-byte Ed25519 signature\n * @returns `true` if signature is valid, `false` if signature verification fails\n * @throws {Error} If public key is not 32 bytes or signature is not 64 bytes\n */\nexport function ed25519Verify(\n publicKey: Uint8Array,\n message: Uint8Array,\n signature: Uint8Array,\n): boolean {\n if (publicKey.length !== ED25519_PUBLIC_KEY_SIZE) {\n throw new Error(`Public key must be ${ED25519_PUBLIC_KEY_SIZE} bytes`);\n }\n if (signature.length !== ED25519_SIGNATURE_SIZE) {\n throw new Error(`Signature must be ${ED25519_SIGNATURE_SIZE} bytes`);\n }\n\n try {\n return ed25519.verify(signature, message, publicKey);\n } catch {\n return false;\n }\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/scrypt.rs\n\nimport { scrypt as nobleScrypt } from \"@noble/hashes/scrypt.js\";\n\n/**\n * Derive a key using Scrypt with recommended parameters.\n * Uses N=2^15 (32768), r=8, p=1 as recommended defaults.\n *\n * @param password - Password or passphrase\n * @param salt - Salt value\n * @param outputLen - Desired output length\n * @returns Derived key\n */\nexport function scrypt(password: Uint8Array, salt: Uint8Array, outputLen: number): Uint8Array {\n return scryptOpt(password, salt, outputLen, 15, 8, 1);\n}\n\n/**\n * Derive a key using Scrypt with custom parameters.\n *\n * @param password - Password or passphrase\n * @param salt - Salt value\n * @param outputLen - Desired output length\n * @param logN - Log2 of the CPU/memory cost parameter N (must be <64)\n * @param r - Block size parameter (must be >0)\n * @param p - Parallelization parameter (must be >0)\n * @returns Derived key\n */\nexport function scryptOpt(\n password: Uint8Array,\n salt: Uint8Array,\n outputLen: number,\n logN: number,\n r: number,\n p: number,\n): Uint8Array {\n if (logN >= 64) {\n throw new Error(\"logN must be <64\");\n }\n if (r === 0) {\n throw new Error(\"r must be >0\");\n }\n if (p === 0) {\n throw new Error(\"p must be >0\");\n }\n\n const N = 1 << logN; // 2^logN\n\n return nobleScrypt(password, salt, { N, r, p, dkLen: outputLen });\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/argon.rs\n\nimport { argon2id as nobleArgon2id } from \"@noble/hashes/argon2.js\";\n\n/**\n * Derive a key using Argon2id with default parameters.\n * This matches the Rust `argon2id` function signature.\n *\n * @param password - Password or passphrase\n * @param salt - Salt value (must be at least 8 bytes)\n * @param outputLen - Desired output length\n * @returns Derived key\n */\nexport function argon2id(password: Uint8Array, salt: Uint8Array, outputLen: number): Uint8Array {\n // Use default parameters matching Argon2::default() in Rust\n return argon2idHashOpt(password, salt, outputLen, 3, 65536, 4);\n}\n\n/**\n * Derive a key using Argon2id with custom parameters.\n *\n * @param password - Password or passphrase\n * @param salt - Salt value (must be at least 8 bytes)\n * @param outputLen - Desired output length\n * @param iterations - Number of iterations (t)\n * @param memory - Memory in KiB (m)\n * @param parallelism - Degree of parallelism (p)\n * @returns Derived key\n */\nexport function argon2idHashOpt(\n password: Uint8Array,\n salt: Uint8Array,\n outputLen: number,\n iterations: number,\n memory: number,\n parallelism: number,\n): Uint8Array {\n return nobleArgon2id(password, salt, {\n t: iterations,\n m: memory,\n p: parallelism,\n dkLen: outputLen,\n });\n}\n"],"mappings":"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"}
@@ -226,10 +226,10 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
226
226
  * @throws {CryptoError} If key is not 32 bytes or nonce is not 12 bytes
227
227
  */
228
228
  function aeadChaCha20Poly1305EncryptWithAad(plaintext, key, nonce, aad) {
229
- if (key.length !== SYMMETRIC_KEY_SIZE) throw CryptoError.invalidParameter(`Key must be ${SYMMETRIC_KEY_SIZE} bytes`);
230
- if (nonce.length !== SYMMETRIC_NONCE_SIZE) throw CryptoError.invalidParameter(`Nonce must be ${SYMMETRIC_NONCE_SIZE} bytes`);
229
+ if (key.length !== 32) throw CryptoError.invalidParameter(`Key must be ${32} bytes`);
230
+ if (nonce.length !== 12) throw CryptoError.invalidParameter(`Nonce must be ${12} bytes`);
231
231
  const sealed = (0, _noble_ciphers_chacha_js.chacha20poly1305)(key, nonce, aad).encrypt(plaintext);
232
- return [sealed.slice(0, sealed.length - SYMMETRIC_AUTH_SIZE), sealed.slice(sealed.length - SYMMETRIC_AUTH_SIZE)];
232
+ return [sealed.slice(0, sealed.length - 16), sealed.slice(sealed.length - 16)];
233
233
  }
234
234
  /**
235
235
  * Decrypt data using ChaCha20-Poly1305 AEAD cipher.
@@ -258,9 +258,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
258
258
  * @throws {CryptoError} If authentication fails (tampered data, wrong key/nonce, or AAD mismatch)
259
259
  */
260
260
  function aeadChaCha20Poly1305DecryptWithAad(ciphertext, key, nonce, aad, authTag) {
261
- if (key.length !== SYMMETRIC_KEY_SIZE) throw CryptoError.invalidParameter(`Key must be ${SYMMETRIC_KEY_SIZE} bytes`);
262
- if (nonce.length !== SYMMETRIC_NONCE_SIZE) throw CryptoError.invalidParameter(`Nonce must be ${SYMMETRIC_NONCE_SIZE} bytes`);
263
- if (authTag.length !== SYMMETRIC_AUTH_SIZE) throw CryptoError.invalidParameter(`Auth tag must be ${SYMMETRIC_AUTH_SIZE} bytes`);
261
+ if (key.length !== 32) throw CryptoError.invalidParameter(`Key must be ${32} bytes`);
262
+ if (nonce.length !== 12) throw CryptoError.invalidParameter(`Nonce must be ${12} bytes`);
263
+ if (authTag.length !== 16) throw CryptoError.invalidParameter(`Auth tag must be ${16} bytes`);
264
264
  const sealed = new Uint8Array(ciphertext.length + authTag.length);
265
265
  sealed.set(ciphertext);
266
266
  sealed.set(authTag, ciphertext.length);
@@ -288,7 +288,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
288
288
  * Uses HKDF with "agreement" as domain separation salt.
289
289
  */
290
290
  function deriveAgreementPrivateKey(keyMaterial) {
291
- return hkdfHmacSha256(keyMaterial, new TextEncoder().encode("agreement"), X25519_PRIVATE_KEY_SIZE);
291
+ return hkdfHmacSha256(keyMaterial, new TextEncoder().encode("agreement"), 32);
292
292
  }
293
293
  /**
294
294
  * Derive a signing private key from key material.
@@ -301,13 +301,13 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
301
301
  * Generate a new random X25519 private key.
302
302
  */
303
303
  function x25519NewPrivateKeyUsing(rng) {
304
- return rng.randomData(X25519_PRIVATE_KEY_SIZE);
304
+ return rng.randomData(32);
305
305
  }
306
306
  /**
307
307
  * Derive an X25519 public key from a private key.
308
308
  */
309
309
  function x25519PublicKeyFromPrivateKey(privateKey) {
310
- if (privateKey.length !== X25519_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${X25519_PRIVATE_KEY_SIZE} bytes`);
310
+ if (privateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
311
311
  return _noble_curves_ed25519_js.x25519.getPublicKey(privateKey);
312
312
  }
313
313
  const SYMMETRIC_KEY_SIZE$1 = 32;
@@ -324,8 +324,8 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
324
324
  * @throws {Error} If private key is not 32 bytes or public key is not 32 bytes
325
325
  */
326
326
  function x25519SharedKey(x25519Private, x25519Public) {
327
- if (x25519Private.length !== X25519_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${X25519_PRIVATE_KEY_SIZE} bytes`);
328
- if (x25519Public.length !== X25519_PUBLIC_KEY_SIZE) throw new Error(`Public key must be ${X25519_PUBLIC_KEY_SIZE} bytes`);
327
+ if (x25519Private.length !== 32) throw new Error(`Private key must be ${32} bytes`);
328
+ if (x25519Public.length !== 32) throw new Error(`Public key must be ${32} bytes`);
329
329
  return hkdfHmacSha256(_noble_curves_ed25519_js.x25519.getSharedSecret(x25519Private, x25519Public), new TextEncoder().encode("agreement"), SYMMETRIC_KEY_SIZE$1);
330
330
  }
331
331
 
@@ -350,27 +350,27 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
350
350
  * the key is used.
351
351
  */
352
352
  function ecdsaNewPrivateKeyUsing(rng) {
353
- return rng.randomData(ECDSA_PRIVATE_KEY_SIZE);
353
+ return rng.randomData(32);
354
354
  }
355
355
  /**
356
356
  * Derive a compressed ECDSA public key from a private key.
357
357
  */
358
358
  function ecdsaPublicKeyFromPrivateKey(privateKey) {
359
- if (privateKey.length !== ECDSA_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);
359
+ if (privateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
360
360
  return _noble_curves_secp256k1_js.secp256k1.getPublicKey(privateKey, true);
361
361
  }
362
362
  /**
363
363
  * Decompress a compressed public key to uncompressed format.
364
364
  */
365
365
  function ecdsaDecompressPublicKey(compressed) {
366
- if (compressed.length !== ECDSA_PUBLIC_KEY_SIZE) throw new Error(`Compressed public key must be ${ECDSA_PUBLIC_KEY_SIZE} bytes`);
366
+ if (compressed.length !== 33) throw new Error(`Compressed public key must be ${33} bytes`);
367
367
  return _noble_curves_secp256k1_js.secp256k1.Point.fromBytes(compressed).toBytes(false);
368
368
  }
369
369
  /**
370
370
  * Compress an uncompressed public key.
371
371
  */
372
372
  function ecdsaCompressPublicKey(uncompressed) {
373
- if (uncompressed.length !== ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE) throw new Error(`Uncompressed public key must be ${ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE} bytes`);
373
+ if (uncompressed.length !== 65) throw new Error(`Uncompressed public key must be ${65} bytes`);
374
374
  return _noble_curves_secp256k1_js.secp256k1.Point.fromBytes(uncompressed).toBytes(true);
375
375
  }
376
376
  /**
@@ -380,14 +380,14 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
380
380
  * matching the Rust reference implementation behavior.
381
381
  */
382
382
  function ecdsaDerivePrivateKey(keyMaterial) {
383
- return hkdfHmacSha256(keyMaterial, new TextEncoder().encode("signing"), ECDSA_PRIVATE_KEY_SIZE);
383
+ return hkdfHmacSha256(keyMaterial, new TextEncoder().encode("signing"), 32);
384
384
  }
385
385
  /**
386
386
  * Extract the x-only (Schnorr) public key from a private key.
387
387
  * This is used for BIP-340 Schnorr signatures.
388
388
  */
389
389
  function schnorrPublicKeyFromPrivateKey(privateKey) {
390
- if (privateKey.length !== ECDSA_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);
390
+ if (privateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
391
391
  return _noble_curves_secp256k1_js.secp256k1.getPublicKey(privateKey, false).slice(1, 33);
392
392
  }
393
393
 
@@ -413,7 +413,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
413
413
  * @throws {Error} If private key is not 32 bytes
414
414
  */
415
415
  function ecdsaSign(privateKey, message) {
416
- if (privateKey.length !== ECDSA_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);
416
+ if (privateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
417
417
  const messageHash = doubleSha256(message);
418
418
  return _noble_curves_secp256k1_js.secp256k1.sign(messageHash, privateKey, { prehash: false });
419
419
  }
@@ -429,8 +429,8 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
429
429
  * @throws {Error} If public key is not 33 bytes or signature is not 64 bytes
430
430
  */
431
431
  function ecdsaVerify(publicKey, signature, message) {
432
- if (publicKey.length !== ECDSA_PUBLIC_KEY_SIZE) throw new Error(`Public key must be ${ECDSA_PUBLIC_KEY_SIZE} bytes`);
433
- if (signature.length !== ECDSA_SIGNATURE_SIZE) throw new Error(`Signature must be ${ECDSA_SIGNATURE_SIZE} bytes`);
432
+ if (publicKey.length !== 33) throw new Error(`Public key must be ${33} bytes`);
433
+ if (signature.length !== 64) throw new Error(`Signature must be ${64} bytes`);
434
434
  try {
435
435
  const messageHash = doubleSha256(message);
436
436
  return _noble_curves_secp256k1_js.secp256k1.verify(signature, messageHash, publicKey, { prehash: false });
@@ -479,7 +479,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
479
479
  * @returns 64-byte Schnorr signature
480
480
  */
481
481
  function schnorrSignWithAuxRand(ecdsaPrivateKey, message, auxRand) {
482
- if (ecdsaPrivateKey.length !== ECDSA_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);
482
+ if (ecdsaPrivateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
483
483
  if (auxRand.length !== 32) throw new Error("Auxiliary randomness must be 32 bytes");
484
484
  return _noble_curves_secp256k1_js.schnorr.sign(message, ecdsaPrivateKey, auxRand);
485
485
  }
@@ -492,8 +492,8 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
492
492
  * @returns true if signature is valid
493
493
  */
494
494
  function schnorrVerify(schnorrPublicKey, signature, message) {
495
- if (schnorrPublicKey.length !== SCHNORR_PUBLIC_KEY_SIZE) throw new Error(`Public key must be ${SCHNORR_PUBLIC_KEY_SIZE} bytes`);
496
- if (signature.length !== SCHNORR_SIGNATURE_SIZE) throw new Error(`Signature must be ${SCHNORR_SIGNATURE_SIZE} bytes`);
495
+ if (schnorrPublicKey.length !== 32) throw new Error(`Public key must be ${32} bytes`);
496
+ if (signature.length !== 64) throw new Error(`Signature must be ${64} bytes`);
497
497
  try {
498
498
  return _noble_curves_secp256k1_js.schnorr.verify(signature, message, schnorrPublicKey);
499
499
  } catch {
@@ -515,13 +515,13 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
515
515
  * Generate a new random Ed25519 private key.
516
516
  */
517
517
  function ed25519NewPrivateKeyUsing(rng) {
518
- return rng.randomData(ED25519_PRIVATE_KEY_SIZE);
518
+ return rng.randomData(32);
519
519
  }
520
520
  /**
521
521
  * Derive an Ed25519 public key from a private key.
522
522
  */
523
523
  function ed25519PublicKeyFromPrivateKey(privateKey) {
524
- if (privateKey.length !== ED25519_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${ED25519_PRIVATE_KEY_SIZE} bytes`);
524
+ if (privateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
525
525
  return _noble_curves_ed25519_js.ed25519.getPublicKey(privateKey);
526
526
  }
527
527
  /**
@@ -536,7 +536,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
536
536
  * @throws {Error} If private key is not 32 bytes
537
537
  */
538
538
  function ed25519Sign(privateKey, message) {
539
- if (privateKey.length !== ED25519_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${ED25519_PRIVATE_KEY_SIZE} bytes`);
539
+ if (privateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
540
540
  return _noble_curves_ed25519_js.ed25519.sign(message, privateKey);
541
541
  }
542
542
  /**
@@ -549,8 +549,8 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
549
549
  * @throws {Error} If public key is not 32 bytes or signature is not 64 bytes
550
550
  */
551
551
  function ed25519Verify(publicKey, message, signature) {
552
- if (publicKey.length !== ED25519_PUBLIC_KEY_SIZE) throw new Error(`Public key must be ${ED25519_PUBLIC_KEY_SIZE} bytes`);
553
- if (signature.length !== ED25519_SIGNATURE_SIZE) throw new Error(`Signature must be ${ED25519_SIGNATURE_SIZE} bytes`);
552
+ if (publicKey.length !== 32) throw new Error(`Public key must be ${32} bytes`);
553
+ if (signature.length !== 64) throw new Error(`Signature must be ${64} bytes`);
554
554
  try {
555
555
  return _noble_curves_ed25519_js.ed25519.verify(signature, message, publicKey);
556
556
  } catch {
@@ -1 +1 @@
1
- {"version":3,"file":"index.iife.js","names":["nobleSha256","nobleSha512","x25519","SYMMETRIC_KEY_SIZE","secp256k1","secp256k1","SecureRandomNumberGenerator","schnorr","ed25519"],"sources":["../src/error.ts","../src/memzero.ts","../src/hash.ts","../src/symmetric-encryption.ts","../src/public-key-encryption.ts","../src/ecdsa-keys.ts","../src/ecdsa-signing.ts","../src/schnorr-signing.ts","../src/ed25519-signing.ts","../src/scrypt.ts","../src/argon.ts"],"sourcesContent":["/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/error.rs\n\n/**\n * AEAD-specific error for authentication failures\n */\nexport class AeadError extends Error {\n constructor(message = \"AEAD authentication failed\") {\n super(message);\n this.name = \"AeadError\";\n }\n}\n\n/**\n * Generic crypto error type\n */\nexport class CryptoError extends Error {\n override readonly cause?: Error | undefined;\n\n constructor(message: string, cause?: Error) {\n super(message);\n this.name = \"CryptoError\";\n this.cause = cause;\n }\n\n /**\n * Create a CryptoError for AEAD authentication failures.\n *\n * @param error - Optional underlying AeadError\n * @returns A CryptoError wrapping the AEAD error\n */\n static aead(error?: AeadError): CryptoError {\n return new CryptoError(\"AEAD error\", error ?? new AeadError());\n }\n\n /**\n * Create a CryptoError for invalid parameter values.\n *\n * @param message - Description of the invalid parameter\n * @returns A CryptoError describing the invalid parameter\n */\n static invalidParameter(message: string): CryptoError {\n return new CryptoError(`Invalid parameter: ${message}`);\n }\n}\n\n/**\n * Result type for crypto operations (using standard Error)\n */\nexport type CryptoResult<T> = T;\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/memzero.rs\n\n/**\n * Securely zero out a typed array.\n *\n * **IMPORTANT: This is a best-effort implementation.** Unlike the Rust reference\n * implementation which uses `std::ptr::write_volatile()` for guaranteed volatile\n * writes, JavaScript engines and JIT compilers can still potentially optimize\n * away these zeroing operations. The check at the end helps prevent optimization,\n * but it is not foolproof.\n *\n * For truly sensitive cryptographic operations, consider using the Web Crypto API's\n * `crypto.subtle` with non-extractable keys when possible, as it provides stronger\n * guarantees than what can be achieved with pure JavaScript.\n *\n * This function attempts to prevent the compiler from optimizing away\n * the zeroing operation by using a verification check after the zeroing loop.\n */\nexport function memzero(data: Uint8Array | Uint32Array): void {\n const len = data.length;\n for (let i = 0; i < len; i++) {\n data[i] = 0;\n }\n // Force a side effect to prevent optimization\n if (data.length > 0 && data[0] !== 0) {\n throw new Error(\"memzero failed\");\n }\n}\n\n/**\n * Securely zero out an array of Uint8Arrays.\n */\nexport function memzeroVecVecU8(arrays: Uint8Array[]): void {\n for (const arr of arrays) {\n memzero(arr);\n }\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/hash.rs\n\nimport { sha256 as nobleSha256, sha512 as nobleSha512 } from \"@noble/hashes/sha2.js\";\nimport { hmac } from \"@noble/hashes/hmac.js\";\nimport { pbkdf2 } from \"@noble/hashes/pbkdf2.js\";\nimport { hkdf } from \"@noble/hashes/hkdf.js\";\n\n// Constants\nexport const CRC32_SIZE = 4;\nexport const SHA256_SIZE = 32;\nexport const SHA512_SIZE = 64;\n\n// CRC-32 lookup table (IEEE polynomial 0xedb88320)\nconst CRC32_TABLE = new Uint32Array(256);\nfor (let i = 0; i < 256; i++) {\n let crc = i;\n for (let j = 0; j < 8; j++) {\n crc = (crc & 1) !== 0 ? (crc >>> 1) ^ 0xedb88320 : crc >>> 1;\n }\n CRC32_TABLE[i] = crc >>> 0;\n}\n\n/**\n * Calculate CRC-32 checksum\n */\nexport function crc32(data: Uint8Array): number {\n let crc = 0xffffffff;\n for (const byte of data) {\n crc = CRC32_TABLE[(crc ^ byte) & 0xff] ^ (crc >>> 8);\n }\n return (crc ^ 0xffffffff) >>> 0;\n}\n\n/**\n * Calculate CRC-32 checksum and return as a 4-byte big-endian array\n */\nexport function crc32Data(data: Uint8Array): Uint8Array {\n return crc32DataOpt(data, false);\n}\n\n/**\n * Calculate CRC-32 checksum and return as a 4-byte array\n * @param data - Input data\n * @param littleEndian - If true, returns little-endian; otherwise big-endian\n */\nexport function crc32DataOpt(data: Uint8Array, littleEndian: boolean): Uint8Array {\n const checksum = crc32(data);\n const result = new Uint8Array(4);\n const view = new DataView(result.buffer);\n view.setUint32(0, checksum, littleEndian);\n return result;\n}\n\n/**\n * Calculate SHA-256 hash\n */\nexport function sha256(data: Uint8Array): Uint8Array {\n return nobleSha256(data);\n}\n\n/**\n * Calculate double SHA-256 hash (SHA-256 of SHA-256)\n * This is the standard Bitcoin hashing function\n */\nexport function doubleSha256(message: Uint8Array): Uint8Array {\n return sha256(sha256(message));\n}\n\n/**\n * Calculate SHA-512 hash\n */\nexport function sha512(data: Uint8Array): Uint8Array {\n return nobleSha512(data);\n}\n\n/**\n * Calculate HMAC-SHA-256\n */\nexport function hmacSha256(key: Uint8Array, message: Uint8Array): Uint8Array {\n return hmac(nobleSha256, key, message);\n}\n\n/**\n * Calculate HMAC-SHA-512\n */\nexport function hmacSha512(key: Uint8Array, message: Uint8Array): Uint8Array {\n return hmac(nobleSha512, key, message);\n}\n\n/**\n * Derive a key using PBKDF2 with HMAC-SHA-256\n */\nexport function pbkdf2HmacSha256(\n password: Uint8Array,\n salt: Uint8Array,\n iterations: number,\n keyLen: number,\n): Uint8Array {\n return pbkdf2(nobleSha256, password, salt, { c: iterations, dkLen: keyLen });\n}\n\n/**\n * Derive a key using PBKDF2 with HMAC-SHA-512\n */\nexport function pbkdf2HmacSha512(\n password: Uint8Array,\n salt: Uint8Array,\n iterations: number,\n keyLen: number,\n): Uint8Array {\n return pbkdf2(nobleSha512, password, salt, { c: iterations, dkLen: keyLen });\n}\n\n/**\n * Derive a key using HKDF with HMAC-SHA-256\n */\nexport function hkdfHmacSha256(\n keyMaterial: Uint8Array,\n salt: Uint8Array,\n keyLen: number,\n): Uint8Array {\n return hkdf(nobleSha256, keyMaterial, salt, undefined, keyLen);\n}\n\n/**\n * Derive a key using HKDF with HMAC-SHA-512\n */\nexport function hkdfHmacSha512(\n keyMaterial: Uint8Array,\n salt: Uint8Array,\n keyLen: number,\n): Uint8Array {\n return hkdf(nobleSha512, keyMaterial, salt, undefined, keyLen);\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/symmetric_encryption.rs\n\nimport { chacha20poly1305 } from \"@noble/ciphers/chacha.js\";\nimport { CryptoError, AeadError } from \"./error.js\";\n\n// Constants\nexport const SYMMETRIC_KEY_SIZE = 32;\nexport const SYMMETRIC_NONCE_SIZE = 12;\nexport const SYMMETRIC_AUTH_SIZE = 16;\n\n/**\n * Encrypt data using ChaCha20-Poly1305 AEAD cipher.\n *\n * **Security Warning**: The nonce MUST be unique for every encryption operation\n * with the same key. Reusing a nonce completely breaks the security of the\n * encryption scheme and can reveal plaintext.\n *\n * @param plaintext - The data to encrypt\n * @param key - 32-byte encryption key\n * @param nonce - 12-byte nonce (MUST be unique per encryption with the same key)\n * @returns Tuple of [ciphertext, authTag] where authTag is 16 bytes\n * @throws {CryptoError} If key is not 32 bytes or nonce is not 12 bytes\n */\nexport function aeadChaCha20Poly1305Encrypt(\n plaintext: Uint8Array,\n key: Uint8Array,\n nonce: Uint8Array,\n): [Uint8Array, Uint8Array] {\n return aeadChaCha20Poly1305EncryptWithAad(plaintext, key, nonce, new Uint8Array(0));\n}\n\n/**\n * Encrypt data using ChaCha20-Poly1305 AEAD cipher with additional authenticated data.\n *\n * **Security Warning**: The nonce MUST be unique for every encryption operation\n * with the same key. Reusing a nonce completely breaks the security of the\n * encryption scheme and can reveal plaintext.\n *\n * @param plaintext - The data to encrypt\n * @param key - 32-byte encryption key\n * @param nonce - 12-byte nonce (MUST be unique per encryption with the same key)\n * @param aad - Additional authenticated data (not encrypted, but integrity-protected)\n * @returns Tuple of [ciphertext, authTag] where authTag is 16 bytes\n * @throws {CryptoError} If key is not 32 bytes or nonce is not 12 bytes\n */\nexport function aeadChaCha20Poly1305EncryptWithAad(\n plaintext: Uint8Array,\n key: Uint8Array,\n nonce: Uint8Array,\n aad: Uint8Array,\n): [Uint8Array, Uint8Array] {\n if (key.length !== SYMMETRIC_KEY_SIZE) {\n throw CryptoError.invalidParameter(`Key must be ${SYMMETRIC_KEY_SIZE} bytes`);\n }\n if (nonce.length !== SYMMETRIC_NONCE_SIZE) {\n throw CryptoError.invalidParameter(`Nonce must be ${SYMMETRIC_NONCE_SIZE} bytes`);\n }\n\n const cipher = chacha20poly1305(key, nonce, aad);\n const sealed = cipher.encrypt(plaintext);\n\n // The sealed output contains ciphertext + 16-byte auth tag\n const ciphertext = sealed.slice(0, sealed.length - SYMMETRIC_AUTH_SIZE);\n const authTag = sealed.slice(sealed.length - SYMMETRIC_AUTH_SIZE);\n\n return [ciphertext, authTag];\n}\n\n/**\n * Decrypt data using ChaCha20-Poly1305 AEAD cipher.\n *\n * @param ciphertext - The encrypted data\n * @param key - 32-byte encryption key (must match key used for encryption)\n * @param nonce - 12-byte nonce (must match nonce used for encryption)\n * @param authTag - 16-byte authentication tag from encryption\n * @returns Decrypted plaintext\n * @throws {CryptoError} If key/nonce/authTag sizes are invalid\n * @throws {CryptoError} If authentication fails (tampered data or wrong key/nonce)\n */\nexport function aeadChaCha20Poly1305Decrypt(\n ciphertext: Uint8Array,\n key: Uint8Array,\n nonce: Uint8Array,\n authTag: Uint8Array,\n): Uint8Array {\n return aeadChaCha20Poly1305DecryptWithAad(ciphertext, key, nonce, new Uint8Array(0), authTag);\n}\n\n/**\n * Decrypt data using ChaCha20-Poly1305 AEAD cipher with additional authenticated data.\n *\n * @param ciphertext - The encrypted data\n * @param key - 32-byte encryption key (must match key used for encryption)\n * @param nonce - 12-byte nonce (must match nonce used for encryption)\n * @param aad - Additional authenticated data (must exactly match AAD used for encryption)\n * @param authTag - 16-byte authentication tag from encryption\n * @returns Decrypted plaintext\n * @throws {CryptoError} If key/nonce/authTag sizes are invalid\n * @throws {CryptoError} If authentication fails (tampered data, wrong key/nonce, or AAD mismatch)\n */\nexport function aeadChaCha20Poly1305DecryptWithAad(\n ciphertext: Uint8Array,\n key: Uint8Array,\n nonce: Uint8Array,\n aad: Uint8Array,\n authTag: Uint8Array,\n): Uint8Array {\n if (key.length !== SYMMETRIC_KEY_SIZE) {\n throw CryptoError.invalidParameter(`Key must be ${SYMMETRIC_KEY_SIZE} bytes`);\n }\n if (nonce.length !== SYMMETRIC_NONCE_SIZE) {\n throw CryptoError.invalidParameter(`Nonce must be ${SYMMETRIC_NONCE_SIZE} bytes`);\n }\n if (authTag.length !== SYMMETRIC_AUTH_SIZE) {\n throw CryptoError.invalidParameter(`Auth tag must be ${SYMMETRIC_AUTH_SIZE} bytes`);\n }\n\n // Combine ciphertext and auth tag for decryption\n const sealed = new Uint8Array(ciphertext.length + authTag.length);\n sealed.set(ciphertext);\n sealed.set(authTag, ciphertext.length);\n\n try {\n const cipher = chacha20poly1305(key, nonce, aad);\n return cipher.decrypt(sealed);\n } catch (error) {\n // Preserve the original error for debugging while wrapping in our error type\n const aeadError = new AeadError(\n `Decryption failed: ${error instanceof Error ? error.message : \"authentication error\"}`,\n );\n throw CryptoError.aead(aeadError);\n }\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/public_key_encryption.rs\n\nimport { x25519 } from \"@noble/curves/ed25519.js\";\nimport type { RandomNumberGenerator } from \"@bcts/rand\";\nimport { hkdfHmacSha256 } from \"./hash.js\";\n\n// Constants\nexport const GENERIC_PRIVATE_KEY_SIZE = 32;\nexport const GENERIC_PUBLIC_KEY_SIZE = 32;\nexport const X25519_PRIVATE_KEY_SIZE = 32;\nexport const X25519_PUBLIC_KEY_SIZE = 32;\n\n/**\n * Derive an X25519 agreement private key from key material.\n * Uses HKDF with \"agreement\" as domain separation salt.\n */\nexport function deriveAgreementPrivateKey(keyMaterial: Uint8Array): Uint8Array {\n const salt = new TextEncoder().encode(\"agreement\");\n return hkdfHmacSha256(keyMaterial, salt, X25519_PRIVATE_KEY_SIZE);\n}\n\n/**\n * Derive a signing private key from key material.\n * Uses HKDF with \"signing\" as domain separation salt.\n */\nexport function deriveSigningPrivateKey(keyMaterial: Uint8Array): Uint8Array {\n const salt = new TextEncoder().encode(\"signing\");\n return hkdfHmacSha256(keyMaterial, salt, 32);\n}\n\n/**\n * Generate a new random X25519 private key.\n */\nexport function x25519NewPrivateKeyUsing(rng: RandomNumberGenerator): Uint8Array {\n return rng.randomData(X25519_PRIVATE_KEY_SIZE);\n}\n\n/**\n * Derive an X25519 public key from a private key.\n */\nexport function x25519PublicKeyFromPrivateKey(privateKey: Uint8Array): Uint8Array {\n if (privateKey.length !== X25519_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${X25519_PRIVATE_KEY_SIZE} bytes`);\n }\n return x25519.getPublicKey(privateKey);\n}\n\n// Symmetric key size for the derived shared key\nconst SYMMETRIC_KEY_SIZE = 32;\n\n/**\n * Compute a shared symmetric key using X25519 key agreement (ECDH).\n *\n * This function performs X25519 Diffie-Hellman key agreement and then\n * derives a symmetric key using HKDF-SHA256 with \"agreement\" as the salt.\n * This matches the Rust bc-crypto implementation for cross-platform compatibility.\n *\n * @param x25519Private - 32-byte X25519 private key\n * @param x25519Public - 32-byte X25519 public key from the other party\n * @returns 32-byte derived symmetric key\n * @throws {Error} If private key is not 32 bytes or public key is not 32 bytes\n */\nexport function x25519SharedKey(x25519Private: Uint8Array, x25519Public: Uint8Array): Uint8Array {\n if (x25519Private.length !== X25519_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${X25519_PRIVATE_KEY_SIZE} bytes`);\n }\n if (x25519Public.length !== X25519_PUBLIC_KEY_SIZE) {\n throw new Error(`Public key must be ${X25519_PUBLIC_KEY_SIZE} bytes`);\n }\n // Perform raw X25519 Diffie-Hellman\n const rawSharedSecret = x25519.getSharedSecret(x25519Private, x25519Public);\n // Derive symmetric key using HKDF with \"agreement\" salt (matches Rust implementation)\n const salt = new TextEncoder().encode(\"agreement\");\n return hkdfHmacSha256(rawSharedSecret, salt, SYMMETRIC_KEY_SIZE);\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/ecdsa_keys.rs\n\nimport { secp256k1 } from \"@noble/curves/secp256k1.js\";\nimport type { RandomNumberGenerator } from \"@bcts/rand\";\nimport { hkdfHmacSha256 } from \"./hash.js\";\n\n// Constants\nexport const ECDSA_PRIVATE_KEY_SIZE = 32;\nexport const ECDSA_PUBLIC_KEY_SIZE = 33; // Compressed\nexport const ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE = 65;\nexport const ECDSA_MESSAGE_HASH_SIZE = 32;\nexport const ECDSA_SIGNATURE_SIZE = 64;\nexport const SCHNORR_PUBLIC_KEY_SIZE = 32; // x-only\n\n/**\n * Generate a new random ECDSA private key using secp256k1.\n *\n * Note: Unlike some implementations, this directly returns the random bytes\n * without validation. The secp256k1 library will handle any edge cases when\n * the key is used.\n */\nexport function ecdsaNewPrivateKeyUsing(rng: RandomNumberGenerator): Uint8Array {\n return rng.randomData(ECDSA_PRIVATE_KEY_SIZE);\n}\n\n/**\n * Derive a compressed ECDSA public key from a private key.\n */\nexport function ecdsaPublicKeyFromPrivateKey(privateKey: Uint8Array): Uint8Array {\n if (privateKey.length !== ECDSA_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);\n }\n return secp256k1.getPublicKey(privateKey, true); // true = compressed\n}\n\n/**\n * Decompress a compressed public key to uncompressed format.\n */\nexport function ecdsaDecompressPublicKey(compressed: Uint8Array): Uint8Array {\n if (compressed.length !== ECDSA_PUBLIC_KEY_SIZE) {\n throw new Error(`Compressed public key must be ${ECDSA_PUBLIC_KEY_SIZE} bytes`);\n }\n const point = secp256k1.Point.fromBytes(compressed);\n return point.toBytes(false); // false = uncompressed\n}\n\n/**\n * Compress an uncompressed public key.\n */\nexport function ecdsaCompressPublicKey(uncompressed: Uint8Array): Uint8Array {\n if (uncompressed.length !== ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE) {\n throw new Error(`Uncompressed public key must be ${ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE} bytes`);\n }\n const point = secp256k1.Point.fromBytes(uncompressed);\n return point.toBytes(true); // true = compressed\n}\n\n/**\n * Derive an ECDSA private key from key material using HKDF.\n *\n * Note: This directly returns the HKDF output without validation,\n * matching the Rust reference implementation behavior.\n */\nexport function ecdsaDerivePrivateKey(keyMaterial: Uint8Array): Uint8Array {\n const salt = new TextEncoder().encode(\"signing\");\n return hkdfHmacSha256(keyMaterial, salt, ECDSA_PRIVATE_KEY_SIZE);\n}\n\n/**\n * Extract the x-only (Schnorr) public key from a private key.\n * This is used for BIP-340 Schnorr signatures.\n */\nexport function schnorrPublicKeyFromPrivateKey(privateKey: Uint8Array): Uint8Array {\n if (privateKey.length !== ECDSA_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);\n }\n // Get the full public key and extract just the x-coordinate\n const fullPubKey = secp256k1.getPublicKey(privateKey, false); // uncompressed\n // Skip the 0x04 prefix and take only x-coordinate (first 32 bytes after prefix)\n return fullPubKey.slice(1, 33);\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/ecdsa_signing.rs\n\nimport { secp256k1 } from \"@noble/curves/secp256k1.js\";\nimport { doubleSha256 } from \"./hash.js\";\nimport {\n ECDSA_PRIVATE_KEY_SIZE,\n ECDSA_PUBLIC_KEY_SIZE,\n ECDSA_SIGNATURE_SIZE,\n} from \"./ecdsa-keys.js\";\n\n/**\n * Sign a message using ECDSA with secp256k1.\n *\n * The message is hashed with double SHA-256 before signing (Bitcoin standard).\n *\n * **Security Note**: The private key must be kept secret. ECDSA requires\n * cryptographically secure random nonces internally; this is handled by\n * the underlying library using RFC 6979 deterministic nonces.\n *\n * @param privateKey - 32-byte secp256k1 private key\n * @param message - Message to sign (any length, will be double-SHA256 hashed)\n * @returns 64-byte compact signature (r || s format)\n * @throws {Error} If private key is not 32 bytes\n */\nexport function ecdsaSign(privateKey: Uint8Array, message: Uint8Array): Uint8Array {\n if (privateKey.length !== ECDSA_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);\n }\n\n const messageHash = doubleSha256(message);\n // prehash: false because we already hashed the message with doubleSha256\n return secp256k1.sign(messageHash, privateKey, { prehash: false });\n}\n\n/**\n * Verify an ECDSA signature with secp256k1.\n *\n * The message is hashed with double SHA-256 before verification (Bitcoin standard).\n *\n * @param publicKey - 33-byte compressed secp256k1 public key\n * @param signature - 64-byte compact signature (r || s format)\n * @param message - Original message that was signed\n * @returns `true` if signature is valid, `false` if signature verification fails\n * @throws {Error} If public key is not 33 bytes or signature is not 64 bytes\n */\nexport function ecdsaVerify(\n publicKey: Uint8Array,\n signature: Uint8Array,\n message: Uint8Array,\n): boolean {\n if (publicKey.length !== ECDSA_PUBLIC_KEY_SIZE) {\n throw new Error(`Public key must be ${ECDSA_PUBLIC_KEY_SIZE} bytes`);\n }\n if (signature.length !== ECDSA_SIGNATURE_SIZE) {\n throw new Error(`Signature must be ${ECDSA_SIGNATURE_SIZE} bytes`);\n }\n\n try {\n const messageHash = doubleSha256(message);\n // prehash: false because we already hashed the message with doubleSha256\n return secp256k1.verify(signature, messageHash, publicKey, { prehash: false });\n } catch {\n return false;\n }\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/schnorr_signing.rs\n\nimport { schnorr } from \"@noble/curves/secp256k1.js\";\nimport type { RandomNumberGenerator } from \"@bcts/rand\";\nimport { SecureRandomNumberGenerator } from \"@bcts/rand\";\nimport { ECDSA_PRIVATE_KEY_SIZE, SCHNORR_PUBLIC_KEY_SIZE } from \"./ecdsa-keys.js\";\n\n// Constants\nexport const SCHNORR_SIGNATURE_SIZE = 64;\n\n/**\n * Sign a message using Schnorr signature (BIP-340).\n * Uses secure random auxiliary randomness.\n *\n * @param ecdsaPrivateKey - 32-byte private key\n * @param message - Message to sign (not pre-hashed, per BIP-340)\n * @returns 64-byte Schnorr signature\n */\nexport function schnorrSign(ecdsaPrivateKey: Uint8Array, message: Uint8Array): Uint8Array {\n const rng = new SecureRandomNumberGenerator();\n return schnorrSignUsing(ecdsaPrivateKey, message, rng);\n}\n\n/**\n * Sign a message using Schnorr signature with a custom RNG.\n *\n * @param ecdsaPrivateKey - 32-byte private key\n * @param message - Message to sign\n * @param rng - Random number generator for auxiliary randomness\n * @returns 64-byte Schnorr signature\n */\nexport function schnorrSignUsing(\n ecdsaPrivateKey: Uint8Array,\n message: Uint8Array,\n rng: RandomNumberGenerator,\n): Uint8Array {\n const auxRand = rng.randomData(32);\n return schnorrSignWithAuxRand(ecdsaPrivateKey, message, auxRand);\n}\n\n/**\n * Sign a message using Schnorr signature with specific auxiliary randomness.\n * This is useful for deterministic signing in tests.\n *\n * @param ecdsaPrivateKey - 32-byte private key\n * @param message - Message to sign\n * @param auxRand - 32-byte auxiliary randomness (per BIP-340)\n * @returns 64-byte Schnorr signature\n */\nexport function schnorrSignWithAuxRand(\n ecdsaPrivateKey: Uint8Array,\n message: Uint8Array,\n auxRand: Uint8Array,\n): Uint8Array {\n if (ecdsaPrivateKey.length !== ECDSA_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);\n }\n if (auxRand.length !== 32) {\n throw new Error(\"Auxiliary randomness must be 32 bytes\");\n }\n\n return schnorr.sign(message, ecdsaPrivateKey, auxRand);\n}\n\n/**\n * Verify a Schnorr signature (BIP-340).\n *\n * @param schnorrPublicKey - 32-byte x-only public key\n * @param signature - 64-byte Schnorr signature\n * @param message - Original message\n * @returns true if signature is valid\n */\nexport function schnorrVerify(\n schnorrPublicKey: Uint8Array,\n signature: Uint8Array,\n message: Uint8Array,\n): boolean {\n if (schnorrPublicKey.length !== SCHNORR_PUBLIC_KEY_SIZE) {\n throw new Error(`Public key must be ${SCHNORR_PUBLIC_KEY_SIZE} bytes`);\n }\n if (signature.length !== SCHNORR_SIGNATURE_SIZE) {\n throw new Error(`Signature must be ${SCHNORR_SIGNATURE_SIZE} bytes`);\n }\n\n try {\n return schnorr.verify(signature, message, schnorrPublicKey);\n } catch {\n return false;\n }\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/ed25519_signing.rs\n\nimport { ed25519 } from \"@noble/curves/ed25519.js\";\nimport type { RandomNumberGenerator } from \"@bcts/rand\";\n\n// Constants\nexport const ED25519_PUBLIC_KEY_SIZE = 32;\nexport const ED25519_PRIVATE_KEY_SIZE = 32;\nexport const ED25519_SIGNATURE_SIZE = 64;\n\n/**\n * Generate a new random Ed25519 private key.\n */\nexport function ed25519NewPrivateKeyUsing(rng: RandomNumberGenerator): Uint8Array {\n return rng.randomData(ED25519_PRIVATE_KEY_SIZE);\n}\n\n/**\n * Derive an Ed25519 public key from a private key.\n */\nexport function ed25519PublicKeyFromPrivateKey(privateKey: Uint8Array): Uint8Array {\n if (privateKey.length !== ED25519_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ED25519_PRIVATE_KEY_SIZE} bytes`);\n }\n return ed25519.getPublicKey(privateKey);\n}\n\n/**\n * Sign a message using Ed25519.\n *\n * **Security Note**: The private key must be kept secret. The same private key\n * can safely sign multiple messages.\n *\n * @param privateKey - 32-byte Ed25519 private key\n * @param message - Message to sign (any length)\n * @returns 64-byte Ed25519 signature\n * @throws {Error} If private key is not 32 bytes\n */\nexport function ed25519Sign(privateKey: Uint8Array, message: Uint8Array): Uint8Array {\n if (privateKey.length !== ED25519_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ED25519_PRIVATE_KEY_SIZE} bytes`);\n }\n return ed25519.sign(message, privateKey);\n}\n\n/**\n * Verify an Ed25519 signature.\n *\n * @param publicKey - 32-byte Ed25519 public key\n * @param message - Original message that was signed\n * @param signature - 64-byte Ed25519 signature\n * @returns `true` if signature is valid, `false` if signature verification fails\n * @throws {Error} If public key is not 32 bytes or signature is not 64 bytes\n */\nexport function ed25519Verify(\n publicKey: Uint8Array,\n message: Uint8Array,\n signature: Uint8Array,\n): boolean {\n if (publicKey.length !== ED25519_PUBLIC_KEY_SIZE) {\n throw new Error(`Public key must be ${ED25519_PUBLIC_KEY_SIZE} bytes`);\n }\n if (signature.length !== ED25519_SIGNATURE_SIZE) {\n throw new Error(`Signature must be ${ED25519_SIGNATURE_SIZE} bytes`);\n }\n\n try {\n return ed25519.verify(signature, message, publicKey);\n } catch {\n return false;\n }\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/scrypt.rs\n\nimport { scrypt as nobleScrypt } from \"@noble/hashes/scrypt.js\";\n\n/**\n * Derive a key using Scrypt with recommended parameters.\n * Uses N=2^15 (32768), r=8, p=1 as recommended defaults.\n *\n * @param password - Password or passphrase\n * @param salt - Salt value\n * @param outputLen - Desired output length\n * @returns Derived key\n */\nexport function scrypt(password: Uint8Array, salt: Uint8Array, outputLen: number): Uint8Array {\n return scryptOpt(password, salt, outputLen, 15, 8, 1);\n}\n\n/**\n * Derive a key using Scrypt with custom parameters.\n *\n * @param password - Password or passphrase\n * @param salt - Salt value\n * @param outputLen - Desired output length\n * @param logN - Log2 of the CPU/memory cost parameter N (must be <64)\n * @param r - Block size parameter (must be >0)\n * @param p - Parallelization parameter (must be >0)\n * @returns Derived key\n */\nexport function scryptOpt(\n password: Uint8Array,\n salt: Uint8Array,\n outputLen: number,\n logN: number,\n r: number,\n p: number,\n): Uint8Array {\n if (logN >= 64) {\n throw new Error(\"logN must be <64\");\n }\n if (r === 0) {\n throw new Error(\"r must be >0\");\n }\n if (p === 0) {\n throw new Error(\"p must be >0\");\n }\n\n const N = 1 << logN; // 2^logN\n\n return nobleScrypt(password, salt, { N, r, p, dkLen: outputLen });\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/argon.rs\n\nimport { argon2id as nobleArgon2id } from \"@noble/hashes/argon2.js\";\n\n/**\n * Derive a key using Argon2id with default parameters.\n * This matches the Rust `argon2id` function signature.\n *\n * @param password - Password or passphrase\n * @param salt - Salt value (must be at least 8 bytes)\n * @param outputLen - Desired output length\n * @returns Derived key\n */\nexport function argon2id(password: Uint8Array, salt: Uint8Array, outputLen: number): Uint8Array {\n // Use default parameters matching Argon2::default() in Rust\n return argon2idHashOpt(password, salt, outputLen, 3, 65536, 4);\n}\n\n/**\n * Derive a key using Argon2id with custom parameters.\n *\n * @param password - Password or passphrase\n * @param salt - Salt value (must be at least 8 bytes)\n * @param outputLen - Desired output length\n * @param iterations - Number of iterations (t)\n * @param memory - Memory in KiB (m)\n * @param parallelism - Degree of parallelism (p)\n * @returns Derived key\n */\nexport function argon2idHashOpt(\n password: Uint8Array,\n salt: Uint8Array,\n outputLen: number,\n iterations: number,\n memory: number,\n parallelism: number,\n): Uint8Array {\n return nobleArgon2id(password, salt, {\n t: iterations,\n m: memory,\n p: parallelism,\n dkLen: outputLen,\n });\n}\n"],"mappings":";;;;;;;;;;;;;CAWA,IAAa,YAAb,cAA+B,MAAM;EACnC,YAAY,UAAU,8BAA8B;AAClD,SAAM,QAAQ;AACd,QAAK,OAAO;;;;;;CAOhB,IAAa,cAAb,MAAa,oBAAoB,MAAM;EACrC,AAAkB;EAElB,YAAY,SAAiB,OAAe;AAC1C,SAAM,QAAQ;AACd,QAAK,OAAO;AACZ,QAAK,QAAQ;;;;;;;;EASf,OAAO,KAAK,OAAgC;AAC1C,UAAO,IAAI,YAAY,cAAc,SAAS,IAAI,WAAW,CAAC;;;;;;;;EAShE,OAAO,iBAAiB,SAA8B;AACpD,UAAO,IAAI,YAAY,sBAAsB,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;CCvB3D,SAAgB,QAAQ,MAAsC;EAC5D,MAAM,MAAM,KAAK;AACjB,OAAK,IAAI,IAAI,GAAG,IAAI,KAAK,IACvB,MAAK,KAAK;AAGZ,MAAI,KAAK,SAAS,KAAK,KAAK,OAAO,EACjC,OAAM,IAAI,MAAM,iBAAiB;;;;;CAOrC,SAAgB,gBAAgB,QAA4B;AAC1D,OAAK,MAAM,OAAO,OAChB,SAAQ,IAAI;;;;;;;;;;CC1BhB,MAAa,aAAa;CAC1B,MAAa,cAAc;CAC3B,MAAa,cAAc;CAG3B,MAAM,cAAc,IAAI,YAAY,IAAI;AACxC,MAAK,IAAI,IAAI,GAAG,IAAI,KAAK,KAAK;EAC5B,IAAI,MAAM;AACV,OAAK,IAAI,IAAI,GAAG,IAAI,GAAG,IACrB,QAAO,MAAM,OAAO,IAAK,QAAQ,IAAK,aAAa,QAAQ;AAE7D,cAAY,KAAK,QAAQ;;;;;CAM3B,SAAgB,MAAM,MAA0B;EAC9C,IAAI,MAAM;AACV,OAAK,MAAM,QAAQ,KACjB,OAAM,aAAa,MAAM,QAAQ,OAAS,QAAQ;AAEpD,UAAQ,MAAM,gBAAgB;;;;;CAMhC,SAAgB,UAAU,MAA8B;AACtD,SAAO,aAAa,MAAM,MAAM;;;;;;;CAQlC,SAAgB,aAAa,MAAkB,cAAmC;EAChF,MAAM,WAAW,MAAM,KAAK;EAC5B,MAAM,SAAS,IAAI,WAAW,EAAE;AAEhC,EADa,IAAI,SAAS,OAAO,OAAO,CACnC,UAAU,GAAG,UAAU,aAAa;AACzC,SAAO;;;;;CAMT,SAAgB,OAAO,MAA8B;AACnD,2CAAmB,KAAK;;;;;;CAO1B,SAAgB,aAAa,SAAiC;AAC5D,SAAO,OAAO,OAAO,QAAQ,CAAC;;;;;CAMhC,SAAgB,OAAO,MAA8B;AACnD,2CAAmB,KAAK;;;;;CAM1B,SAAgB,WAAW,KAAiB,SAAiC;AAC3E,yCAAYA,8BAAa,KAAK,QAAQ;;;;;CAMxC,SAAgB,WAAW,KAAiB,SAAiC;AAC3E,yCAAYC,8BAAa,KAAK,QAAQ;;;;;CAMxC,SAAgB,iBACd,UACA,MACA,YACA,QACY;AACZ,6CAAcD,8BAAa,UAAU,MAAM;GAAE,GAAG;GAAY,OAAO;GAAQ,CAAC;;;;;CAM9E,SAAgB,iBACd,UACA,MACA,YACA,QACY;AACZ,6CAAcC,8BAAa,UAAU,MAAM;GAAE,GAAG;GAAY,OAAO;GAAQ,CAAC;;;;;CAM9E,SAAgB,eACd,aACA,MACA,QACY;AACZ,yCAAYD,8BAAa,aAAa,MAAM,QAAW,OAAO;;;;;CAMhE,SAAgB,eACd,aACA,MACA,QACY;AACZ,yCAAYC,8BAAa,aAAa,MAAM,QAAW,OAAO;;;;;;;;;;CC9HhE,MAAa,qBAAqB;CAClC,MAAa,uBAAuB;CACpC,MAAa,sBAAsB;;;;;;;;;;;;;;CAenC,SAAgB,4BACd,WACA,KACA,OAC0B;AAC1B,SAAO,mCAAmC,WAAW,KAAK,OAAO,IAAI,WAAW,EAAE,CAAC;;;;;;;;;;;;;;;;CAiBrF,SAAgB,mCACd,WACA,KACA,OACA,KAC0B;AAC1B,MAAI,IAAI,WAAW,mBACjB,OAAM,YAAY,iBAAiB,eAAe,mBAAmB,QAAQ;AAE/E,MAAI,MAAM,WAAW,qBACnB,OAAM,YAAY,iBAAiB,iBAAiB,qBAAqB,QAAQ;EAInF,MAAM,wDAD0B,KAAK,OAAO,IAAI,CAC1B,QAAQ,UAAU;AAMxC,SAAO,CAHY,OAAO,MAAM,GAAG,OAAO,SAAS,oBAAoB,EACvD,OAAO,MAAM,OAAO,SAAS,oBAAoB,CAErC;;;;;;;;;;;;;CAc9B,SAAgB,4BACd,YACA,KACA,OACA,SACY;AACZ,SAAO,mCAAmC,YAAY,KAAK,OAAO,IAAI,WAAW,EAAE,EAAE,QAAQ;;;;;;;;;;;;;;CAe/F,SAAgB,mCACd,YACA,KACA,OACA,KACA,SACY;AACZ,MAAI,IAAI,WAAW,mBACjB,OAAM,YAAY,iBAAiB,eAAe,mBAAmB,QAAQ;AAE/E,MAAI,MAAM,WAAW,qBACnB,OAAM,YAAY,iBAAiB,iBAAiB,qBAAqB,QAAQ;AAEnF,MAAI,QAAQ,WAAW,oBACrB,OAAM,YAAY,iBAAiB,oBAAoB,oBAAoB,QAAQ;EAIrF,MAAM,SAAS,IAAI,WAAW,WAAW,SAAS,QAAQ,OAAO;AACjE,SAAO,IAAI,WAAW;AACtB,SAAO,IAAI,SAAS,WAAW,OAAO;AAEtC,MAAI;AAEF,yDADgC,KAAK,OAAO,IAAI,CAClC,QAAQ,OAAO;WACtB,OAAO;GAEd,MAAM,YAAY,IAAI,UACpB,sBAAsB,iBAAiB,QAAQ,MAAM,UAAU,yBAChE;AACD,SAAM,YAAY,KAAK,UAAU;;;;;;;;;;;CC3HrC,MAAa,2BAA2B;CACxC,MAAa,0BAA0B;CACvC,MAAa,0BAA0B;CACvC,MAAa,yBAAyB;;;;;CAMtC,SAAgB,0BAA0B,aAAqC;AAE7E,SAAO,eAAe,aADT,IAAI,aAAa,CAAC,OAAO,YAAY,EACT,wBAAwB;;;;;;CAOnE,SAAgB,wBAAwB,aAAqC;AAE3E,SAAO,eAAe,aADT,IAAI,aAAa,CAAC,OAAO,UAAU,EACP,GAAG;;;;;CAM9C,SAAgB,yBAAyB,KAAwC;AAC/E,SAAO,IAAI,WAAW,wBAAwB;;;;;CAMhD,SAAgB,8BAA8B,YAAoC;AAChF,MAAI,WAAW,WAAW,wBACxB,OAAM,IAAI,MAAM,uBAAuB,wBAAwB,QAAQ;AAEzE,SAAOC,gCAAO,aAAa,WAAW;;CAIxC,MAAMC,uBAAqB;;;;;;;;;;;;;CAc3B,SAAgB,gBAAgB,eAA2B,cAAsC;AAC/F,MAAI,cAAc,WAAW,wBAC3B,OAAM,IAAI,MAAM,uBAAuB,wBAAwB,QAAQ;AAEzE,MAAI,aAAa,WAAW,uBAC1B,OAAM,IAAI,MAAM,sBAAsB,uBAAuB,QAAQ;AAMvE,SAAO,eAHiBD,gCAAO,gBAAgB,eAAe,aAAa,EAE9D,IAAI,aAAa,CAAC,OAAO,YAAY,EACLC,qBAAmB;;;;;;;;;;CClElE,MAAa,yBAAyB;CACtC,MAAa,wBAAwB;CACrC,MAAa,qCAAqC;CAClD,MAAa,0BAA0B;CACvC,MAAa,uBAAuB;CACpC,MAAa,0BAA0B;;;;;;;;CASvC,SAAgB,wBAAwB,KAAwC;AAC9E,SAAO,IAAI,WAAW,uBAAuB;;;;;CAM/C,SAAgB,6BAA6B,YAAoC;AAC/E,MAAI,WAAW,WAAW,uBACxB,OAAM,IAAI,MAAM,uBAAuB,uBAAuB,QAAQ;AAExE,SAAOC,qCAAU,aAAa,YAAY,KAAK;;;;;CAMjD,SAAgB,yBAAyB,YAAoC;AAC3E,MAAI,WAAW,WAAW,sBACxB,OAAM,IAAI,MAAM,iCAAiC,sBAAsB,QAAQ;AAGjF,SADcA,qCAAU,MAAM,UAAU,WAAW,CACtC,QAAQ,MAAM;;;;;CAM7B,SAAgB,uBAAuB,cAAsC;AAC3E,MAAI,aAAa,WAAW,mCAC1B,OAAM,IAAI,MAAM,mCAAmC,mCAAmC,QAAQ;AAGhG,SADcA,qCAAU,MAAM,UAAU,aAAa,CACxC,QAAQ,KAAK;;;;;;;;CAS5B,SAAgB,sBAAsB,aAAqC;AAEzE,SAAO,eAAe,aADT,IAAI,aAAa,CAAC,OAAO,UAAU,EACP,uBAAuB;;;;;;CAOlE,SAAgB,+BAA+B,YAAoC;AACjF,MAAI,WAAW,WAAW,uBACxB,OAAM,IAAI,MAAM,uBAAuB,uBAAuB,QAAQ;AAKxE,SAFmBA,qCAAU,aAAa,YAAY,MAAM,CAE1C,MAAM,GAAG,GAAG;;;;;;;;;;;;;;;;;;;;;;;;CCvDhC,SAAgB,UAAU,YAAwB,SAAiC;AACjF,MAAI,WAAW,WAAW,uBACxB,OAAM,IAAI,MAAM,uBAAuB,uBAAuB,QAAQ;EAGxE,MAAM,cAAc,aAAa,QAAQ;AAEzC,SAAOC,qCAAU,KAAK,aAAa,YAAY,EAAE,SAAS,OAAO,CAAC;;;;;;;;;;;;;CAcpE,SAAgB,YACd,WACA,WACA,SACS;AACT,MAAI,UAAU,WAAW,sBACvB,OAAM,IAAI,MAAM,sBAAsB,sBAAsB,QAAQ;AAEtE,MAAI,UAAU,WAAW,qBACvB,OAAM,IAAI,MAAM,qBAAqB,qBAAqB,QAAQ;AAGpE,MAAI;GACF,MAAM,cAAc,aAAa,QAAQ;AAEzC,UAAOA,qCAAU,OAAO,WAAW,aAAa,WAAW,EAAE,SAAS,OAAO,CAAC;UACxE;AACN,UAAO;;;;;;;;;;;CCtDX,MAAa,yBAAyB;;;;;;;;;CAUtC,SAAgB,YAAY,iBAA6B,SAAiC;AAExF,SAAO,iBAAiB,iBAAiB,SAD7B,IAAIC,wCAA6B,CACS;;;;;;;;;;CAWxD,SAAgB,iBACd,iBACA,SACA,KACY;AAEZ,SAAO,uBAAuB,iBAAiB,SAD/B,IAAI,WAAW,GAAG,CAC8B;;;;;;;;;;;CAYlE,SAAgB,uBACd,iBACA,SACA,SACY;AACZ,MAAI,gBAAgB,WAAW,uBAC7B,OAAM,IAAI,MAAM,uBAAuB,uBAAuB,QAAQ;AAExE,MAAI,QAAQ,WAAW,GACrB,OAAM,IAAI,MAAM,wCAAwC;AAG1D,SAAOC,mCAAQ,KAAK,SAAS,iBAAiB,QAAQ;;;;;;;;;;CAWxD,SAAgB,cACd,kBACA,WACA,SACS;AACT,MAAI,iBAAiB,WAAW,wBAC9B,OAAM,IAAI,MAAM,sBAAsB,wBAAwB,QAAQ;AAExE,MAAI,UAAU,WAAW,uBACvB,OAAM,IAAI,MAAM,qBAAqB,uBAAuB,QAAQ;AAGtE,MAAI;AACF,UAAOA,mCAAQ,OAAO,WAAW,SAAS,iBAAiB;UACrD;AACN,UAAO;;;;;;;;;;;CCjFX,MAAa,0BAA0B;CACvC,MAAa,2BAA2B;CACxC,MAAa,yBAAyB;;;;CAKtC,SAAgB,0BAA0B,KAAwC;AAChF,SAAO,IAAI,WAAW,yBAAyB;;;;;CAMjD,SAAgB,+BAA+B,YAAoC;AACjF,MAAI,WAAW,WAAW,yBACxB,OAAM,IAAI,MAAM,uBAAuB,yBAAyB,QAAQ;AAE1E,SAAOC,iCAAQ,aAAa,WAAW;;;;;;;;;;;;;CAczC,SAAgB,YAAY,YAAwB,SAAiC;AACnF,MAAI,WAAW,WAAW,yBACxB,OAAM,IAAI,MAAM,uBAAuB,yBAAyB,QAAQ;AAE1E,SAAOA,iCAAQ,KAAK,SAAS,WAAW;;;;;;;;;;;CAY1C,SAAgB,cACd,WACA,SACA,WACS;AACT,MAAI,UAAU,WAAW,wBACvB,OAAM,IAAI,MAAM,sBAAsB,wBAAwB,QAAQ;AAExE,MAAI,UAAU,WAAW,uBACvB,OAAM,IAAI,MAAM,qBAAqB,uBAAuB,QAAQ;AAGtE,MAAI;AACF,UAAOA,iCAAQ,OAAO,WAAW,SAAS,UAAU;UAC9C;AACN,UAAO;;;;;;;;;;;;;;;;;;;;CCxDX,SAAgB,OAAO,UAAsB,MAAkB,WAA+B;AAC5F,SAAO,UAAU,UAAU,MAAM,WAAW,IAAI,GAAG,EAAE;;;;;;;;;;;;;CAcvD,SAAgB,UACd,UACA,MACA,WACA,MACA,GACA,GACY;AACZ,MAAI,QAAQ,GACV,OAAM,IAAI,MAAM,mBAAmB;AAErC,MAAI,MAAM,EACR,OAAM,IAAI,MAAM,eAAe;AAEjC,MAAI,MAAM,EACR,OAAM,IAAI,MAAM,eAAe;AAKjC,6CAAmB,UAAU,MAAM;GAAE,GAF3B,KAAK;GAEyB;GAAG;GAAG,OAAO;GAAW,CAAC;;;;;;;;;;;;;;;;;;;CCnCnE,SAAgB,SAAS,UAAsB,MAAkB,WAA+B;AAE9F,SAAO,gBAAgB,UAAU,MAAM,WAAW,GAAG,OAAO,EAAE;;;;;;;;;;;;;CAchE,SAAgB,gBACd,UACA,MACA,WACA,YACA,QACA,aACY;AACZ,+CAAqB,UAAU,MAAM;GACnC,GAAG;GACH,GAAG;GACH,GAAG;GACH,OAAO;GACR,CAAC"}
1
+ {"version":3,"file":"index.iife.js","names":["nobleSha256","nobleSha512","x25519","SYMMETRIC_KEY_SIZE","secp256k1","secp256k1","SecureRandomNumberGenerator","schnorr","ed25519"],"sources":["../src/error.ts","../src/memzero.ts","../src/hash.ts","../src/symmetric-encryption.ts","../src/public-key-encryption.ts","../src/ecdsa-keys.ts","../src/ecdsa-signing.ts","../src/schnorr-signing.ts","../src/ed25519-signing.ts","../src/scrypt.ts","../src/argon.ts"],"sourcesContent":["/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/error.rs\n\n/**\n * AEAD-specific error for authentication failures\n */\nexport class AeadError extends Error {\n constructor(message = \"AEAD authentication failed\") {\n super(message);\n this.name = \"AeadError\";\n }\n}\n\n/**\n * Generic crypto error type\n */\nexport class CryptoError extends Error {\n override readonly cause?: Error | undefined;\n\n constructor(message: string, cause?: Error) {\n super(message);\n this.name = \"CryptoError\";\n this.cause = cause;\n }\n\n /**\n * Create a CryptoError for AEAD authentication failures.\n *\n * @param error - Optional underlying AeadError\n * @returns A CryptoError wrapping the AEAD error\n */\n static aead(error?: AeadError): CryptoError {\n return new CryptoError(\"AEAD error\", error ?? new AeadError());\n }\n\n /**\n * Create a CryptoError for invalid parameter values.\n *\n * @param message - Description of the invalid parameter\n * @returns A CryptoError describing the invalid parameter\n */\n static invalidParameter(message: string): CryptoError {\n return new CryptoError(`Invalid parameter: ${message}`);\n }\n}\n\n/**\n * Result type for crypto operations (using standard Error)\n */\nexport type CryptoResult<T> = T;\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/memzero.rs\n\n/**\n * Securely zero out a typed array.\n *\n * **IMPORTANT: This is a best-effort implementation.** Unlike the Rust reference\n * implementation which uses `std::ptr::write_volatile()` for guaranteed volatile\n * writes, JavaScript engines and JIT compilers can still potentially optimize\n * away these zeroing operations. The check at the end helps prevent optimization,\n * but it is not foolproof.\n *\n * For truly sensitive cryptographic operations, consider using the Web Crypto API's\n * `crypto.subtle` with non-extractable keys when possible, as it provides stronger\n * guarantees than what can be achieved with pure JavaScript.\n *\n * This function attempts to prevent the compiler from optimizing away\n * the zeroing operation by using a verification check after the zeroing loop.\n */\nexport function memzero(data: Uint8Array | Uint32Array): void {\n const len = data.length;\n for (let i = 0; i < len; i++) {\n data[i] = 0;\n }\n // Force a side effect to prevent optimization\n if (data.length > 0 && data[0] !== 0) {\n throw new Error(\"memzero failed\");\n }\n}\n\n/**\n * Securely zero out an array of Uint8Arrays.\n */\nexport function memzeroVecVecU8(arrays: Uint8Array[]): void {\n for (const arr of arrays) {\n memzero(arr);\n }\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/hash.rs\n\nimport { sha256 as nobleSha256, sha512 as nobleSha512 } from \"@noble/hashes/sha2.js\";\nimport { hmac } from \"@noble/hashes/hmac.js\";\nimport { pbkdf2 } from \"@noble/hashes/pbkdf2.js\";\nimport { hkdf } from \"@noble/hashes/hkdf.js\";\n\n// Constants\nexport const CRC32_SIZE = 4;\nexport const SHA256_SIZE = 32;\nexport const SHA512_SIZE = 64;\n\n// CRC-32 lookup table (IEEE polynomial 0xedb88320)\nconst CRC32_TABLE = new Uint32Array(256);\nfor (let i = 0; i < 256; i++) {\n let crc = i;\n for (let j = 0; j < 8; j++) {\n crc = (crc & 1) !== 0 ? (crc >>> 1) ^ 0xedb88320 : crc >>> 1;\n }\n CRC32_TABLE[i] = crc >>> 0;\n}\n\n/**\n * Calculate CRC-32 checksum\n */\nexport function crc32(data: Uint8Array): number {\n let crc = 0xffffffff;\n for (const byte of data) {\n crc = CRC32_TABLE[(crc ^ byte) & 0xff] ^ (crc >>> 8);\n }\n return (crc ^ 0xffffffff) >>> 0;\n}\n\n/**\n * Calculate CRC-32 checksum and return as a 4-byte big-endian array\n */\nexport function crc32Data(data: Uint8Array): Uint8Array {\n return crc32DataOpt(data, false);\n}\n\n/**\n * Calculate CRC-32 checksum and return as a 4-byte array\n * @param data - Input data\n * @param littleEndian - If true, returns little-endian; otherwise big-endian\n */\nexport function crc32DataOpt(data: Uint8Array, littleEndian: boolean): Uint8Array {\n const checksum = crc32(data);\n const result = new Uint8Array(4);\n const view = new DataView(result.buffer);\n view.setUint32(0, checksum, littleEndian);\n return result;\n}\n\n/**\n * Calculate SHA-256 hash\n */\nexport function sha256(data: Uint8Array): Uint8Array {\n return nobleSha256(data);\n}\n\n/**\n * Calculate double SHA-256 hash (SHA-256 of SHA-256)\n * This is the standard Bitcoin hashing function\n */\nexport function doubleSha256(message: Uint8Array): Uint8Array {\n return sha256(sha256(message));\n}\n\n/**\n * Calculate SHA-512 hash\n */\nexport function sha512(data: Uint8Array): Uint8Array {\n return nobleSha512(data);\n}\n\n/**\n * Calculate HMAC-SHA-256\n */\nexport function hmacSha256(key: Uint8Array, message: Uint8Array): Uint8Array {\n return hmac(nobleSha256, key, message);\n}\n\n/**\n * Calculate HMAC-SHA-512\n */\nexport function hmacSha512(key: Uint8Array, message: Uint8Array): Uint8Array {\n return hmac(nobleSha512, key, message);\n}\n\n/**\n * Derive a key using PBKDF2 with HMAC-SHA-256\n */\nexport function pbkdf2HmacSha256(\n password: Uint8Array,\n salt: Uint8Array,\n iterations: number,\n keyLen: number,\n): Uint8Array {\n return pbkdf2(nobleSha256, password, salt, { c: iterations, dkLen: keyLen });\n}\n\n/**\n * Derive a key using PBKDF2 with HMAC-SHA-512\n */\nexport function pbkdf2HmacSha512(\n password: Uint8Array,\n salt: Uint8Array,\n iterations: number,\n keyLen: number,\n): Uint8Array {\n return pbkdf2(nobleSha512, password, salt, { c: iterations, dkLen: keyLen });\n}\n\n/**\n * Derive a key using HKDF with HMAC-SHA-256\n */\nexport function hkdfHmacSha256(\n keyMaterial: Uint8Array,\n salt: Uint8Array,\n keyLen: number,\n): Uint8Array {\n return hkdf(nobleSha256, keyMaterial, salt, undefined, keyLen);\n}\n\n/**\n * Derive a key using HKDF with HMAC-SHA-512\n */\nexport function hkdfHmacSha512(\n keyMaterial: Uint8Array,\n salt: Uint8Array,\n keyLen: number,\n): Uint8Array {\n return hkdf(nobleSha512, keyMaterial, salt, undefined, keyLen);\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/symmetric_encryption.rs\n\nimport { chacha20poly1305 } from \"@noble/ciphers/chacha.js\";\nimport { CryptoError, AeadError } from \"./error.js\";\n\n// Constants\nexport const SYMMETRIC_KEY_SIZE = 32;\nexport const SYMMETRIC_NONCE_SIZE = 12;\nexport const SYMMETRIC_AUTH_SIZE = 16;\n\n/**\n * Encrypt data using ChaCha20-Poly1305 AEAD cipher.\n *\n * **Security Warning**: The nonce MUST be unique for every encryption operation\n * with the same key. Reusing a nonce completely breaks the security of the\n * encryption scheme and can reveal plaintext.\n *\n * @param plaintext - The data to encrypt\n * @param key - 32-byte encryption key\n * @param nonce - 12-byte nonce (MUST be unique per encryption with the same key)\n * @returns Tuple of [ciphertext, authTag] where authTag is 16 bytes\n * @throws {CryptoError} If key is not 32 bytes or nonce is not 12 bytes\n */\nexport function aeadChaCha20Poly1305Encrypt(\n plaintext: Uint8Array,\n key: Uint8Array,\n nonce: Uint8Array,\n): [Uint8Array, Uint8Array] {\n return aeadChaCha20Poly1305EncryptWithAad(plaintext, key, nonce, new Uint8Array(0));\n}\n\n/**\n * Encrypt data using ChaCha20-Poly1305 AEAD cipher with additional authenticated data.\n *\n * **Security Warning**: The nonce MUST be unique for every encryption operation\n * with the same key. Reusing a nonce completely breaks the security of the\n * encryption scheme and can reveal plaintext.\n *\n * @param plaintext - The data to encrypt\n * @param key - 32-byte encryption key\n * @param nonce - 12-byte nonce (MUST be unique per encryption with the same key)\n * @param aad - Additional authenticated data (not encrypted, but integrity-protected)\n * @returns Tuple of [ciphertext, authTag] where authTag is 16 bytes\n * @throws {CryptoError} If key is not 32 bytes or nonce is not 12 bytes\n */\nexport function aeadChaCha20Poly1305EncryptWithAad(\n plaintext: Uint8Array,\n key: Uint8Array,\n nonce: Uint8Array,\n aad: Uint8Array,\n): [Uint8Array, Uint8Array] {\n if (key.length !== SYMMETRIC_KEY_SIZE) {\n throw CryptoError.invalidParameter(`Key must be ${SYMMETRIC_KEY_SIZE} bytes`);\n }\n if (nonce.length !== SYMMETRIC_NONCE_SIZE) {\n throw CryptoError.invalidParameter(`Nonce must be ${SYMMETRIC_NONCE_SIZE} bytes`);\n }\n\n const cipher = chacha20poly1305(key, nonce, aad);\n const sealed = cipher.encrypt(plaintext);\n\n // The sealed output contains ciphertext + 16-byte auth tag\n const ciphertext = sealed.slice(0, sealed.length - SYMMETRIC_AUTH_SIZE);\n const authTag = sealed.slice(sealed.length - SYMMETRIC_AUTH_SIZE);\n\n return [ciphertext, authTag];\n}\n\n/**\n * Decrypt data using ChaCha20-Poly1305 AEAD cipher.\n *\n * @param ciphertext - The encrypted data\n * @param key - 32-byte encryption key (must match key used for encryption)\n * @param nonce - 12-byte nonce (must match nonce used for encryption)\n * @param authTag - 16-byte authentication tag from encryption\n * @returns Decrypted plaintext\n * @throws {CryptoError} If key/nonce/authTag sizes are invalid\n * @throws {CryptoError} If authentication fails (tampered data or wrong key/nonce)\n */\nexport function aeadChaCha20Poly1305Decrypt(\n ciphertext: Uint8Array,\n key: Uint8Array,\n nonce: Uint8Array,\n authTag: Uint8Array,\n): Uint8Array {\n return aeadChaCha20Poly1305DecryptWithAad(ciphertext, key, nonce, new Uint8Array(0), authTag);\n}\n\n/**\n * Decrypt data using ChaCha20-Poly1305 AEAD cipher with additional authenticated data.\n *\n * @param ciphertext - The encrypted data\n * @param key - 32-byte encryption key (must match key used for encryption)\n * @param nonce - 12-byte nonce (must match nonce used for encryption)\n * @param aad - Additional authenticated data (must exactly match AAD used for encryption)\n * @param authTag - 16-byte authentication tag from encryption\n * @returns Decrypted plaintext\n * @throws {CryptoError} If key/nonce/authTag sizes are invalid\n * @throws {CryptoError} If authentication fails (tampered data, wrong key/nonce, or AAD mismatch)\n */\nexport function aeadChaCha20Poly1305DecryptWithAad(\n ciphertext: Uint8Array,\n key: Uint8Array,\n nonce: Uint8Array,\n aad: Uint8Array,\n authTag: Uint8Array,\n): Uint8Array {\n if (key.length !== SYMMETRIC_KEY_SIZE) {\n throw CryptoError.invalidParameter(`Key must be ${SYMMETRIC_KEY_SIZE} bytes`);\n }\n if (nonce.length !== SYMMETRIC_NONCE_SIZE) {\n throw CryptoError.invalidParameter(`Nonce must be ${SYMMETRIC_NONCE_SIZE} bytes`);\n }\n if (authTag.length !== SYMMETRIC_AUTH_SIZE) {\n throw CryptoError.invalidParameter(`Auth tag must be ${SYMMETRIC_AUTH_SIZE} bytes`);\n }\n\n // Combine ciphertext and auth tag for decryption\n const sealed = new Uint8Array(ciphertext.length + authTag.length);\n sealed.set(ciphertext);\n sealed.set(authTag, ciphertext.length);\n\n try {\n const cipher = chacha20poly1305(key, nonce, aad);\n return cipher.decrypt(sealed);\n } catch (error) {\n // Preserve the original error for debugging while wrapping in our error type\n const aeadError = new AeadError(\n `Decryption failed: ${error instanceof Error ? error.message : \"authentication error\"}`,\n );\n throw CryptoError.aead(aeadError);\n }\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/public_key_encryption.rs\n\nimport { x25519 } from \"@noble/curves/ed25519.js\";\nimport type { RandomNumberGenerator } from \"@bcts/rand\";\nimport { hkdfHmacSha256 } from \"./hash.js\";\n\n// Constants\nexport const GENERIC_PRIVATE_KEY_SIZE = 32;\nexport const GENERIC_PUBLIC_KEY_SIZE = 32;\nexport const X25519_PRIVATE_KEY_SIZE = 32;\nexport const X25519_PUBLIC_KEY_SIZE = 32;\n\n/**\n * Derive an X25519 agreement private key from key material.\n * Uses HKDF with \"agreement\" as domain separation salt.\n */\nexport function deriveAgreementPrivateKey(keyMaterial: Uint8Array): Uint8Array {\n const salt = new TextEncoder().encode(\"agreement\");\n return hkdfHmacSha256(keyMaterial, salt, X25519_PRIVATE_KEY_SIZE);\n}\n\n/**\n * Derive a signing private key from key material.\n * Uses HKDF with \"signing\" as domain separation salt.\n */\nexport function deriveSigningPrivateKey(keyMaterial: Uint8Array): Uint8Array {\n const salt = new TextEncoder().encode(\"signing\");\n return hkdfHmacSha256(keyMaterial, salt, 32);\n}\n\n/**\n * Generate a new random X25519 private key.\n */\nexport function x25519NewPrivateKeyUsing(rng: RandomNumberGenerator): Uint8Array {\n return rng.randomData(X25519_PRIVATE_KEY_SIZE);\n}\n\n/**\n * Derive an X25519 public key from a private key.\n */\nexport function x25519PublicKeyFromPrivateKey(privateKey: Uint8Array): Uint8Array {\n if (privateKey.length !== X25519_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${X25519_PRIVATE_KEY_SIZE} bytes`);\n }\n return x25519.getPublicKey(privateKey);\n}\n\n// Symmetric key size for the derived shared key\nconst SYMMETRIC_KEY_SIZE = 32;\n\n/**\n * Compute a shared symmetric key using X25519 key agreement (ECDH).\n *\n * This function performs X25519 Diffie-Hellman key agreement and then\n * derives a symmetric key using HKDF-SHA256 with \"agreement\" as the salt.\n * This matches the Rust bc-crypto implementation for cross-platform compatibility.\n *\n * @param x25519Private - 32-byte X25519 private key\n * @param x25519Public - 32-byte X25519 public key from the other party\n * @returns 32-byte derived symmetric key\n * @throws {Error} If private key is not 32 bytes or public key is not 32 bytes\n */\nexport function x25519SharedKey(x25519Private: Uint8Array, x25519Public: Uint8Array): Uint8Array {\n if (x25519Private.length !== X25519_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${X25519_PRIVATE_KEY_SIZE} bytes`);\n }\n if (x25519Public.length !== X25519_PUBLIC_KEY_SIZE) {\n throw new Error(`Public key must be ${X25519_PUBLIC_KEY_SIZE} bytes`);\n }\n // Perform raw X25519 Diffie-Hellman\n const rawSharedSecret = x25519.getSharedSecret(x25519Private, x25519Public);\n // Derive symmetric key using HKDF with \"agreement\" salt (matches Rust implementation)\n const salt = new TextEncoder().encode(\"agreement\");\n return hkdfHmacSha256(rawSharedSecret, salt, SYMMETRIC_KEY_SIZE);\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/ecdsa_keys.rs\n\nimport { secp256k1 } from \"@noble/curves/secp256k1.js\";\nimport type { RandomNumberGenerator } from \"@bcts/rand\";\nimport { hkdfHmacSha256 } from \"./hash.js\";\n\n// Constants\nexport const ECDSA_PRIVATE_KEY_SIZE = 32;\nexport const ECDSA_PUBLIC_KEY_SIZE = 33; // Compressed\nexport const ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE = 65;\nexport const ECDSA_MESSAGE_HASH_SIZE = 32;\nexport const ECDSA_SIGNATURE_SIZE = 64;\nexport const SCHNORR_PUBLIC_KEY_SIZE = 32; // x-only\n\n/**\n * Generate a new random ECDSA private key using secp256k1.\n *\n * Note: Unlike some implementations, this directly returns the random bytes\n * without validation. The secp256k1 library will handle any edge cases when\n * the key is used.\n */\nexport function ecdsaNewPrivateKeyUsing(rng: RandomNumberGenerator): Uint8Array {\n return rng.randomData(ECDSA_PRIVATE_KEY_SIZE);\n}\n\n/**\n * Derive a compressed ECDSA public key from a private key.\n */\nexport function ecdsaPublicKeyFromPrivateKey(privateKey: Uint8Array): Uint8Array {\n if (privateKey.length !== ECDSA_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);\n }\n return secp256k1.getPublicKey(privateKey, true); // true = compressed\n}\n\n/**\n * Decompress a compressed public key to uncompressed format.\n */\nexport function ecdsaDecompressPublicKey(compressed: Uint8Array): Uint8Array {\n if (compressed.length !== ECDSA_PUBLIC_KEY_SIZE) {\n throw new Error(`Compressed public key must be ${ECDSA_PUBLIC_KEY_SIZE} bytes`);\n }\n const point = secp256k1.Point.fromBytes(compressed);\n return point.toBytes(false); // false = uncompressed\n}\n\n/**\n * Compress an uncompressed public key.\n */\nexport function ecdsaCompressPublicKey(uncompressed: Uint8Array): Uint8Array {\n if (uncompressed.length !== ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE) {\n throw new Error(`Uncompressed public key must be ${ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE} bytes`);\n }\n const point = secp256k1.Point.fromBytes(uncompressed);\n return point.toBytes(true); // true = compressed\n}\n\n/**\n * Derive an ECDSA private key from key material using HKDF.\n *\n * Note: This directly returns the HKDF output without validation,\n * matching the Rust reference implementation behavior.\n */\nexport function ecdsaDerivePrivateKey(keyMaterial: Uint8Array): Uint8Array {\n const salt = new TextEncoder().encode(\"signing\");\n return hkdfHmacSha256(keyMaterial, salt, ECDSA_PRIVATE_KEY_SIZE);\n}\n\n/**\n * Extract the x-only (Schnorr) public key from a private key.\n * This is used for BIP-340 Schnorr signatures.\n */\nexport function schnorrPublicKeyFromPrivateKey(privateKey: Uint8Array): Uint8Array {\n if (privateKey.length !== ECDSA_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);\n }\n // Get the full public key and extract just the x-coordinate\n const fullPubKey = secp256k1.getPublicKey(privateKey, false); // uncompressed\n // Skip the 0x04 prefix and take only x-coordinate (first 32 bytes after prefix)\n return fullPubKey.slice(1, 33);\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/ecdsa_signing.rs\n\nimport { secp256k1 } from \"@noble/curves/secp256k1.js\";\nimport { doubleSha256 } from \"./hash.js\";\nimport {\n ECDSA_PRIVATE_KEY_SIZE,\n ECDSA_PUBLIC_KEY_SIZE,\n ECDSA_SIGNATURE_SIZE,\n} from \"./ecdsa-keys.js\";\n\n/**\n * Sign a message using ECDSA with secp256k1.\n *\n * The message is hashed with double SHA-256 before signing (Bitcoin standard).\n *\n * **Security Note**: The private key must be kept secret. ECDSA requires\n * cryptographically secure random nonces internally; this is handled by\n * the underlying library using RFC 6979 deterministic nonces.\n *\n * @param privateKey - 32-byte secp256k1 private key\n * @param message - Message to sign (any length, will be double-SHA256 hashed)\n * @returns 64-byte compact signature (r || s format)\n * @throws {Error} If private key is not 32 bytes\n */\nexport function ecdsaSign(privateKey: Uint8Array, message: Uint8Array): Uint8Array {\n if (privateKey.length !== ECDSA_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);\n }\n\n const messageHash = doubleSha256(message);\n // prehash: false because we already hashed the message with doubleSha256\n return secp256k1.sign(messageHash, privateKey, { prehash: false });\n}\n\n/**\n * Verify an ECDSA signature with secp256k1.\n *\n * The message is hashed with double SHA-256 before verification (Bitcoin standard).\n *\n * @param publicKey - 33-byte compressed secp256k1 public key\n * @param signature - 64-byte compact signature (r || s format)\n * @param message - Original message that was signed\n * @returns `true` if signature is valid, `false` if signature verification fails\n * @throws {Error} If public key is not 33 bytes or signature is not 64 bytes\n */\nexport function ecdsaVerify(\n publicKey: Uint8Array,\n signature: Uint8Array,\n message: Uint8Array,\n): boolean {\n if (publicKey.length !== ECDSA_PUBLIC_KEY_SIZE) {\n throw new Error(`Public key must be ${ECDSA_PUBLIC_KEY_SIZE} bytes`);\n }\n if (signature.length !== ECDSA_SIGNATURE_SIZE) {\n throw new Error(`Signature must be ${ECDSA_SIGNATURE_SIZE} bytes`);\n }\n\n try {\n const messageHash = doubleSha256(message);\n // prehash: false because we already hashed the message with doubleSha256\n return secp256k1.verify(signature, messageHash, publicKey, { prehash: false });\n } catch {\n return false;\n }\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/schnorr_signing.rs\n\nimport { schnorr } from \"@noble/curves/secp256k1.js\";\nimport type { RandomNumberGenerator } from \"@bcts/rand\";\nimport { SecureRandomNumberGenerator } from \"@bcts/rand\";\nimport { ECDSA_PRIVATE_KEY_SIZE, SCHNORR_PUBLIC_KEY_SIZE } from \"./ecdsa-keys.js\";\n\n// Constants\nexport const SCHNORR_SIGNATURE_SIZE = 64;\n\n/**\n * Sign a message using Schnorr signature (BIP-340).\n * Uses secure random auxiliary randomness.\n *\n * @param ecdsaPrivateKey - 32-byte private key\n * @param message - Message to sign (not pre-hashed, per BIP-340)\n * @returns 64-byte Schnorr signature\n */\nexport function schnorrSign(ecdsaPrivateKey: Uint8Array, message: Uint8Array): Uint8Array {\n const rng = new SecureRandomNumberGenerator();\n return schnorrSignUsing(ecdsaPrivateKey, message, rng);\n}\n\n/**\n * Sign a message using Schnorr signature with a custom RNG.\n *\n * @param ecdsaPrivateKey - 32-byte private key\n * @param message - Message to sign\n * @param rng - Random number generator for auxiliary randomness\n * @returns 64-byte Schnorr signature\n */\nexport function schnorrSignUsing(\n ecdsaPrivateKey: Uint8Array,\n message: Uint8Array,\n rng: RandomNumberGenerator,\n): Uint8Array {\n const auxRand = rng.randomData(32);\n return schnorrSignWithAuxRand(ecdsaPrivateKey, message, auxRand);\n}\n\n/**\n * Sign a message using Schnorr signature with specific auxiliary randomness.\n * This is useful for deterministic signing in tests.\n *\n * @param ecdsaPrivateKey - 32-byte private key\n * @param message - Message to sign\n * @param auxRand - 32-byte auxiliary randomness (per BIP-340)\n * @returns 64-byte Schnorr signature\n */\nexport function schnorrSignWithAuxRand(\n ecdsaPrivateKey: Uint8Array,\n message: Uint8Array,\n auxRand: Uint8Array,\n): Uint8Array {\n if (ecdsaPrivateKey.length !== ECDSA_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);\n }\n if (auxRand.length !== 32) {\n throw new Error(\"Auxiliary randomness must be 32 bytes\");\n }\n\n return schnorr.sign(message, ecdsaPrivateKey, auxRand);\n}\n\n/**\n * Verify a Schnorr signature (BIP-340).\n *\n * @param schnorrPublicKey - 32-byte x-only public key\n * @param signature - 64-byte Schnorr signature\n * @param message - Original message\n * @returns true if signature is valid\n */\nexport function schnorrVerify(\n schnorrPublicKey: Uint8Array,\n signature: Uint8Array,\n message: Uint8Array,\n): boolean {\n if (schnorrPublicKey.length !== SCHNORR_PUBLIC_KEY_SIZE) {\n throw new Error(`Public key must be ${SCHNORR_PUBLIC_KEY_SIZE} bytes`);\n }\n if (signature.length !== SCHNORR_SIGNATURE_SIZE) {\n throw new Error(`Signature must be ${SCHNORR_SIGNATURE_SIZE} bytes`);\n }\n\n try {\n return schnorr.verify(signature, message, schnorrPublicKey);\n } catch {\n return false;\n }\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/ed25519_signing.rs\n\nimport { ed25519 } from \"@noble/curves/ed25519.js\";\nimport type { RandomNumberGenerator } from \"@bcts/rand\";\n\n// Constants\nexport const ED25519_PUBLIC_KEY_SIZE = 32;\nexport const ED25519_PRIVATE_KEY_SIZE = 32;\nexport const ED25519_SIGNATURE_SIZE = 64;\n\n/**\n * Generate a new random Ed25519 private key.\n */\nexport function ed25519NewPrivateKeyUsing(rng: RandomNumberGenerator): Uint8Array {\n return rng.randomData(ED25519_PRIVATE_KEY_SIZE);\n}\n\n/**\n * Derive an Ed25519 public key from a private key.\n */\nexport function ed25519PublicKeyFromPrivateKey(privateKey: Uint8Array): Uint8Array {\n if (privateKey.length !== ED25519_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ED25519_PRIVATE_KEY_SIZE} bytes`);\n }\n return ed25519.getPublicKey(privateKey);\n}\n\n/**\n * Sign a message using Ed25519.\n *\n * **Security Note**: The private key must be kept secret. The same private key\n * can safely sign multiple messages.\n *\n * @param privateKey - 32-byte Ed25519 private key\n * @param message - Message to sign (any length)\n * @returns 64-byte Ed25519 signature\n * @throws {Error} If private key is not 32 bytes\n */\nexport function ed25519Sign(privateKey: Uint8Array, message: Uint8Array): Uint8Array {\n if (privateKey.length !== ED25519_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ED25519_PRIVATE_KEY_SIZE} bytes`);\n }\n return ed25519.sign(message, privateKey);\n}\n\n/**\n * Verify an Ed25519 signature.\n *\n * @param publicKey - 32-byte Ed25519 public key\n * @param message - Original message that was signed\n * @param signature - 64-byte Ed25519 signature\n * @returns `true` if signature is valid, `false` if signature verification fails\n * @throws {Error} If public key is not 32 bytes or signature is not 64 bytes\n */\nexport function ed25519Verify(\n publicKey: Uint8Array,\n message: Uint8Array,\n signature: Uint8Array,\n): boolean {\n if (publicKey.length !== ED25519_PUBLIC_KEY_SIZE) {\n throw new Error(`Public key must be ${ED25519_PUBLIC_KEY_SIZE} bytes`);\n }\n if (signature.length !== ED25519_SIGNATURE_SIZE) {\n throw new Error(`Signature must be ${ED25519_SIGNATURE_SIZE} bytes`);\n }\n\n try {\n return ed25519.verify(signature, message, publicKey);\n } catch {\n return false;\n }\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/scrypt.rs\n\nimport { scrypt as nobleScrypt } from \"@noble/hashes/scrypt.js\";\n\n/**\n * Derive a key using Scrypt with recommended parameters.\n * Uses N=2^15 (32768), r=8, p=1 as recommended defaults.\n *\n * @param password - Password or passphrase\n * @param salt - Salt value\n * @param outputLen - Desired output length\n * @returns Derived key\n */\nexport function scrypt(password: Uint8Array, salt: Uint8Array, outputLen: number): Uint8Array {\n return scryptOpt(password, salt, outputLen, 15, 8, 1);\n}\n\n/**\n * Derive a key using Scrypt with custom parameters.\n *\n * @param password - Password or passphrase\n * @param salt - Salt value\n * @param outputLen - Desired output length\n * @param logN - Log2 of the CPU/memory cost parameter N (must be <64)\n * @param r - Block size parameter (must be >0)\n * @param p - Parallelization parameter (must be >0)\n * @returns Derived key\n */\nexport function scryptOpt(\n password: Uint8Array,\n salt: Uint8Array,\n outputLen: number,\n logN: number,\n r: number,\n p: number,\n): Uint8Array {\n if (logN >= 64) {\n throw new Error(\"logN must be <64\");\n }\n if (r === 0) {\n throw new Error(\"r must be >0\");\n }\n if (p === 0) {\n throw new Error(\"p must be >0\");\n }\n\n const N = 1 << logN; // 2^logN\n\n return nobleScrypt(password, salt, { N, r, p, dkLen: outputLen });\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/argon.rs\n\nimport { argon2id as nobleArgon2id } from \"@noble/hashes/argon2.js\";\n\n/**\n * Derive a key using Argon2id with default parameters.\n * This matches the Rust `argon2id` function signature.\n *\n * @param password - Password or passphrase\n * @param salt - Salt value (must be at least 8 bytes)\n * @param outputLen - Desired output length\n * @returns Derived key\n */\nexport function argon2id(password: Uint8Array, salt: Uint8Array, outputLen: number): Uint8Array {\n // Use default parameters matching Argon2::default() in Rust\n return argon2idHashOpt(password, salt, outputLen, 3, 65536, 4);\n}\n\n/**\n * Derive a key using Argon2id with custom parameters.\n *\n * @param password - Password or passphrase\n * @param salt - Salt value (must be at least 8 bytes)\n * @param outputLen - Desired output length\n * @param iterations - Number of iterations (t)\n * @param memory - Memory in KiB (m)\n * @param parallelism - Degree of parallelism (p)\n * @returns Derived key\n */\nexport function argon2idHashOpt(\n password: Uint8Array,\n salt: Uint8Array,\n outputLen: number,\n iterations: number,\n memory: number,\n parallelism: number,\n): Uint8Array {\n return nobleArgon2id(password, salt, {\n t: iterations,\n m: memory,\n p: parallelism,\n dkLen: outputLen,\n });\n}\n"],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -233,10 +233,10 @@ function aeadChaCha20Poly1305Encrypt(plaintext, key, nonce) {
233
233
  * @throws {CryptoError} If key is not 32 bytes or nonce is not 12 bytes
234
234
  */
235
235
  function aeadChaCha20Poly1305EncryptWithAad(plaintext, key, nonce, aad) {
236
- if (key.length !== SYMMETRIC_KEY_SIZE) throw CryptoError.invalidParameter(`Key must be ${SYMMETRIC_KEY_SIZE} bytes`);
237
- if (nonce.length !== SYMMETRIC_NONCE_SIZE) throw CryptoError.invalidParameter(`Nonce must be ${SYMMETRIC_NONCE_SIZE} bytes`);
236
+ if (key.length !== 32) throw CryptoError.invalidParameter(`Key must be ${32} bytes`);
237
+ if (nonce.length !== 12) throw CryptoError.invalidParameter(`Nonce must be ${12} bytes`);
238
238
  const sealed = chacha20poly1305(key, nonce, aad).encrypt(plaintext);
239
- return [sealed.slice(0, sealed.length - SYMMETRIC_AUTH_SIZE), sealed.slice(sealed.length - SYMMETRIC_AUTH_SIZE)];
239
+ return [sealed.slice(0, sealed.length - 16), sealed.slice(sealed.length - 16)];
240
240
  }
241
241
  /**
242
242
  * Decrypt data using ChaCha20-Poly1305 AEAD cipher.
@@ -265,9 +265,9 @@ function aeadChaCha20Poly1305Decrypt(ciphertext, key, nonce, authTag) {
265
265
  * @throws {CryptoError} If authentication fails (tampered data, wrong key/nonce, or AAD mismatch)
266
266
  */
267
267
  function aeadChaCha20Poly1305DecryptWithAad(ciphertext, key, nonce, aad, authTag) {
268
- if (key.length !== SYMMETRIC_KEY_SIZE) throw CryptoError.invalidParameter(`Key must be ${SYMMETRIC_KEY_SIZE} bytes`);
269
- if (nonce.length !== SYMMETRIC_NONCE_SIZE) throw CryptoError.invalidParameter(`Nonce must be ${SYMMETRIC_NONCE_SIZE} bytes`);
270
- if (authTag.length !== SYMMETRIC_AUTH_SIZE) throw CryptoError.invalidParameter(`Auth tag must be ${SYMMETRIC_AUTH_SIZE} bytes`);
268
+ if (key.length !== 32) throw CryptoError.invalidParameter(`Key must be ${32} bytes`);
269
+ if (nonce.length !== 12) throw CryptoError.invalidParameter(`Nonce must be ${12} bytes`);
270
+ if (authTag.length !== 16) throw CryptoError.invalidParameter(`Auth tag must be ${16} bytes`);
271
271
  const sealed = new Uint8Array(ciphertext.length + authTag.length);
272
272
  sealed.set(ciphertext);
273
273
  sealed.set(authTag, ciphertext.length);
@@ -295,7 +295,7 @@ const X25519_PUBLIC_KEY_SIZE = 32;
295
295
  * Uses HKDF with "agreement" as domain separation salt.
296
296
  */
297
297
  function deriveAgreementPrivateKey(keyMaterial) {
298
- return hkdfHmacSha256(keyMaterial, new TextEncoder().encode("agreement"), X25519_PRIVATE_KEY_SIZE);
298
+ return hkdfHmacSha256(keyMaterial, new TextEncoder().encode("agreement"), 32);
299
299
  }
300
300
  /**
301
301
  * Derive a signing private key from key material.
@@ -308,13 +308,13 @@ function deriveSigningPrivateKey(keyMaterial) {
308
308
  * Generate a new random X25519 private key.
309
309
  */
310
310
  function x25519NewPrivateKeyUsing(rng) {
311
- return rng.randomData(X25519_PRIVATE_KEY_SIZE);
311
+ return rng.randomData(32);
312
312
  }
313
313
  /**
314
314
  * Derive an X25519 public key from a private key.
315
315
  */
316
316
  function x25519PublicKeyFromPrivateKey(privateKey) {
317
- if (privateKey.length !== X25519_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${X25519_PRIVATE_KEY_SIZE} bytes`);
317
+ if (privateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
318
318
  return x25519.getPublicKey(privateKey);
319
319
  }
320
320
  const SYMMETRIC_KEY_SIZE$1 = 32;
@@ -331,8 +331,8 @@ const SYMMETRIC_KEY_SIZE$1 = 32;
331
331
  * @throws {Error} If private key is not 32 bytes or public key is not 32 bytes
332
332
  */
333
333
  function x25519SharedKey(x25519Private, x25519Public) {
334
- if (x25519Private.length !== X25519_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${X25519_PRIVATE_KEY_SIZE} bytes`);
335
- if (x25519Public.length !== X25519_PUBLIC_KEY_SIZE) throw new Error(`Public key must be ${X25519_PUBLIC_KEY_SIZE} bytes`);
334
+ if (x25519Private.length !== 32) throw new Error(`Private key must be ${32} bytes`);
335
+ if (x25519Public.length !== 32) throw new Error(`Public key must be ${32} bytes`);
336
336
  return hkdfHmacSha256(x25519.getSharedSecret(x25519Private, x25519Public), new TextEncoder().encode("agreement"), SYMMETRIC_KEY_SIZE$1);
337
337
  }
338
338
 
@@ -357,27 +357,27 @@ const SCHNORR_PUBLIC_KEY_SIZE = 32;
357
357
  * the key is used.
358
358
  */
359
359
  function ecdsaNewPrivateKeyUsing(rng) {
360
- return rng.randomData(ECDSA_PRIVATE_KEY_SIZE);
360
+ return rng.randomData(32);
361
361
  }
362
362
  /**
363
363
  * Derive a compressed ECDSA public key from a private key.
364
364
  */
365
365
  function ecdsaPublicKeyFromPrivateKey(privateKey) {
366
- if (privateKey.length !== ECDSA_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);
366
+ if (privateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
367
367
  return secp256k1.getPublicKey(privateKey, true);
368
368
  }
369
369
  /**
370
370
  * Decompress a compressed public key to uncompressed format.
371
371
  */
372
372
  function ecdsaDecompressPublicKey(compressed) {
373
- if (compressed.length !== ECDSA_PUBLIC_KEY_SIZE) throw new Error(`Compressed public key must be ${ECDSA_PUBLIC_KEY_SIZE} bytes`);
373
+ if (compressed.length !== 33) throw new Error(`Compressed public key must be ${33} bytes`);
374
374
  return secp256k1.Point.fromBytes(compressed).toBytes(false);
375
375
  }
376
376
  /**
377
377
  * Compress an uncompressed public key.
378
378
  */
379
379
  function ecdsaCompressPublicKey(uncompressed) {
380
- if (uncompressed.length !== ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE) throw new Error(`Uncompressed public key must be ${ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE} bytes`);
380
+ if (uncompressed.length !== 65) throw new Error(`Uncompressed public key must be ${65} bytes`);
381
381
  return secp256k1.Point.fromBytes(uncompressed).toBytes(true);
382
382
  }
383
383
  /**
@@ -387,14 +387,14 @@ function ecdsaCompressPublicKey(uncompressed) {
387
387
  * matching the Rust reference implementation behavior.
388
388
  */
389
389
  function ecdsaDerivePrivateKey(keyMaterial) {
390
- return hkdfHmacSha256(keyMaterial, new TextEncoder().encode("signing"), ECDSA_PRIVATE_KEY_SIZE);
390
+ return hkdfHmacSha256(keyMaterial, new TextEncoder().encode("signing"), 32);
391
391
  }
392
392
  /**
393
393
  * Extract the x-only (Schnorr) public key from a private key.
394
394
  * This is used for BIP-340 Schnorr signatures.
395
395
  */
396
396
  function schnorrPublicKeyFromPrivateKey(privateKey) {
397
- if (privateKey.length !== ECDSA_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);
397
+ if (privateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
398
398
  return secp256k1.getPublicKey(privateKey, false).slice(1, 33);
399
399
  }
400
400
 
@@ -420,7 +420,7 @@ function schnorrPublicKeyFromPrivateKey(privateKey) {
420
420
  * @throws {Error} If private key is not 32 bytes
421
421
  */
422
422
  function ecdsaSign(privateKey, message) {
423
- if (privateKey.length !== ECDSA_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);
423
+ if (privateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
424
424
  const messageHash = doubleSha256(message);
425
425
  return secp256k1.sign(messageHash, privateKey, { prehash: false });
426
426
  }
@@ -436,8 +436,8 @@ function ecdsaSign(privateKey, message) {
436
436
  * @throws {Error} If public key is not 33 bytes or signature is not 64 bytes
437
437
  */
438
438
  function ecdsaVerify(publicKey, signature, message) {
439
- if (publicKey.length !== ECDSA_PUBLIC_KEY_SIZE) throw new Error(`Public key must be ${ECDSA_PUBLIC_KEY_SIZE} bytes`);
440
- if (signature.length !== ECDSA_SIGNATURE_SIZE) throw new Error(`Signature must be ${ECDSA_SIGNATURE_SIZE} bytes`);
439
+ if (publicKey.length !== 33) throw new Error(`Public key must be ${33} bytes`);
440
+ if (signature.length !== 64) throw new Error(`Signature must be ${64} bytes`);
441
441
  try {
442
442
  const messageHash = doubleSha256(message);
443
443
  return secp256k1.verify(signature, messageHash, publicKey, { prehash: false });
@@ -486,7 +486,7 @@ function schnorrSignUsing(ecdsaPrivateKey, message, rng) {
486
486
  * @returns 64-byte Schnorr signature
487
487
  */
488
488
  function schnorrSignWithAuxRand(ecdsaPrivateKey, message, auxRand) {
489
- if (ecdsaPrivateKey.length !== ECDSA_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);
489
+ if (ecdsaPrivateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
490
490
  if (auxRand.length !== 32) throw new Error("Auxiliary randomness must be 32 bytes");
491
491
  return schnorr.sign(message, ecdsaPrivateKey, auxRand);
492
492
  }
@@ -499,8 +499,8 @@ function schnorrSignWithAuxRand(ecdsaPrivateKey, message, auxRand) {
499
499
  * @returns true if signature is valid
500
500
  */
501
501
  function schnorrVerify(schnorrPublicKey, signature, message) {
502
- if (schnorrPublicKey.length !== SCHNORR_PUBLIC_KEY_SIZE) throw new Error(`Public key must be ${SCHNORR_PUBLIC_KEY_SIZE} bytes`);
503
- if (signature.length !== SCHNORR_SIGNATURE_SIZE) throw new Error(`Signature must be ${SCHNORR_SIGNATURE_SIZE} bytes`);
502
+ if (schnorrPublicKey.length !== 32) throw new Error(`Public key must be ${32} bytes`);
503
+ if (signature.length !== 64) throw new Error(`Signature must be ${64} bytes`);
504
504
  try {
505
505
  return schnorr.verify(signature, message, schnorrPublicKey);
506
506
  } catch {
@@ -522,13 +522,13 @@ const ED25519_SIGNATURE_SIZE = 64;
522
522
  * Generate a new random Ed25519 private key.
523
523
  */
524
524
  function ed25519NewPrivateKeyUsing(rng) {
525
- return rng.randomData(ED25519_PRIVATE_KEY_SIZE);
525
+ return rng.randomData(32);
526
526
  }
527
527
  /**
528
528
  * Derive an Ed25519 public key from a private key.
529
529
  */
530
530
  function ed25519PublicKeyFromPrivateKey(privateKey) {
531
- if (privateKey.length !== ED25519_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${ED25519_PRIVATE_KEY_SIZE} bytes`);
531
+ if (privateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
532
532
  return ed25519.getPublicKey(privateKey);
533
533
  }
534
534
  /**
@@ -543,7 +543,7 @@ function ed25519PublicKeyFromPrivateKey(privateKey) {
543
543
  * @throws {Error} If private key is not 32 bytes
544
544
  */
545
545
  function ed25519Sign(privateKey, message) {
546
- if (privateKey.length !== ED25519_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${ED25519_PRIVATE_KEY_SIZE} bytes`);
546
+ if (privateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
547
547
  return ed25519.sign(message, privateKey);
548
548
  }
549
549
  /**
@@ -556,8 +556,8 @@ function ed25519Sign(privateKey, message) {
556
556
  * @throws {Error} If public key is not 32 bytes or signature is not 64 bytes
557
557
  */
558
558
  function ed25519Verify(publicKey, message, signature) {
559
- if (publicKey.length !== ED25519_PUBLIC_KEY_SIZE) throw new Error(`Public key must be ${ED25519_PUBLIC_KEY_SIZE} bytes`);
560
- if (signature.length !== ED25519_SIGNATURE_SIZE) throw new Error(`Signature must be ${ED25519_SIGNATURE_SIZE} bytes`);
559
+ if (publicKey.length !== 32) throw new Error(`Public key must be ${32} bytes`);
560
+ if (signature.length !== 64) throw new Error(`Signature must be ${64} bytes`);
561
561
  try {
562
562
  return ed25519.verify(signature, message, publicKey);
563
563
  } catch {
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["nobleSha256","nobleSha512","SYMMETRIC_KEY_SIZE","nobleScrypt","nobleArgon2id"],"sources":["../src/error.ts","../src/memzero.ts","../src/hash.ts","../src/symmetric-encryption.ts","../src/public-key-encryption.ts","../src/ecdsa-keys.ts","../src/ecdsa-signing.ts","../src/schnorr-signing.ts","../src/ed25519-signing.ts","../src/scrypt.ts","../src/argon.ts"],"sourcesContent":["/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/error.rs\n\n/**\n * AEAD-specific error for authentication failures\n */\nexport class AeadError extends Error {\n constructor(message = \"AEAD authentication failed\") {\n super(message);\n this.name = \"AeadError\";\n }\n}\n\n/**\n * Generic crypto error type\n */\nexport class CryptoError extends Error {\n override readonly cause?: Error | undefined;\n\n constructor(message: string, cause?: Error) {\n super(message);\n this.name = \"CryptoError\";\n this.cause = cause;\n }\n\n /**\n * Create a CryptoError for AEAD authentication failures.\n *\n * @param error - Optional underlying AeadError\n * @returns A CryptoError wrapping the AEAD error\n */\n static aead(error?: AeadError): CryptoError {\n return new CryptoError(\"AEAD error\", error ?? new AeadError());\n }\n\n /**\n * Create a CryptoError for invalid parameter values.\n *\n * @param message - Description of the invalid parameter\n * @returns A CryptoError describing the invalid parameter\n */\n static invalidParameter(message: string): CryptoError {\n return new CryptoError(`Invalid parameter: ${message}`);\n }\n}\n\n/**\n * Result type for crypto operations (using standard Error)\n */\nexport type CryptoResult<T> = T;\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/memzero.rs\n\n/**\n * Securely zero out a typed array.\n *\n * **IMPORTANT: This is a best-effort implementation.** Unlike the Rust reference\n * implementation which uses `std::ptr::write_volatile()` for guaranteed volatile\n * writes, JavaScript engines and JIT compilers can still potentially optimize\n * away these zeroing operations. The check at the end helps prevent optimization,\n * but it is not foolproof.\n *\n * For truly sensitive cryptographic operations, consider using the Web Crypto API's\n * `crypto.subtle` with non-extractable keys when possible, as it provides stronger\n * guarantees than what can be achieved with pure JavaScript.\n *\n * This function attempts to prevent the compiler from optimizing away\n * the zeroing operation by using a verification check after the zeroing loop.\n */\nexport function memzero(data: Uint8Array | Uint32Array): void {\n const len = data.length;\n for (let i = 0; i < len; i++) {\n data[i] = 0;\n }\n // Force a side effect to prevent optimization\n if (data.length > 0 && data[0] !== 0) {\n throw new Error(\"memzero failed\");\n }\n}\n\n/**\n * Securely zero out an array of Uint8Arrays.\n */\nexport function memzeroVecVecU8(arrays: Uint8Array[]): void {\n for (const arr of arrays) {\n memzero(arr);\n }\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/hash.rs\n\nimport { sha256 as nobleSha256, sha512 as nobleSha512 } from \"@noble/hashes/sha2.js\";\nimport { hmac } from \"@noble/hashes/hmac.js\";\nimport { pbkdf2 } from \"@noble/hashes/pbkdf2.js\";\nimport { hkdf } from \"@noble/hashes/hkdf.js\";\n\n// Constants\nexport const CRC32_SIZE = 4;\nexport const SHA256_SIZE = 32;\nexport const SHA512_SIZE = 64;\n\n// CRC-32 lookup table (IEEE polynomial 0xedb88320)\nconst CRC32_TABLE = new Uint32Array(256);\nfor (let i = 0; i < 256; i++) {\n let crc = i;\n for (let j = 0; j < 8; j++) {\n crc = (crc & 1) !== 0 ? (crc >>> 1) ^ 0xedb88320 : crc >>> 1;\n }\n CRC32_TABLE[i] = crc >>> 0;\n}\n\n/**\n * Calculate CRC-32 checksum\n */\nexport function crc32(data: Uint8Array): number {\n let crc = 0xffffffff;\n for (const byte of data) {\n crc = CRC32_TABLE[(crc ^ byte) & 0xff] ^ (crc >>> 8);\n }\n return (crc ^ 0xffffffff) >>> 0;\n}\n\n/**\n * Calculate CRC-32 checksum and return as a 4-byte big-endian array\n */\nexport function crc32Data(data: Uint8Array): Uint8Array {\n return crc32DataOpt(data, false);\n}\n\n/**\n * Calculate CRC-32 checksum and return as a 4-byte array\n * @param data - Input data\n * @param littleEndian - If true, returns little-endian; otherwise big-endian\n */\nexport function crc32DataOpt(data: Uint8Array, littleEndian: boolean): Uint8Array {\n const checksum = crc32(data);\n const result = new Uint8Array(4);\n const view = new DataView(result.buffer);\n view.setUint32(0, checksum, littleEndian);\n return result;\n}\n\n/**\n * Calculate SHA-256 hash\n */\nexport function sha256(data: Uint8Array): Uint8Array {\n return nobleSha256(data);\n}\n\n/**\n * Calculate double SHA-256 hash (SHA-256 of SHA-256)\n * This is the standard Bitcoin hashing function\n */\nexport function doubleSha256(message: Uint8Array): Uint8Array {\n return sha256(sha256(message));\n}\n\n/**\n * Calculate SHA-512 hash\n */\nexport function sha512(data: Uint8Array): Uint8Array {\n return nobleSha512(data);\n}\n\n/**\n * Calculate HMAC-SHA-256\n */\nexport function hmacSha256(key: Uint8Array, message: Uint8Array): Uint8Array {\n return hmac(nobleSha256, key, message);\n}\n\n/**\n * Calculate HMAC-SHA-512\n */\nexport function hmacSha512(key: Uint8Array, message: Uint8Array): Uint8Array {\n return hmac(nobleSha512, key, message);\n}\n\n/**\n * Derive a key using PBKDF2 with HMAC-SHA-256\n */\nexport function pbkdf2HmacSha256(\n password: Uint8Array,\n salt: Uint8Array,\n iterations: number,\n keyLen: number,\n): Uint8Array {\n return pbkdf2(nobleSha256, password, salt, { c: iterations, dkLen: keyLen });\n}\n\n/**\n * Derive a key using PBKDF2 with HMAC-SHA-512\n */\nexport function pbkdf2HmacSha512(\n password: Uint8Array,\n salt: Uint8Array,\n iterations: number,\n keyLen: number,\n): Uint8Array {\n return pbkdf2(nobleSha512, password, salt, { c: iterations, dkLen: keyLen });\n}\n\n/**\n * Derive a key using HKDF with HMAC-SHA-256\n */\nexport function hkdfHmacSha256(\n keyMaterial: Uint8Array,\n salt: Uint8Array,\n keyLen: number,\n): Uint8Array {\n return hkdf(nobleSha256, keyMaterial, salt, undefined, keyLen);\n}\n\n/**\n * Derive a key using HKDF with HMAC-SHA-512\n */\nexport function hkdfHmacSha512(\n keyMaterial: Uint8Array,\n salt: Uint8Array,\n keyLen: number,\n): Uint8Array {\n return hkdf(nobleSha512, keyMaterial, salt, undefined, keyLen);\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/symmetric_encryption.rs\n\nimport { chacha20poly1305 } from \"@noble/ciphers/chacha.js\";\nimport { CryptoError, AeadError } from \"./error.js\";\n\n// Constants\nexport const SYMMETRIC_KEY_SIZE = 32;\nexport const SYMMETRIC_NONCE_SIZE = 12;\nexport const SYMMETRIC_AUTH_SIZE = 16;\n\n/**\n * Encrypt data using ChaCha20-Poly1305 AEAD cipher.\n *\n * **Security Warning**: The nonce MUST be unique for every encryption operation\n * with the same key. Reusing a nonce completely breaks the security of the\n * encryption scheme and can reveal plaintext.\n *\n * @param plaintext - The data to encrypt\n * @param key - 32-byte encryption key\n * @param nonce - 12-byte nonce (MUST be unique per encryption with the same key)\n * @returns Tuple of [ciphertext, authTag] where authTag is 16 bytes\n * @throws {CryptoError} If key is not 32 bytes or nonce is not 12 bytes\n */\nexport function aeadChaCha20Poly1305Encrypt(\n plaintext: Uint8Array,\n key: Uint8Array,\n nonce: Uint8Array,\n): [Uint8Array, Uint8Array] {\n return aeadChaCha20Poly1305EncryptWithAad(plaintext, key, nonce, new Uint8Array(0));\n}\n\n/**\n * Encrypt data using ChaCha20-Poly1305 AEAD cipher with additional authenticated data.\n *\n * **Security Warning**: The nonce MUST be unique for every encryption operation\n * with the same key. Reusing a nonce completely breaks the security of the\n * encryption scheme and can reveal plaintext.\n *\n * @param plaintext - The data to encrypt\n * @param key - 32-byte encryption key\n * @param nonce - 12-byte nonce (MUST be unique per encryption with the same key)\n * @param aad - Additional authenticated data (not encrypted, but integrity-protected)\n * @returns Tuple of [ciphertext, authTag] where authTag is 16 bytes\n * @throws {CryptoError} If key is not 32 bytes or nonce is not 12 bytes\n */\nexport function aeadChaCha20Poly1305EncryptWithAad(\n plaintext: Uint8Array,\n key: Uint8Array,\n nonce: Uint8Array,\n aad: Uint8Array,\n): [Uint8Array, Uint8Array] {\n if (key.length !== SYMMETRIC_KEY_SIZE) {\n throw CryptoError.invalidParameter(`Key must be ${SYMMETRIC_KEY_SIZE} bytes`);\n }\n if (nonce.length !== SYMMETRIC_NONCE_SIZE) {\n throw CryptoError.invalidParameter(`Nonce must be ${SYMMETRIC_NONCE_SIZE} bytes`);\n }\n\n const cipher = chacha20poly1305(key, nonce, aad);\n const sealed = cipher.encrypt(plaintext);\n\n // The sealed output contains ciphertext + 16-byte auth tag\n const ciphertext = sealed.slice(0, sealed.length - SYMMETRIC_AUTH_SIZE);\n const authTag = sealed.slice(sealed.length - SYMMETRIC_AUTH_SIZE);\n\n return [ciphertext, authTag];\n}\n\n/**\n * Decrypt data using ChaCha20-Poly1305 AEAD cipher.\n *\n * @param ciphertext - The encrypted data\n * @param key - 32-byte encryption key (must match key used for encryption)\n * @param nonce - 12-byte nonce (must match nonce used for encryption)\n * @param authTag - 16-byte authentication tag from encryption\n * @returns Decrypted plaintext\n * @throws {CryptoError} If key/nonce/authTag sizes are invalid\n * @throws {CryptoError} If authentication fails (tampered data or wrong key/nonce)\n */\nexport function aeadChaCha20Poly1305Decrypt(\n ciphertext: Uint8Array,\n key: Uint8Array,\n nonce: Uint8Array,\n authTag: Uint8Array,\n): Uint8Array {\n return aeadChaCha20Poly1305DecryptWithAad(ciphertext, key, nonce, new Uint8Array(0), authTag);\n}\n\n/**\n * Decrypt data using ChaCha20-Poly1305 AEAD cipher with additional authenticated data.\n *\n * @param ciphertext - The encrypted data\n * @param key - 32-byte encryption key (must match key used for encryption)\n * @param nonce - 12-byte nonce (must match nonce used for encryption)\n * @param aad - Additional authenticated data (must exactly match AAD used for encryption)\n * @param authTag - 16-byte authentication tag from encryption\n * @returns Decrypted plaintext\n * @throws {CryptoError} If key/nonce/authTag sizes are invalid\n * @throws {CryptoError} If authentication fails (tampered data, wrong key/nonce, or AAD mismatch)\n */\nexport function aeadChaCha20Poly1305DecryptWithAad(\n ciphertext: Uint8Array,\n key: Uint8Array,\n nonce: Uint8Array,\n aad: Uint8Array,\n authTag: Uint8Array,\n): Uint8Array {\n if (key.length !== SYMMETRIC_KEY_SIZE) {\n throw CryptoError.invalidParameter(`Key must be ${SYMMETRIC_KEY_SIZE} bytes`);\n }\n if (nonce.length !== SYMMETRIC_NONCE_SIZE) {\n throw CryptoError.invalidParameter(`Nonce must be ${SYMMETRIC_NONCE_SIZE} bytes`);\n }\n if (authTag.length !== SYMMETRIC_AUTH_SIZE) {\n throw CryptoError.invalidParameter(`Auth tag must be ${SYMMETRIC_AUTH_SIZE} bytes`);\n }\n\n // Combine ciphertext and auth tag for decryption\n const sealed = new Uint8Array(ciphertext.length + authTag.length);\n sealed.set(ciphertext);\n sealed.set(authTag, ciphertext.length);\n\n try {\n const cipher = chacha20poly1305(key, nonce, aad);\n return cipher.decrypt(sealed);\n } catch (error) {\n // Preserve the original error for debugging while wrapping in our error type\n const aeadError = new AeadError(\n `Decryption failed: ${error instanceof Error ? error.message : \"authentication error\"}`,\n );\n throw CryptoError.aead(aeadError);\n }\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/public_key_encryption.rs\n\nimport { x25519 } from \"@noble/curves/ed25519.js\";\nimport type { RandomNumberGenerator } from \"@bcts/rand\";\nimport { hkdfHmacSha256 } from \"./hash.js\";\n\n// Constants\nexport const GENERIC_PRIVATE_KEY_SIZE = 32;\nexport const GENERIC_PUBLIC_KEY_SIZE = 32;\nexport const X25519_PRIVATE_KEY_SIZE = 32;\nexport const X25519_PUBLIC_KEY_SIZE = 32;\n\n/**\n * Derive an X25519 agreement private key from key material.\n * Uses HKDF with \"agreement\" as domain separation salt.\n */\nexport function deriveAgreementPrivateKey(keyMaterial: Uint8Array): Uint8Array {\n const salt = new TextEncoder().encode(\"agreement\");\n return hkdfHmacSha256(keyMaterial, salt, X25519_PRIVATE_KEY_SIZE);\n}\n\n/**\n * Derive a signing private key from key material.\n * Uses HKDF with \"signing\" as domain separation salt.\n */\nexport function deriveSigningPrivateKey(keyMaterial: Uint8Array): Uint8Array {\n const salt = new TextEncoder().encode(\"signing\");\n return hkdfHmacSha256(keyMaterial, salt, 32);\n}\n\n/**\n * Generate a new random X25519 private key.\n */\nexport function x25519NewPrivateKeyUsing(rng: RandomNumberGenerator): Uint8Array {\n return rng.randomData(X25519_PRIVATE_KEY_SIZE);\n}\n\n/**\n * Derive an X25519 public key from a private key.\n */\nexport function x25519PublicKeyFromPrivateKey(privateKey: Uint8Array): Uint8Array {\n if (privateKey.length !== X25519_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${X25519_PRIVATE_KEY_SIZE} bytes`);\n }\n return x25519.getPublicKey(privateKey);\n}\n\n// Symmetric key size for the derived shared key\nconst SYMMETRIC_KEY_SIZE = 32;\n\n/**\n * Compute a shared symmetric key using X25519 key agreement (ECDH).\n *\n * This function performs X25519 Diffie-Hellman key agreement and then\n * derives a symmetric key using HKDF-SHA256 with \"agreement\" as the salt.\n * This matches the Rust bc-crypto implementation for cross-platform compatibility.\n *\n * @param x25519Private - 32-byte X25519 private key\n * @param x25519Public - 32-byte X25519 public key from the other party\n * @returns 32-byte derived symmetric key\n * @throws {Error} If private key is not 32 bytes or public key is not 32 bytes\n */\nexport function x25519SharedKey(x25519Private: Uint8Array, x25519Public: Uint8Array): Uint8Array {\n if (x25519Private.length !== X25519_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${X25519_PRIVATE_KEY_SIZE} bytes`);\n }\n if (x25519Public.length !== X25519_PUBLIC_KEY_SIZE) {\n throw new Error(`Public key must be ${X25519_PUBLIC_KEY_SIZE} bytes`);\n }\n // Perform raw X25519 Diffie-Hellman\n const rawSharedSecret = x25519.getSharedSecret(x25519Private, x25519Public);\n // Derive symmetric key using HKDF with \"agreement\" salt (matches Rust implementation)\n const salt = new TextEncoder().encode(\"agreement\");\n return hkdfHmacSha256(rawSharedSecret, salt, SYMMETRIC_KEY_SIZE);\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/ecdsa_keys.rs\n\nimport { secp256k1 } from \"@noble/curves/secp256k1.js\";\nimport type { RandomNumberGenerator } from \"@bcts/rand\";\nimport { hkdfHmacSha256 } from \"./hash.js\";\n\n// Constants\nexport const ECDSA_PRIVATE_KEY_SIZE = 32;\nexport const ECDSA_PUBLIC_KEY_SIZE = 33; // Compressed\nexport const ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE = 65;\nexport const ECDSA_MESSAGE_HASH_SIZE = 32;\nexport const ECDSA_SIGNATURE_SIZE = 64;\nexport const SCHNORR_PUBLIC_KEY_SIZE = 32; // x-only\n\n/**\n * Generate a new random ECDSA private key using secp256k1.\n *\n * Note: Unlike some implementations, this directly returns the random bytes\n * without validation. The secp256k1 library will handle any edge cases when\n * the key is used.\n */\nexport function ecdsaNewPrivateKeyUsing(rng: RandomNumberGenerator): Uint8Array {\n return rng.randomData(ECDSA_PRIVATE_KEY_SIZE);\n}\n\n/**\n * Derive a compressed ECDSA public key from a private key.\n */\nexport function ecdsaPublicKeyFromPrivateKey(privateKey: Uint8Array): Uint8Array {\n if (privateKey.length !== ECDSA_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);\n }\n return secp256k1.getPublicKey(privateKey, true); // true = compressed\n}\n\n/**\n * Decompress a compressed public key to uncompressed format.\n */\nexport function ecdsaDecompressPublicKey(compressed: Uint8Array): Uint8Array {\n if (compressed.length !== ECDSA_PUBLIC_KEY_SIZE) {\n throw new Error(`Compressed public key must be ${ECDSA_PUBLIC_KEY_SIZE} bytes`);\n }\n const point = secp256k1.Point.fromBytes(compressed);\n return point.toBytes(false); // false = uncompressed\n}\n\n/**\n * Compress an uncompressed public key.\n */\nexport function ecdsaCompressPublicKey(uncompressed: Uint8Array): Uint8Array {\n if (uncompressed.length !== ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE) {\n throw new Error(`Uncompressed public key must be ${ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE} bytes`);\n }\n const point = secp256k1.Point.fromBytes(uncompressed);\n return point.toBytes(true); // true = compressed\n}\n\n/**\n * Derive an ECDSA private key from key material using HKDF.\n *\n * Note: This directly returns the HKDF output without validation,\n * matching the Rust reference implementation behavior.\n */\nexport function ecdsaDerivePrivateKey(keyMaterial: Uint8Array): Uint8Array {\n const salt = new TextEncoder().encode(\"signing\");\n return hkdfHmacSha256(keyMaterial, salt, ECDSA_PRIVATE_KEY_SIZE);\n}\n\n/**\n * Extract the x-only (Schnorr) public key from a private key.\n * This is used for BIP-340 Schnorr signatures.\n */\nexport function schnorrPublicKeyFromPrivateKey(privateKey: Uint8Array): Uint8Array {\n if (privateKey.length !== ECDSA_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);\n }\n // Get the full public key and extract just the x-coordinate\n const fullPubKey = secp256k1.getPublicKey(privateKey, false); // uncompressed\n // Skip the 0x04 prefix and take only x-coordinate (first 32 bytes after prefix)\n return fullPubKey.slice(1, 33);\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/ecdsa_signing.rs\n\nimport { secp256k1 } from \"@noble/curves/secp256k1.js\";\nimport { doubleSha256 } from \"./hash.js\";\nimport {\n ECDSA_PRIVATE_KEY_SIZE,\n ECDSA_PUBLIC_KEY_SIZE,\n ECDSA_SIGNATURE_SIZE,\n} from \"./ecdsa-keys.js\";\n\n/**\n * Sign a message using ECDSA with secp256k1.\n *\n * The message is hashed with double SHA-256 before signing (Bitcoin standard).\n *\n * **Security Note**: The private key must be kept secret. ECDSA requires\n * cryptographically secure random nonces internally; this is handled by\n * the underlying library using RFC 6979 deterministic nonces.\n *\n * @param privateKey - 32-byte secp256k1 private key\n * @param message - Message to sign (any length, will be double-SHA256 hashed)\n * @returns 64-byte compact signature (r || s format)\n * @throws {Error} If private key is not 32 bytes\n */\nexport function ecdsaSign(privateKey: Uint8Array, message: Uint8Array): Uint8Array {\n if (privateKey.length !== ECDSA_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);\n }\n\n const messageHash = doubleSha256(message);\n // prehash: false because we already hashed the message with doubleSha256\n return secp256k1.sign(messageHash, privateKey, { prehash: false });\n}\n\n/**\n * Verify an ECDSA signature with secp256k1.\n *\n * The message is hashed with double SHA-256 before verification (Bitcoin standard).\n *\n * @param publicKey - 33-byte compressed secp256k1 public key\n * @param signature - 64-byte compact signature (r || s format)\n * @param message - Original message that was signed\n * @returns `true` if signature is valid, `false` if signature verification fails\n * @throws {Error} If public key is not 33 bytes or signature is not 64 bytes\n */\nexport function ecdsaVerify(\n publicKey: Uint8Array,\n signature: Uint8Array,\n message: Uint8Array,\n): boolean {\n if (publicKey.length !== ECDSA_PUBLIC_KEY_SIZE) {\n throw new Error(`Public key must be ${ECDSA_PUBLIC_KEY_SIZE} bytes`);\n }\n if (signature.length !== ECDSA_SIGNATURE_SIZE) {\n throw new Error(`Signature must be ${ECDSA_SIGNATURE_SIZE} bytes`);\n }\n\n try {\n const messageHash = doubleSha256(message);\n // prehash: false because we already hashed the message with doubleSha256\n return secp256k1.verify(signature, messageHash, publicKey, { prehash: false });\n } catch {\n return false;\n }\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/schnorr_signing.rs\n\nimport { schnorr } from \"@noble/curves/secp256k1.js\";\nimport type { RandomNumberGenerator } from \"@bcts/rand\";\nimport { SecureRandomNumberGenerator } from \"@bcts/rand\";\nimport { ECDSA_PRIVATE_KEY_SIZE, SCHNORR_PUBLIC_KEY_SIZE } from \"./ecdsa-keys.js\";\n\n// Constants\nexport const SCHNORR_SIGNATURE_SIZE = 64;\n\n/**\n * Sign a message using Schnorr signature (BIP-340).\n * Uses secure random auxiliary randomness.\n *\n * @param ecdsaPrivateKey - 32-byte private key\n * @param message - Message to sign (not pre-hashed, per BIP-340)\n * @returns 64-byte Schnorr signature\n */\nexport function schnorrSign(ecdsaPrivateKey: Uint8Array, message: Uint8Array): Uint8Array {\n const rng = new SecureRandomNumberGenerator();\n return schnorrSignUsing(ecdsaPrivateKey, message, rng);\n}\n\n/**\n * Sign a message using Schnorr signature with a custom RNG.\n *\n * @param ecdsaPrivateKey - 32-byte private key\n * @param message - Message to sign\n * @param rng - Random number generator for auxiliary randomness\n * @returns 64-byte Schnorr signature\n */\nexport function schnorrSignUsing(\n ecdsaPrivateKey: Uint8Array,\n message: Uint8Array,\n rng: RandomNumberGenerator,\n): Uint8Array {\n const auxRand = rng.randomData(32);\n return schnorrSignWithAuxRand(ecdsaPrivateKey, message, auxRand);\n}\n\n/**\n * Sign a message using Schnorr signature with specific auxiliary randomness.\n * This is useful for deterministic signing in tests.\n *\n * @param ecdsaPrivateKey - 32-byte private key\n * @param message - Message to sign\n * @param auxRand - 32-byte auxiliary randomness (per BIP-340)\n * @returns 64-byte Schnorr signature\n */\nexport function schnorrSignWithAuxRand(\n ecdsaPrivateKey: Uint8Array,\n message: Uint8Array,\n auxRand: Uint8Array,\n): Uint8Array {\n if (ecdsaPrivateKey.length !== ECDSA_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);\n }\n if (auxRand.length !== 32) {\n throw new Error(\"Auxiliary randomness must be 32 bytes\");\n }\n\n return schnorr.sign(message, ecdsaPrivateKey, auxRand);\n}\n\n/**\n * Verify a Schnorr signature (BIP-340).\n *\n * @param schnorrPublicKey - 32-byte x-only public key\n * @param signature - 64-byte Schnorr signature\n * @param message - Original message\n * @returns true if signature is valid\n */\nexport function schnorrVerify(\n schnorrPublicKey: Uint8Array,\n signature: Uint8Array,\n message: Uint8Array,\n): boolean {\n if (schnorrPublicKey.length !== SCHNORR_PUBLIC_KEY_SIZE) {\n throw new Error(`Public key must be ${SCHNORR_PUBLIC_KEY_SIZE} bytes`);\n }\n if (signature.length !== SCHNORR_SIGNATURE_SIZE) {\n throw new Error(`Signature must be ${SCHNORR_SIGNATURE_SIZE} bytes`);\n }\n\n try {\n return schnorr.verify(signature, message, schnorrPublicKey);\n } catch {\n return false;\n }\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/ed25519_signing.rs\n\nimport { ed25519 } from \"@noble/curves/ed25519.js\";\nimport type { RandomNumberGenerator } from \"@bcts/rand\";\n\n// Constants\nexport const ED25519_PUBLIC_KEY_SIZE = 32;\nexport const ED25519_PRIVATE_KEY_SIZE = 32;\nexport const ED25519_SIGNATURE_SIZE = 64;\n\n/**\n * Generate a new random Ed25519 private key.\n */\nexport function ed25519NewPrivateKeyUsing(rng: RandomNumberGenerator): Uint8Array {\n return rng.randomData(ED25519_PRIVATE_KEY_SIZE);\n}\n\n/**\n * Derive an Ed25519 public key from a private key.\n */\nexport function ed25519PublicKeyFromPrivateKey(privateKey: Uint8Array): Uint8Array {\n if (privateKey.length !== ED25519_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ED25519_PRIVATE_KEY_SIZE} bytes`);\n }\n return ed25519.getPublicKey(privateKey);\n}\n\n/**\n * Sign a message using Ed25519.\n *\n * **Security Note**: The private key must be kept secret. The same private key\n * can safely sign multiple messages.\n *\n * @param privateKey - 32-byte Ed25519 private key\n * @param message - Message to sign (any length)\n * @returns 64-byte Ed25519 signature\n * @throws {Error} If private key is not 32 bytes\n */\nexport function ed25519Sign(privateKey: Uint8Array, message: Uint8Array): Uint8Array {\n if (privateKey.length !== ED25519_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ED25519_PRIVATE_KEY_SIZE} bytes`);\n }\n return ed25519.sign(message, privateKey);\n}\n\n/**\n * Verify an Ed25519 signature.\n *\n * @param publicKey - 32-byte Ed25519 public key\n * @param message - Original message that was signed\n * @param signature - 64-byte Ed25519 signature\n * @returns `true` if signature is valid, `false` if signature verification fails\n * @throws {Error} If public key is not 32 bytes or signature is not 64 bytes\n */\nexport function ed25519Verify(\n publicKey: Uint8Array,\n message: Uint8Array,\n signature: Uint8Array,\n): boolean {\n if (publicKey.length !== ED25519_PUBLIC_KEY_SIZE) {\n throw new Error(`Public key must be ${ED25519_PUBLIC_KEY_SIZE} bytes`);\n }\n if (signature.length !== ED25519_SIGNATURE_SIZE) {\n throw new Error(`Signature must be ${ED25519_SIGNATURE_SIZE} bytes`);\n }\n\n try {\n return ed25519.verify(signature, message, publicKey);\n } catch {\n return false;\n }\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/scrypt.rs\n\nimport { scrypt as nobleScrypt } from \"@noble/hashes/scrypt.js\";\n\n/**\n * Derive a key using Scrypt with recommended parameters.\n * Uses N=2^15 (32768), r=8, p=1 as recommended defaults.\n *\n * @param password - Password or passphrase\n * @param salt - Salt value\n * @param outputLen - Desired output length\n * @returns Derived key\n */\nexport function scrypt(password: Uint8Array, salt: Uint8Array, outputLen: number): Uint8Array {\n return scryptOpt(password, salt, outputLen, 15, 8, 1);\n}\n\n/**\n * Derive a key using Scrypt with custom parameters.\n *\n * @param password - Password or passphrase\n * @param salt - Salt value\n * @param outputLen - Desired output length\n * @param logN - Log2 of the CPU/memory cost parameter N (must be <64)\n * @param r - Block size parameter (must be >0)\n * @param p - Parallelization parameter (must be >0)\n * @returns Derived key\n */\nexport function scryptOpt(\n password: Uint8Array,\n salt: Uint8Array,\n outputLen: number,\n logN: number,\n r: number,\n p: number,\n): Uint8Array {\n if (logN >= 64) {\n throw new Error(\"logN must be <64\");\n }\n if (r === 0) {\n throw new Error(\"r must be >0\");\n }\n if (p === 0) {\n throw new Error(\"p must be >0\");\n }\n\n const N = 1 << logN; // 2^logN\n\n return nobleScrypt(password, salt, { N, r, p, dkLen: outputLen });\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/argon.rs\n\nimport { argon2id as nobleArgon2id } from \"@noble/hashes/argon2.js\";\n\n/**\n * Derive a key using Argon2id with default parameters.\n * This matches the Rust `argon2id` function signature.\n *\n * @param password - Password or passphrase\n * @param salt - Salt value (must be at least 8 bytes)\n * @param outputLen - Desired output length\n * @returns Derived key\n */\nexport function argon2id(password: Uint8Array, salt: Uint8Array, outputLen: number): Uint8Array {\n // Use default parameters matching Argon2::default() in Rust\n return argon2idHashOpt(password, salt, outputLen, 3, 65536, 4);\n}\n\n/**\n * Derive a key using Argon2id with custom parameters.\n *\n * @param password - Password or passphrase\n * @param salt - Salt value (must be at least 8 bytes)\n * @param outputLen - Desired output length\n * @param iterations - Number of iterations (t)\n * @param memory - Memory in KiB (m)\n * @param parallelism - Degree of parallelism (p)\n * @returns Derived key\n */\nexport function argon2idHashOpt(\n password: Uint8Array,\n salt: Uint8Array,\n outputLen: number,\n iterations: number,\n memory: number,\n parallelism: number,\n): Uint8Array {\n return nobleArgon2id(password, salt, {\n t: iterations,\n m: memory,\n p: parallelism,\n dkLen: outputLen,\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAWA,IAAa,YAAb,cAA+B,MAAM;CACnC,YAAY,UAAU,8BAA8B;AAClD,QAAM,QAAQ;AACd,OAAK,OAAO;;;;;;AAOhB,IAAa,cAAb,MAAa,oBAAoB,MAAM;CACrC,AAAkB;CAElB,YAAY,SAAiB,OAAe;AAC1C,QAAM,QAAQ;AACd,OAAK,OAAO;AACZ,OAAK,QAAQ;;;;;;;;CASf,OAAO,KAAK,OAAgC;AAC1C,SAAO,IAAI,YAAY,cAAc,SAAS,IAAI,WAAW,CAAC;;;;;;;;CAShE,OAAO,iBAAiB,SAA8B;AACpD,SAAO,IAAI,YAAY,sBAAsB,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;ACvB3D,SAAgB,QAAQ,MAAsC;CAC5D,MAAM,MAAM,KAAK;AACjB,MAAK,IAAI,IAAI,GAAG,IAAI,KAAK,IACvB,MAAK,KAAK;AAGZ,KAAI,KAAK,SAAS,KAAK,KAAK,OAAO,EACjC,OAAM,IAAI,MAAM,iBAAiB;;;;;AAOrC,SAAgB,gBAAgB,QAA4B;AAC1D,MAAK,MAAM,OAAO,OAChB,SAAQ,IAAI;;;;;;;;;;AC1BhB,MAAa,aAAa;AAC1B,MAAa,cAAc;AAC3B,MAAa,cAAc;AAG3B,MAAM,cAAc,IAAI,YAAY,IAAI;AACxC,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,KAAK;CAC5B,IAAI,MAAM;AACV,MAAK,IAAI,IAAI,GAAG,IAAI,GAAG,IACrB,QAAO,MAAM,OAAO,IAAK,QAAQ,IAAK,aAAa,QAAQ;AAE7D,aAAY,KAAK,QAAQ;;;;;AAM3B,SAAgB,MAAM,MAA0B;CAC9C,IAAI,MAAM;AACV,MAAK,MAAM,QAAQ,KACjB,OAAM,aAAa,MAAM,QAAQ,OAAS,QAAQ;AAEpD,SAAQ,MAAM,gBAAgB;;;;;AAMhC,SAAgB,UAAU,MAA8B;AACtD,QAAO,aAAa,MAAM,MAAM;;;;;;;AAQlC,SAAgB,aAAa,MAAkB,cAAmC;CAChF,MAAM,WAAW,MAAM,KAAK;CAC5B,MAAM,SAAS,IAAI,WAAW,EAAE;AAEhC,CADa,IAAI,SAAS,OAAO,OAAO,CACnC,UAAU,GAAG,UAAU,aAAa;AACzC,QAAO;;;;;AAMT,SAAgB,OAAO,MAA8B;AACnD,QAAOA,SAAY,KAAK;;;;;;AAO1B,SAAgB,aAAa,SAAiC;AAC5D,QAAO,OAAO,OAAO,QAAQ,CAAC;;;;;AAMhC,SAAgB,OAAO,MAA8B;AACnD,QAAOC,SAAY,KAAK;;;;;AAM1B,SAAgB,WAAW,KAAiB,SAAiC;AAC3E,QAAO,KAAKD,UAAa,KAAK,QAAQ;;;;;AAMxC,SAAgB,WAAW,KAAiB,SAAiC;AAC3E,QAAO,KAAKC,UAAa,KAAK,QAAQ;;;;;AAMxC,SAAgB,iBACd,UACA,MACA,YACA,QACY;AACZ,QAAO,OAAOD,UAAa,UAAU,MAAM;EAAE,GAAG;EAAY,OAAO;EAAQ,CAAC;;;;;AAM9E,SAAgB,iBACd,UACA,MACA,YACA,QACY;AACZ,QAAO,OAAOC,UAAa,UAAU,MAAM;EAAE,GAAG;EAAY,OAAO;EAAQ,CAAC;;;;;AAM9E,SAAgB,eACd,aACA,MACA,QACY;AACZ,QAAO,KAAKD,UAAa,aAAa,MAAM,QAAW,OAAO;;;;;AAMhE,SAAgB,eACd,aACA,MACA,QACY;AACZ,QAAO,KAAKC,UAAa,aAAa,MAAM,QAAW,OAAO;;;;;;;;;;AC9HhE,MAAa,qBAAqB;AAClC,MAAa,uBAAuB;AACpC,MAAa,sBAAsB;;;;;;;;;;;;;;AAenC,SAAgB,4BACd,WACA,KACA,OAC0B;AAC1B,QAAO,mCAAmC,WAAW,KAAK,OAAO,IAAI,WAAW,EAAE,CAAC;;;;;;;;;;;;;;;;AAiBrF,SAAgB,mCACd,WACA,KACA,OACA,KAC0B;AAC1B,KAAI,IAAI,WAAW,mBACjB,OAAM,YAAY,iBAAiB,eAAe,mBAAmB,QAAQ;AAE/E,KAAI,MAAM,WAAW,qBACnB,OAAM,YAAY,iBAAiB,iBAAiB,qBAAqB,QAAQ;CAInF,MAAM,SADS,iBAAiB,KAAK,OAAO,IAAI,CAC1B,QAAQ,UAAU;AAMxC,QAAO,CAHY,OAAO,MAAM,GAAG,OAAO,SAAS,oBAAoB,EACvD,OAAO,MAAM,OAAO,SAAS,oBAAoB,CAErC;;;;;;;;;;;;;AAc9B,SAAgB,4BACd,YACA,KACA,OACA,SACY;AACZ,QAAO,mCAAmC,YAAY,KAAK,OAAO,IAAI,WAAW,EAAE,EAAE,QAAQ;;;;;;;;;;;;;;AAe/F,SAAgB,mCACd,YACA,KACA,OACA,KACA,SACY;AACZ,KAAI,IAAI,WAAW,mBACjB,OAAM,YAAY,iBAAiB,eAAe,mBAAmB,QAAQ;AAE/E,KAAI,MAAM,WAAW,qBACnB,OAAM,YAAY,iBAAiB,iBAAiB,qBAAqB,QAAQ;AAEnF,KAAI,QAAQ,WAAW,oBACrB,OAAM,YAAY,iBAAiB,oBAAoB,oBAAoB,QAAQ;CAIrF,MAAM,SAAS,IAAI,WAAW,WAAW,SAAS,QAAQ,OAAO;AACjE,QAAO,IAAI,WAAW;AACtB,QAAO,IAAI,SAAS,WAAW,OAAO;AAEtC,KAAI;AAEF,SADe,iBAAiB,KAAK,OAAO,IAAI,CAClC,QAAQ,OAAO;UACtB,OAAO;EAEd,MAAM,YAAY,IAAI,UACpB,sBAAsB,iBAAiB,QAAQ,MAAM,UAAU,yBAChE;AACD,QAAM,YAAY,KAAK,UAAU;;;;;;;;;;;AC3HrC,MAAa,2BAA2B;AACxC,MAAa,0BAA0B;AACvC,MAAa,0BAA0B;AACvC,MAAa,yBAAyB;;;;;AAMtC,SAAgB,0BAA0B,aAAqC;AAE7E,QAAO,eAAe,aADT,IAAI,aAAa,CAAC,OAAO,YAAY,EACT,wBAAwB;;;;;;AAOnE,SAAgB,wBAAwB,aAAqC;AAE3E,QAAO,eAAe,aADT,IAAI,aAAa,CAAC,OAAO,UAAU,EACP,GAAG;;;;;AAM9C,SAAgB,yBAAyB,KAAwC;AAC/E,QAAO,IAAI,WAAW,wBAAwB;;;;;AAMhD,SAAgB,8BAA8B,YAAoC;AAChF,KAAI,WAAW,WAAW,wBACxB,OAAM,IAAI,MAAM,uBAAuB,wBAAwB,QAAQ;AAEzE,QAAO,OAAO,aAAa,WAAW;;AAIxC,MAAMC,uBAAqB;;;;;;;;;;;;;AAc3B,SAAgB,gBAAgB,eAA2B,cAAsC;AAC/F,KAAI,cAAc,WAAW,wBAC3B,OAAM,IAAI,MAAM,uBAAuB,wBAAwB,QAAQ;AAEzE,KAAI,aAAa,WAAW,uBAC1B,OAAM,IAAI,MAAM,sBAAsB,uBAAuB,QAAQ;AAMvE,QAAO,eAHiB,OAAO,gBAAgB,eAAe,aAAa,EAE9D,IAAI,aAAa,CAAC,OAAO,YAAY,EACLA,qBAAmB;;;;;;;;;;AClElE,MAAa,yBAAyB;AACtC,MAAa,wBAAwB;AACrC,MAAa,qCAAqC;AAClD,MAAa,0BAA0B;AACvC,MAAa,uBAAuB;AACpC,MAAa,0BAA0B;;;;;;;;AASvC,SAAgB,wBAAwB,KAAwC;AAC9E,QAAO,IAAI,WAAW,uBAAuB;;;;;AAM/C,SAAgB,6BAA6B,YAAoC;AAC/E,KAAI,WAAW,WAAW,uBACxB,OAAM,IAAI,MAAM,uBAAuB,uBAAuB,QAAQ;AAExE,QAAO,UAAU,aAAa,YAAY,KAAK;;;;;AAMjD,SAAgB,yBAAyB,YAAoC;AAC3E,KAAI,WAAW,WAAW,sBACxB,OAAM,IAAI,MAAM,iCAAiC,sBAAsB,QAAQ;AAGjF,QADc,UAAU,MAAM,UAAU,WAAW,CACtC,QAAQ,MAAM;;;;;AAM7B,SAAgB,uBAAuB,cAAsC;AAC3E,KAAI,aAAa,WAAW,mCAC1B,OAAM,IAAI,MAAM,mCAAmC,mCAAmC,QAAQ;AAGhG,QADc,UAAU,MAAM,UAAU,aAAa,CACxC,QAAQ,KAAK;;;;;;;;AAS5B,SAAgB,sBAAsB,aAAqC;AAEzE,QAAO,eAAe,aADT,IAAI,aAAa,CAAC,OAAO,UAAU,EACP,uBAAuB;;;;;;AAOlE,SAAgB,+BAA+B,YAAoC;AACjF,KAAI,WAAW,WAAW,uBACxB,OAAM,IAAI,MAAM,uBAAuB,uBAAuB,QAAQ;AAKxE,QAFmB,UAAU,aAAa,YAAY,MAAM,CAE1C,MAAM,GAAG,GAAG;;;;;;;;;;;;;;;;;;;;;;;;ACvDhC,SAAgB,UAAU,YAAwB,SAAiC;AACjF,KAAI,WAAW,WAAW,uBACxB,OAAM,IAAI,MAAM,uBAAuB,uBAAuB,QAAQ;CAGxE,MAAM,cAAc,aAAa,QAAQ;AAEzC,QAAO,UAAU,KAAK,aAAa,YAAY,EAAE,SAAS,OAAO,CAAC;;;;;;;;;;;;;AAcpE,SAAgB,YACd,WACA,WACA,SACS;AACT,KAAI,UAAU,WAAW,sBACvB,OAAM,IAAI,MAAM,sBAAsB,sBAAsB,QAAQ;AAEtE,KAAI,UAAU,WAAW,qBACvB,OAAM,IAAI,MAAM,qBAAqB,qBAAqB,QAAQ;AAGpE,KAAI;EACF,MAAM,cAAc,aAAa,QAAQ;AAEzC,SAAO,UAAU,OAAO,WAAW,aAAa,WAAW,EAAE,SAAS,OAAO,CAAC;SACxE;AACN,SAAO;;;;;;;;;;;ACtDX,MAAa,yBAAyB;;;;;;;;;AAUtC,SAAgB,YAAY,iBAA6B,SAAiC;AAExF,QAAO,iBAAiB,iBAAiB,SAD7B,IAAI,6BAA6B,CACS;;;;;;;;;;AAWxD,SAAgB,iBACd,iBACA,SACA,KACY;AAEZ,QAAO,uBAAuB,iBAAiB,SAD/B,IAAI,WAAW,GAAG,CAC8B;;;;;;;;;;;AAYlE,SAAgB,uBACd,iBACA,SACA,SACY;AACZ,KAAI,gBAAgB,WAAW,uBAC7B,OAAM,IAAI,MAAM,uBAAuB,uBAAuB,QAAQ;AAExE,KAAI,QAAQ,WAAW,GACrB,OAAM,IAAI,MAAM,wCAAwC;AAG1D,QAAO,QAAQ,KAAK,SAAS,iBAAiB,QAAQ;;;;;;;;;;AAWxD,SAAgB,cACd,kBACA,WACA,SACS;AACT,KAAI,iBAAiB,WAAW,wBAC9B,OAAM,IAAI,MAAM,sBAAsB,wBAAwB,QAAQ;AAExE,KAAI,UAAU,WAAW,uBACvB,OAAM,IAAI,MAAM,qBAAqB,uBAAuB,QAAQ;AAGtE,KAAI;AACF,SAAO,QAAQ,OAAO,WAAW,SAAS,iBAAiB;SACrD;AACN,SAAO;;;;;;;;;;;ACjFX,MAAa,0BAA0B;AACvC,MAAa,2BAA2B;AACxC,MAAa,yBAAyB;;;;AAKtC,SAAgB,0BAA0B,KAAwC;AAChF,QAAO,IAAI,WAAW,yBAAyB;;;;;AAMjD,SAAgB,+BAA+B,YAAoC;AACjF,KAAI,WAAW,WAAW,yBACxB,OAAM,IAAI,MAAM,uBAAuB,yBAAyB,QAAQ;AAE1E,QAAO,QAAQ,aAAa,WAAW;;;;;;;;;;;;;AAczC,SAAgB,YAAY,YAAwB,SAAiC;AACnF,KAAI,WAAW,WAAW,yBACxB,OAAM,IAAI,MAAM,uBAAuB,yBAAyB,QAAQ;AAE1E,QAAO,QAAQ,KAAK,SAAS,WAAW;;;;;;;;;;;AAY1C,SAAgB,cACd,WACA,SACA,WACS;AACT,KAAI,UAAU,WAAW,wBACvB,OAAM,IAAI,MAAM,sBAAsB,wBAAwB,QAAQ;AAExE,KAAI,UAAU,WAAW,uBACvB,OAAM,IAAI,MAAM,qBAAqB,uBAAuB,QAAQ;AAGtE,KAAI;AACF,SAAO,QAAQ,OAAO,WAAW,SAAS,UAAU;SAC9C;AACN,SAAO;;;;;;;;;;;;;;;;;;;;ACxDX,SAAgB,OAAO,UAAsB,MAAkB,WAA+B;AAC5F,QAAO,UAAU,UAAU,MAAM,WAAW,IAAI,GAAG,EAAE;;;;;;;;;;;;;AAcvD,SAAgB,UACd,UACA,MACA,WACA,MACA,GACA,GACY;AACZ,KAAI,QAAQ,GACV,OAAM,IAAI,MAAM,mBAAmB;AAErC,KAAI,MAAM,EACR,OAAM,IAAI,MAAM,eAAe;AAEjC,KAAI,MAAM,EACR,OAAM,IAAI,MAAM,eAAe;AAKjC,QAAOC,SAAY,UAAU,MAAM;EAAE,GAF3B,KAAK;EAEyB;EAAG;EAAG,OAAO;EAAW,CAAC;;;;;;;;;;;;;;;;;;;ACnCnE,SAAgB,SAAS,UAAsB,MAAkB,WAA+B;AAE9F,QAAO,gBAAgB,UAAU,MAAM,WAAW,GAAG,OAAO,EAAE;;;;;;;;;;;;;AAchE,SAAgB,gBACd,UACA,MACA,WACA,YACA,QACA,aACY;AACZ,QAAOC,WAAc,UAAU,MAAM;EACnC,GAAG;EACH,GAAG;EACH,GAAG;EACH,OAAO;EACR,CAAC"}
1
+ {"version":3,"file":"index.mjs","names":["nobleSha256","nobleSha512","SYMMETRIC_KEY_SIZE","nobleScrypt","nobleArgon2id"],"sources":["../src/error.ts","../src/memzero.ts","../src/hash.ts","../src/symmetric-encryption.ts","../src/public-key-encryption.ts","../src/ecdsa-keys.ts","../src/ecdsa-signing.ts","../src/schnorr-signing.ts","../src/ed25519-signing.ts","../src/scrypt.ts","../src/argon.ts"],"sourcesContent":["/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/error.rs\n\n/**\n * AEAD-specific error for authentication failures\n */\nexport class AeadError extends Error {\n constructor(message = \"AEAD authentication failed\") {\n super(message);\n this.name = \"AeadError\";\n }\n}\n\n/**\n * Generic crypto error type\n */\nexport class CryptoError extends Error {\n override readonly cause?: Error | undefined;\n\n constructor(message: string, cause?: Error) {\n super(message);\n this.name = \"CryptoError\";\n this.cause = cause;\n }\n\n /**\n * Create a CryptoError for AEAD authentication failures.\n *\n * @param error - Optional underlying AeadError\n * @returns A CryptoError wrapping the AEAD error\n */\n static aead(error?: AeadError): CryptoError {\n return new CryptoError(\"AEAD error\", error ?? new AeadError());\n }\n\n /**\n * Create a CryptoError for invalid parameter values.\n *\n * @param message - Description of the invalid parameter\n * @returns A CryptoError describing the invalid parameter\n */\n static invalidParameter(message: string): CryptoError {\n return new CryptoError(`Invalid parameter: ${message}`);\n }\n}\n\n/**\n * Result type for crypto operations (using standard Error)\n */\nexport type CryptoResult<T> = T;\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/memzero.rs\n\n/**\n * Securely zero out a typed array.\n *\n * **IMPORTANT: This is a best-effort implementation.** Unlike the Rust reference\n * implementation which uses `std::ptr::write_volatile()` for guaranteed volatile\n * writes, JavaScript engines and JIT compilers can still potentially optimize\n * away these zeroing operations. The check at the end helps prevent optimization,\n * but it is not foolproof.\n *\n * For truly sensitive cryptographic operations, consider using the Web Crypto API's\n * `crypto.subtle` with non-extractable keys when possible, as it provides stronger\n * guarantees than what can be achieved with pure JavaScript.\n *\n * This function attempts to prevent the compiler from optimizing away\n * the zeroing operation by using a verification check after the zeroing loop.\n */\nexport function memzero(data: Uint8Array | Uint32Array): void {\n const len = data.length;\n for (let i = 0; i < len; i++) {\n data[i] = 0;\n }\n // Force a side effect to prevent optimization\n if (data.length > 0 && data[0] !== 0) {\n throw new Error(\"memzero failed\");\n }\n}\n\n/**\n * Securely zero out an array of Uint8Arrays.\n */\nexport function memzeroVecVecU8(arrays: Uint8Array[]): void {\n for (const arr of arrays) {\n memzero(arr);\n }\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/hash.rs\n\nimport { sha256 as nobleSha256, sha512 as nobleSha512 } from \"@noble/hashes/sha2.js\";\nimport { hmac } from \"@noble/hashes/hmac.js\";\nimport { pbkdf2 } from \"@noble/hashes/pbkdf2.js\";\nimport { hkdf } from \"@noble/hashes/hkdf.js\";\n\n// Constants\nexport const CRC32_SIZE = 4;\nexport const SHA256_SIZE = 32;\nexport const SHA512_SIZE = 64;\n\n// CRC-32 lookup table (IEEE polynomial 0xedb88320)\nconst CRC32_TABLE = new Uint32Array(256);\nfor (let i = 0; i < 256; i++) {\n let crc = i;\n for (let j = 0; j < 8; j++) {\n crc = (crc & 1) !== 0 ? (crc >>> 1) ^ 0xedb88320 : crc >>> 1;\n }\n CRC32_TABLE[i] = crc >>> 0;\n}\n\n/**\n * Calculate CRC-32 checksum\n */\nexport function crc32(data: Uint8Array): number {\n let crc = 0xffffffff;\n for (const byte of data) {\n crc = CRC32_TABLE[(crc ^ byte) & 0xff] ^ (crc >>> 8);\n }\n return (crc ^ 0xffffffff) >>> 0;\n}\n\n/**\n * Calculate CRC-32 checksum and return as a 4-byte big-endian array\n */\nexport function crc32Data(data: Uint8Array): Uint8Array {\n return crc32DataOpt(data, false);\n}\n\n/**\n * Calculate CRC-32 checksum and return as a 4-byte array\n * @param data - Input data\n * @param littleEndian - If true, returns little-endian; otherwise big-endian\n */\nexport function crc32DataOpt(data: Uint8Array, littleEndian: boolean): Uint8Array {\n const checksum = crc32(data);\n const result = new Uint8Array(4);\n const view = new DataView(result.buffer);\n view.setUint32(0, checksum, littleEndian);\n return result;\n}\n\n/**\n * Calculate SHA-256 hash\n */\nexport function sha256(data: Uint8Array): Uint8Array {\n return nobleSha256(data);\n}\n\n/**\n * Calculate double SHA-256 hash (SHA-256 of SHA-256)\n * This is the standard Bitcoin hashing function\n */\nexport function doubleSha256(message: Uint8Array): Uint8Array {\n return sha256(sha256(message));\n}\n\n/**\n * Calculate SHA-512 hash\n */\nexport function sha512(data: Uint8Array): Uint8Array {\n return nobleSha512(data);\n}\n\n/**\n * Calculate HMAC-SHA-256\n */\nexport function hmacSha256(key: Uint8Array, message: Uint8Array): Uint8Array {\n return hmac(nobleSha256, key, message);\n}\n\n/**\n * Calculate HMAC-SHA-512\n */\nexport function hmacSha512(key: Uint8Array, message: Uint8Array): Uint8Array {\n return hmac(nobleSha512, key, message);\n}\n\n/**\n * Derive a key using PBKDF2 with HMAC-SHA-256\n */\nexport function pbkdf2HmacSha256(\n password: Uint8Array,\n salt: Uint8Array,\n iterations: number,\n keyLen: number,\n): Uint8Array {\n return pbkdf2(nobleSha256, password, salt, { c: iterations, dkLen: keyLen });\n}\n\n/**\n * Derive a key using PBKDF2 with HMAC-SHA-512\n */\nexport function pbkdf2HmacSha512(\n password: Uint8Array,\n salt: Uint8Array,\n iterations: number,\n keyLen: number,\n): Uint8Array {\n return pbkdf2(nobleSha512, password, salt, { c: iterations, dkLen: keyLen });\n}\n\n/**\n * Derive a key using HKDF with HMAC-SHA-256\n */\nexport function hkdfHmacSha256(\n keyMaterial: Uint8Array,\n salt: Uint8Array,\n keyLen: number,\n): Uint8Array {\n return hkdf(nobleSha256, keyMaterial, salt, undefined, keyLen);\n}\n\n/**\n * Derive a key using HKDF with HMAC-SHA-512\n */\nexport function hkdfHmacSha512(\n keyMaterial: Uint8Array,\n salt: Uint8Array,\n keyLen: number,\n): Uint8Array {\n return hkdf(nobleSha512, keyMaterial, salt, undefined, keyLen);\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/symmetric_encryption.rs\n\nimport { chacha20poly1305 } from \"@noble/ciphers/chacha.js\";\nimport { CryptoError, AeadError } from \"./error.js\";\n\n// Constants\nexport const SYMMETRIC_KEY_SIZE = 32;\nexport const SYMMETRIC_NONCE_SIZE = 12;\nexport const SYMMETRIC_AUTH_SIZE = 16;\n\n/**\n * Encrypt data using ChaCha20-Poly1305 AEAD cipher.\n *\n * **Security Warning**: The nonce MUST be unique for every encryption operation\n * with the same key. Reusing a nonce completely breaks the security of the\n * encryption scheme and can reveal plaintext.\n *\n * @param plaintext - The data to encrypt\n * @param key - 32-byte encryption key\n * @param nonce - 12-byte nonce (MUST be unique per encryption with the same key)\n * @returns Tuple of [ciphertext, authTag] where authTag is 16 bytes\n * @throws {CryptoError} If key is not 32 bytes or nonce is not 12 bytes\n */\nexport function aeadChaCha20Poly1305Encrypt(\n plaintext: Uint8Array,\n key: Uint8Array,\n nonce: Uint8Array,\n): [Uint8Array, Uint8Array] {\n return aeadChaCha20Poly1305EncryptWithAad(plaintext, key, nonce, new Uint8Array(0));\n}\n\n/**\n * Encrypt data using ChaCha20-Poly1305 AEAD cipher with additional authenticated data.\n *\n * **Security Warning**: The nonce MUST be unique for every encryption operation\n * with the same key. Reusing a nonce completely breaks the security of the\n * encryption scheme and can reveal plaintext.\n *\n * @param plaintext - The data to encrypt\n * @param key - 32-byte encryption key\n * @param nonce - 12-byte nonce (MUST be unique per encryption with the same key)\n * @param aad - Additional authenticated data (not encrypted, but integrity-protected)\n * @returns Tuple of [ciphertext, authTag] where authTag is 16 bytes\n * @throws {CryptoError} If key is not 32 bytes or nonce is not 12 bytes\n */\nexport function aeadChaCha20Poly1305EncryptWithAad(\n plaintext: Uint8Array,\n key: Uint8Array,\n nonce: Uint8Array,\n aad: Uint8Array,\n): [Uint8Array, Uint8Array] {\n if (key.length !== SYMMETRIC_KEY_SIZE) {\n throw CryptoError.invalidParameter(`Key must be ${SYMMETRIC_KEY_SIZE} bytes`);\n }\n if (nonce.length !== SYMMETRIC_NONCE_SIZE) {\n throw CryptoError.invalidParameter(`Nonce must be ${SYMMETRIC_NONCE_SIZE} bytes`);\n }\n\n const cipher = chacha20poly1305(key, nonce, aad);\n const sealed = cipher.encrypt(plaintext);\n\n // The sealed output contains ciphertext + 16-byte auth tag\n const ciphertext = sealed.slice(0, sealed.length - SYMMETRIC_AUTH_SIZE);\n const authTag = sealed.slice(sealed.length - SYMMETRIC_AUTH_SIZE);\n\n return [ciphertext, authTag];\n}\n\n/**\n * Decrypt data using ChaCha20-Poly1305 AEAD cipher.\n *\n * @param ciphertext - The encrypted data\n * @param key - 32-byte encryption key (must match key used for encryption)\n * @param nonce - 12-byte nonce (must match nonce used for encryption)\n * @param authTag - 16-byte authentication tag from encryption\n * @returns Decrypted plaintext\n * @throws {CryptoError} If key/nonce/authTag sizes are invalid\n * @throws {CryptoError} If authentication fails (tampered data or wrong key/nonce)\n */\nexport function aeadChaCha20Poly1305Decrypt(\n ciphertext: Uint8Array,\n key: Uint8Array,\n nonce: Uint8Array,\n authTag: Uint8Array,\n): Uint8Array {\n return aeadChaCha20Poly1305DecryptWithAad(ciphertext, key, nonce, new Uint8Array(0), authTag);\n}\n\n/**\n * Decrypt data using ChaCha20-Poly1305 AEAD cipher with additional authenticated data.\n *\n * @param ciphertext - The encrypted data\n * @param key - 32-byte encryption key (must match key used for encryption)\n * @param nonce - 12-byte nonce (must match nonce used for encryption)\n * @param aad - Additional authenticated data (must exactly match AAD used for encryption)\n * @param authTag - 16-byte authentication tag from encryption\n * @returns Decrypted plaintext\n * @throws {CryptoError} If key/nonce/authTag sizes are invalid\n * @throws {CryptoError} If authentication fails (tampered data, wrong key/nonce, or AAD mismatch)\n */\nexport function aeadChaCha20Poly1305DecryptWithAad(\n ciphertext: Uint8Array,\n key: Uint8Array,\n nonce: Uint8Array,\n aad: Uint8Array,\n authTag: Uint8Array,\n): Uint8Array {\n if (key.length !== SYMMETRIC_KEY_SIZE) {\n throw CryptoError.invalidParameter(`Key must be ${SYMMETRIC_KEY_SIZE} bytes`);\n }\n if (nonce.length !== SYMMETRIC_NONCE_SIZE) {\n throw CryptoError.invalidParameter(`Nonce must be ${SYMMETRIC_NONCE_SIZE} bytes`);\n }\n if (authTag.length !== SYMMETRIC_AUTH_SIZE) {\n throw CryptoError.invalidParameter(`Auth tag must be ${SYMMETRIC_AUTH_SIZE} bytes`);\n }\n\n // Combine ciphertext and auth tag for decryption\n const sealed = new Uint8Array(ciphertext.length + authTag.length);\n sealed.set(ciphertext);\n sealed.set(authTag, ciphertext.length);\n\n try {\n const cipher = chacha20poly1305(key, nonce, aad);\n return cipher.decrypt(sealed);\n } catch (error) {\n // Preserve the original error for debugging while wrapping in our error type\n const aeadError = new AeadError(\n `Decryption failed: ${error instanceof Error ? error.message : \"authentication error\"}`,\n );\n throw CryptoError.aead(aeadError);\n }\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/public_key_encryption.rs\n\nimport { x25519 } from \"@noble/curves/ed25519.js\";\nimport type { RandomNumberGenerator } from \"@bcts/rand\";\nimport { hkdfHmacSha256 } from \"./hash.js\";\n\n// Constants\nexport const GENERIC_PRIVATE_KEY_SIZE = 32;\nexport const GENERIC_PUBLIC_KEY_SIZE = 32;\nexport const X25519_PRIVATE_KEY_SIZE = 32;\nexport const X25519_PUBLIC_KEY_SIZE = 32;\n\n/**\n * Derive an X25519 agreement private key from key material.\n * Uses HKDF with \"agreement\" as domain separation salt.\n */\nexport function deriveAgreementPrivateKey(keyMaterial: Uint8Array): Uint8Array {\n const salt = new TextEncoder().encode(\"agreement\");\n return hkdfHmacSha256(keyMaterial, salt, X25519_PRIVATE_KEY_SIZE);\n}\n\n/**\n * Derive a signing private key from key material.\n * Uses HKDF with \"signing\" as domain separation salt.\n */\nexport function deriveSigningPrivateKey(keyMaterial: Uint8Array): Uint8Array {\n const salt = new TextEncoder().encode(\"signing\");\n return hkdfHmacSha256(keyMaterial, salt, 32);\n}\n\n/**\n * Generate a new random X25519 private key.\n */\nexport function x25519NewPrivateKeyUsing(rng: RandomNumberGenerator): Uint8Array {\n return rng.randomData(X25519_PRIVATE_KEY_SIZE);\n}\n\n/**\n * Derive an X25519 public key from a private key.\n */\nexport function x25519PublicKeyFromPrivateKey(privateKey: Uint8Array): Uint8Array {\n if (privateKey.length !== X25519_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${X25519_PRIVATE_KEY_SIZE} bytes`);\n }\n return x25519.getPublicKey(privateKey);\n}\n\n// Symmetric key size for the derived shared key\nconst SYMMETRIC_KEY_SIZE = 32;\n\n/**\n * Compute a shared symmetric key using X25519 key agreement (ECDH).\n *\n * This function performs X25519 Diffie-Hellman key agreement and then\n * derives a symmetric key using HKDF-SHA256 with \"agreement\" as the salt.\n * This matches the Rust bc-crypto implementation for cross-platform compatibility.\n *\n * @param x25519Private - 32-byte X25519 private key\n * @param x25519Public - 32-byte X25519 public key from the other party\n * @returns 32-byte derived symmetric key\n * @throws {Error} If private key is not 32 bytes or public key is not 32 bytes\n */\nexport function x25519SharedKey(x25519Private: Uint8Array, x25519Public: Uint8Array): Uint8Array {\n if (x25519Private.length !== X25519_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${X25519_PRIVATE_KEY_SIZE} bytes`);\n }\n if (x25519Public.length !== X25519_PUBLIC_KEY_SIZE) {\n throw new Error(`Public key must be ${X25519_PUBLIC_KEY_SIZE} bytes`);\n }\n // Perform raw X25519 Diffie-Hellman\n const rawSharedSecret = x25519.getSharedSecret(x25519Private, x25519Public);\n // Derive symmetric key using HKDF with \"agreement\" salt (matches Rust implementation)\n const salt = new TextEncoder().encode(\"agreement\");\n return hkdfHmacSha256(rawSharedSecret, salt, SYMMETRIC_KEY_SIZE);\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/ecdsa_keys.rs\n\nimport { secp256k1 } from \"@noble/curves/secp256k1.js\";\nimport type { RandomNumberGenerator } from \"@bcts/rand\";\nimport { hkdfHmacSha256 } from \"./hash.js\";\n\n// Constants\nexport const ECDSA_PRIVATE_KEY_SIZE = 32;\nexport const ECDSA_PUBLIC_KEY_SIZE = 33; // Compressed\nexport const ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE = 65;\nexport const ECDSA_MESSAGE_HASH_SIZE = 32;\nexport const ECDSA_SIGNATURE_SIZE = 64;\nexport const SCHNORR_PUBLIC_KEY_SIZE = 32; // x-only\n\n/**\n * Generate a new random ECDSA private key using secp256k1.\n *\n * Note: Unlike some implementations, this directly returns the random bytes\n * without validation. The secp256k1 library will handle any edge cases when\n * the key is used.\n */\nexport function ecdsaNewPrivateKeyUsing(rng: RandomNumberGenerator): Uint8Array {\n return rng.randomData(ECDSA_PRIVATE_KEY_SIZE);\n}\n\n/**\n * Derive a compressed ECDSA public key from a private key.\n */\nexport function ecdsaPublicKeyFromPrivateKey(privateKey: Uint8Array): Uint8Array {\n if (privateKey.length !== ECDSA_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);\n }\n return secp256k1.getPublicKey(privateKey, true); // true = compressed\n}\n\n/**\n * Decompress a compressed public key to uncompressed format.\n */\nexport function ecdsaDecompressPublicKey(compressed: Uint8Array): Uint8Array {\n if (compressed.length !== ECDSA_PUBLIC_KEY_SIZE) {\n throw new Error(`Compressed public key must be ${ECDSA_PUBLIC_KEY_SIZE} bytes`);\n }\n const point = secp256k1.Point.fromBytes(compressed);\n return point.toBytes(false); // false = uncompressed\n}\n\n/**\n * Compress an uncompressed public key.\n */\nexport function ecdsaCompressPublicKey(uncompressed: Uint8Array): Uint8Array {\n if (uncompressed.length !== ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE) {\n throw new Error(`Uncompressed public key must be ${ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE} bytes`);\n }\n const point = secp256k1.Point.fromBytes(uncompressed);\n return point.toBytes(true); // true = compressed\n}\n\n/**\n * Derive an ECDSA private key from key material using HKDF.\n *\n * Note: This directly returns the HKDF output without validation,\n * matching the Rust reference implementation behavior.\n */\nexport function ecdsaDerivePrivateKey(keyMaterial: Uint8Array): Uint8Array {\n const salt = new TextEncoder().encode(\"signing\");\n return hkdfHmacSha256(keyMaterial, salt, ECDSA_PRIVATE_KEY_SIZE);\n}\n\n/**\n * Extract the x-only (Schnorr) public key from a private key.\n * This is used for BIP-340 Schnorr signatures.\n */\nexport function schnorrPublicKeyFromPrivateKey(privateKey: Uint8Array): Uint8Array {\n if (privateKey.length !== ECDSA_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);\n }\n // Get the full public key and extract just the x-coordinate\n const fullPubKey = secp256k1.getPublicKey(privateKey, false); // uncompressed\n // Skip the 0x04 prefix and take only x-coordinate (first 32 bytes after prefix)\n return fullPubKey.slice(1, 33);\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/ecdsa_signing.rs\n\nimport { secp256k1 } from \"@noble/curves/secp256k1.js\";\nimport { doubleSha256 } from \"./hash.js\";\nimport {\n ECDSA_PRIVATE_KEY_SIZE,\n ECDSA_PUBLIC_KEY_SIZE,\n ECDSA_SIGNATURE_SIZE,\n} from \"./ecdsa-keys.js\";\n\n/**\n * Sign a message using ECDSA with secp256k1.\n *\n * The message is hashed with double SHA-256 before signing (Bitcoin standard).\n *\n * **Security Note**: The private key must be kept secret. ECDSA requires\n * cryptographically secure random nonces internally; this is handled by\n * the underlying library using RFC 6979 deterministic nonces.\n *\n * @param privateKey - 32-byte secp256k1 private key\n * @param message - Message to sign (any length, will be double-SHA256 hashed)\n * @returns 64-byte compact signature (r || s format)\n * @throws {Error} If private key is not 32 bytes\n */\nexport function ecdsaSign(privateKey: Uint8Array, message: Uint8Array): Uint8Array {\n if (privateKey.length !== ECDSA_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);\n }\n\n const messageHash = doubleSha256(message);\n // prehash: false because we already hashed the message with doubleSha256\n return secp256k1.sign(messageHash, privateKey, { prehash: false });\n}\n\n/**\n * Verify an ECDSA signature with secp256k1.\n *\n * The message is hashed with double SHA-256 before verification (Bitcoin standard).\n *\n * @param publicKey - 33-byte compressed secp256k1 public key\n * @param signature - 64-byte compact signature (r || s format)\n * @param message - Original message that was signed\n * @returns `true` if signature is valid, `false` if signature verification fails\n * @throws {Error} If public key is not 33 bytes or signature is not 64 bytes\n */\nexport function ecdsaVerify(\n publicKey: Uint8Array,\n signature: Uint8Array,\n message: Uint8Array,\n): boolean {\n if (publicKey.length !== ECDSA_PUBLIC_KEY_SIZE) {\n throw new Error(`Public key must be ${ECDSA_PUBLIC_KEY_SIZE} bytes`);\n }\n if (signature.length !== ECDSA_SIGNATURE_SIZE) {\n throw new Error(`Signature must be ${ECDSA_SIGNATURE_SIZE} bytes`);\n }\n\n try {\n const messageHash = doubleSha256(message);\n // prehash: false because we already hashed the message with doubleSha256\n return secp256k1.verify(signature, messageHash, publicKey, { prehash: false });\n } catch {\n return false;\n }\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/schnorr_signing.rs\n\nimport { schnorr } from \"@noble/curves/secp256k1.js\";\nimport type { RandomNumberGenerator } from \"@bcts/rand\";\nimport { SecureRandomNumberGenerator } from \"@bcts/rand\";\nimport { ECDSA_PRIVATE_KEY_SIZE, SCHNORR_PUBLIC_KEY_SIZE } from \"./ecdsa-keys.js\";\n\n// Constants\nexport const SCHNORR_SIGNATURE_SIZE = 64;\n\n/**\n * Sign a message using Schnorr signature (BIP-340).\n * Uses secure random auxiliary randomness.\n *\n * @param ecdsaPrivateKey - 32-byte private key\n * @param message - Message to sign (not pre-hashed, per BIP-340)\n * @returns 64-byte Schnorr signature\n */\nexport function schnorrSign(ecdsaPrivateKey: Uint8Array, message: Uint8Array): Uint8Array {\n const rng = new SecureRandomNumberGenerator();\n return schnorrSignUsing(ecdsaPrivateKey, message, rng);\n}\n\n/**\n * Sign a message using Schnorr signature with a custom RNG.\n *\n * @param ecdsaPrivateKey - 32-byte private key\n * @param message - Message to sign\n * @param rng - Random number generator for auxiliary randomness\n * @returns 64-byte Schnorr signature\n */\nexport function schnorrSignUsing(\n ecdsaPrivateKey: Uint8Array,\n message: Uint8Array,\n rng: RandomNumberGenerator,\n): Uint8Array {\n const auxRand = rng.randomData(32);\n return schnorrSignWithAuxRand(ecdsaPrivateKey, message, auxRand);\n}\n\n/**\n * Sign a message using Schnorr signature with specific auxiliary randomness.\n * This is useful for deterministic signing in tests.\n *\n * @param ecdsaPrivateKey - 32-byte private key\n * @param message - Message to sign\n * @param auxRand - 32-byte auxiliary randomness (per BIP-340)\n * @returns 64-byte Schnorr signature\n */\nexport function schnorrSignWithAuxRand(\n ecdsaPrivateKey: Uint8Array,\n message: Uint8Array,\n auxRand: Uint8Array,\n): Uint8Array {\n if (ecdsaPrivateKey.length !== ECDSA_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);\n }\n if (auxRand.length !== 32) {\n throw new Error(\"Auxiliary randomness must be 32 bytes\");\n }\n\n return schnorr.sign(message, ecdsaPrivateKey, auxRand);\n}\n\n/**\n * Verify a Schnorr signature (BIP-340).\n *\n * @param schnorrPublicKey - 32-byte x-only public key\n * @param signature - 64-byte Schnorr signature\n * @param message - Original message\n * @returns true if signature is valid\n */\nexport function schnorrVerify(\n schnorrPublicKey: Uint8Array,\n signature: Uint8Array,\n message: Uint8Array,\n): boolean {\n if (schnorrPublicKey.length !== SCHNORR_PUBLIC_KEY_SIZE) {\n throw new Error(`Public key must be ${SCHNORR_PUBLIC_KEY_SIZE} bytes`);\n }\n if (signature.length !== SCHNORR_SIGNATURE_SIZE) {\n throw new Error(`Signature must be ${SCHNORR_SIGNATURE_SIZE} bytes`);\n }\n\n try {\n return schnorr.verify(signature, message, schnorrPublicKey);\n } catch {\n return false;\n }\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/ed25519_signing.rs\n\nimport { ed25519 } from \"@noble/curves/ed25519.js\";\nimport type { RandomNumberGenerator } from \"@bcts/rand\";\n\n// Constants\nexport const ED25519_PUBLIC_KEY_SIZE = 32;\nexport const ED25519_PRIVATE_KEY_SIZE = 32;\nexport const ED25519_SIGNATURE_SIZE = 64;\n\n/**\n * Generate a new random Ed25519 private key.\n */\nexport function ed25519NewPrivateKeyUsing(rng: RandomNumberGenerator): Uint8Array {\n return rng.randomData(ED25519_PRIVATE_KEY_SIZE);\n}\n\n/**\n * Derive an Ed25519 public key from a private key.\n */\nexport function ed25519PublicKeyFromPrivateKey(privateKey: Uint8Array): Uint8Array {\n if (privateKey.length !== ED25519_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ED25519_PRIVATE_KEY_SIZE} bytes`);\n }\n return ed25519.getPublicKey(privateKey);\n}\n\n/**\n * Sign a message using Ed25519.\n *\n * **Security Note**: The private key must be kept secret. The same private key\n * can safely sign multiple messages.\n *\n * @param privateKey - 32-byte Ed25519 private key\n * @param message - Message to sign (any length)\n * @returns 64-byte Ed25519 signature\n * @throws {Error} If private key is not 32 bytes\n */\nexport function ed25519Sign(privateKey: Uint8Array, message: Uint8Array): Uint8Array {\n if (privateKey.length !== ED25519_PRIVATE_KEY_SIZE) {\n throw new Error(`Private key must be ${ED25519_PRIVATE_KEY_SIZE} bytes`);\n }\n return ed25519.sign(message, privateKey);\n}\n\n/**\n * Verify an Ed25519 signature.\n *\n * @param publicKey - 32-byte Ed25519 public key\n * @param message - Original message that was signed\n * @param signature - 64-byte Ed25519 signature\n * @returns `true` if signature is valid, `false` if signature verification fails\n * @throws {Error} If public key is not 32 bytes or signature is not 64 bytes\n */\nexport function ed25519Verify(\n publicKey: Uint8Array,\n message: Uint8Array,\n signature: Uint8Array,\n): boolean {\n if (publicKey.length !== ED25519_PUBLIC_KEY_SIZE) {\n throw new Error(`Public key must be ${ED25519_PUBLIC_KEY_SIZE} bytes`);\n }\n if (signature.length !== ED25519_SIGNATURE_SIZE) {\n throw new Error(`Signature must be ${ED25519_SIGNATURE_SIZE} bytes`);\n }\n\n try {\n return ed25519.verify(signature, message, publicKey);\n } catch {\n return false;\n }\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/scrypt.rs\n\nimport { scrypt as nobleScrypt } from \"@noble/hashes/scrypt.js\";\n\n/**\n * Derive a key using Scrypt with recommended parameters.\n * Uses N=2^15 (32768), r=8, p=1 as recommended defaults.\n *\n * @param password - Password or passphrase\n * @param salt - Salt value\n * @param outputLen - Desired output length\n * @returns Derived key\n */\nexport function scrypt(password: Uint8Array, salt: Uint8Array, outputLen: number): Uint8Array {\n return scryptOpt(password, salt, outputLen, 15, 8, 1);\n}\n\n/**\n * Derive a key using Scrypt with custom parameters.\n *\n * @param password - Password or passphrase\n * @param salt - Salt value\n * @param outputLen - Desired output length\n * @param logN - Log2 of the CPU/memory cost parameter N (must be <64)\n * @param r - Block size parameter (must be >0)\n * @param p - Parallelization parameter (must be >0)\n * @returns Derived key\n */\nexport function scryptOpt(\n password: Uint8Array,\n salt: Uint8Array,\n outputLen: number,\n logN: number,\n r: number,\n p: number,\n): Uint8Array {\n if (logN >= 64) {\n throw new Error(\"logN must be <64\");\n }\n if (r === 0) {\n throw new Error(\"r must be >0\");\n }\n if (p === 0) {\n throw new Error(\"p must be >0\");\n }\n\n const N = 1 << logN; // 2^logN\n\n return nobleScrypt(password, salt, { N, r, p, dkLen: outputLen });\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n */\n\n// Ported from bc-crypto-rust/src/argon.rs\n\nimport { argon2id as nobleArgon2id } from \"@noble/hashes/argon2.js\";\n\n/**\n * Derive a key using Argon2id with default parameters.\n * This matches the Rust `argon2id` function signature.\n *\n * @param password - Password or passphrase\n * @param salt - Salt value (must be at least 8 bytes)\n * @param outputLen - Desired output length\n * @returns Derived key\n */\nexport function argon2id(password: Uint8Array, salt: Uint8Array, outputLen: number): Uint8Array {\n // Use default parameters matching Argon2::default() in Rust\n return argon2idHashOpt(password, salt, outputLen, 3, 65536, 4);\n}\n\n/**\n * Derive a key using Argon2id with custom parameters.\n *\n * @param password - Password or passphrase\n * @param salt - Salt value (must be at least 8 bytes)\n * @param outputLen - Desired output length\n * @param iterations - Number of iterations (t)\n * @param memory - Memory in KiB (m)\n * @param parallelism - Degree of parallelism (p)\n * @returns Derived key\n */\nexport function argon2idHashOpt(\n password: Uint8Array,\n salt: Uint8Array,\n outputLen: number,\n iterations: number,\n memory: number,\n parallelism: number,\n): Uint8Array {\n return nobleArgon2id(password, salt, {\n t: iterations,\n m: memory,\n p: parallelism,\n dkLen: outputLen,\n });\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bcts/crypto",
3
- "version": "1.0.0-alpha.22",
3
+ "version": "1.0.0-alpha.23",
4
4
  "type": "module",
5
5
  "description": "Blockchain Commons Cryptographic Utilities for TypeScript",
6
6
  "license": "BSD-2-Clause-Patent",
@@ -59,21 +59,21 @@
59
59
  "node": ">=18.0.0"
60
60
  },
61
61
  "dependencies": {
62
- "@bcts/rand": "^1.0.0-alpha.22",
63
- "@noble/ciphers": "^2.1.1",
64
- "@noble/curves": "^2.0.1",
65
- "@noble/hashes": "^2.0.1"
62
+ "@bcts/rand": "^1.0.0-alpha.23",
63
+ "@noble/ciphers": "^2.2.0",
64
+ "@noble/curves": "^2.2.0",
65
+ "@noble/hashes": "^2.2.0"
66
66
  },
67
67
  "devDependencies": {
68
68
  "@bcts/eslint": "^0.1.0",
69
69
  "@bcts/tsconfig": "^0.1.0",
70
70
  "@eslint/js": "^10.0.1",
71
- "@types/node": "^25.3.2",
72
- "eslint": "^10.0.2",
71
+ "@types/node": "^25.6.0",
72
+ "eslint": "^10.2.1",
73
73
  "ts-node": "^10.9.2",
74
- "typedoc": "^0.28.17",
75
- "tsdown": "^0.20.3",
76
- "typescript": "^5.9.3",
77
- "vitest": "^4.0.18"
74
+ "typedoc": "^0.28.19",
75
+ "tsdown": "^0.21.0",
76
+ "typescript": "^6.0.3",
77
+ "vitest": "^4.1.5"
78
78
  }
79
79
  }