@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 +28 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.iife.js +28 -28
- package/dist/index.iife.js.map +1 -1
- package/dist/index.mjs +28 -28
- package/dist/index.mjs.map +1 -1
- package/package.json +11 -11
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 !==
|
|
238
|
-
if (nonce.length !==
|
|
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 -
|
|
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 !==
|
|
270
|
-
if (nonce.length !==
|
|
271
|
-
if (authTag.length !==
|
|
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"),
|
|
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(
|
|
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 !==
|
|
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 !==
|
|
336
|
-
if (x25519Public.length !==
|
|
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(
|
|
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 !==
|
|
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 !==
|
|
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 !==
|
|
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"),
|
|
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 !==
|
|
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 !==
|
|
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 !==
|
|
441
|
-
if (signature.length !==
|
|
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 !==
|
|
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 !==
|
|
504
|
-
if (signature.length !==
|
|
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(
|
|
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 !==
|
|
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 !==
|
|
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 !==
|
|
561
|
-
if (signature.length !==
|
|
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 {
|
package/dist/index.cjs.map
CHANGED
|
@@ -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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"}
|
package/dist/index.iife.js
CHANGED
|
@@ -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 !==
|
|
230
|
-
if (nonce.length !==
|
|
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 -
|
|
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 !==
|
|
262
|
-
if (nonce.length !==
|
|
263
|
-
if (authTag.length !==
|
|
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"),
|
|
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(
|
|
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 !==
|
|
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 !==
|
|
328
|
-
if (x25519Public.length !==
|
|
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(
|
|
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 !==
|
|
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 !==
|
|
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 !==
|
|
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"),
|
|
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 !==
|
|
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 !==
|
|
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 !==
|
|
433
|
-
if (signature.length !==
|
|
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 !==
|
|
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 !==
|
|
496
|
-
if (signature.length !==
|
|
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(
|
|
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 !==
|
|
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 !==
|
|
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 !==
|
|
553
|
-
if (signature.length !==
|
|
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 {
|
package/dist/index.iife.js.map
CHANGED
|
@@ -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 !==
|
|
237
|
-
if (nonce.length !==
|
|
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 -
|
|
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 !==
|
|
269
|
-
if (nonce.length !==
|
|
270
|
-
if (authTag.length !==
|
|
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"),
|
|
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(
|
|
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 !==
|
|
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 !==
|
|
335
|
-
if (x25519Public.length !==
|
|
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(
|
|
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 !==
|
|
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 !==
|
|
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 !==
|
|
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"),
|
|
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 !==
|
|
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 !==
|
|
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 !==
|
|
440
|
-
if (signature.length !==
|
|
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 !==
|
|
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 !==
|
|
503
|
-
if (signature.length !==
|
|
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(
|
|
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 !==
|
|
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 !==
|
|
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 !==
|
|
560
|
-
if (signature.length !==
|
|
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 {
|
package/dist/index.mjs.map
CHANGED
|
@@ -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":"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"}
|
|
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.
|
|
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.
|
|
63
|
-
"@noble/ciphers": "^2.
|
|
64
|
-
"@noble/curves": "^2.0
|
|
65
|
-
"@noble/hashes": "^2.0
|
|
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.
|
|
72
|
-
"eslint": "^10.
|
|
71
|
+
"@types/node": "^25.6.0",
|
|
72
|
+
"eslint": "^10.2.1",
|
|
73
73
|
"ts-node": "^10.9.2",
|
|
74
|
-
"typedoc": "^0.28.
|
|
75
|
-
"tsdown": "^0.
|
|
76
|
-
"typescript": "^
|
|
77
|
-
"vitest": "^4.
|
|
74
|
+
"typedoc": "^0.28.19",
|
|
75
|
+
"tsdown": "^0.21.0",
|
|
76
|
+
"typescript": "^6.0.3",
|
|
77
|
+
"vitest": "^4.1.5"
|
|
78
78
|
}
|
|
79
79
|
}
|