@bcts/crypto 1.0.0-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,652 @@
1
+ var bctsCrypto = (function(exports, _noble_hashes_sha2_js, _noble_hashes_hmac_js, _noble_hashes_pbkdf2_js, _noble_hashes_hkdf_js, _noble_ciphers_chacha_js, _noble_curves_ed25519_js, _noble_curves_secp256k1_js, _bcts_rand, _noble_hashes_scrypt_js, _noble_hashes_argon2_js) {
2
+
3
+
4
+ //#region src/error.ts
5
+ /**
6
+ * AEAD-specific error for authentication failures
7
+ */
8
+ var AeadError = class extends Error {
9
+ constructor(message = "AEAD authentication failed") {
10
+ super(message);
11
+ this.name = "AeadError";
12
+ }
13
+ };
14
+ /**
15
+ * Generic crypto error type
16
+ */
17
+ var CryptoError = class CryptoError extends Error {
18
+ cause;
19
+ constructor(message, cause) {
20
+ super(message);
21
+ this.name = "CryptoError";
22
+ this.cause = cause;
23
+ }
24
+ /**
25
+ * Create a CryptoError for AEAD authentication failures.
26
+ *
27
+ * @param error - Optional underlying AeadError
28
+ * @returns A CryptoError wrapping the AEAD error
29
+ */
30
+ static aead(error) {
31
+ return new CryptoError("AEAD error", error ?? new AeadError());
32
+ }
33
+ /**
34
+ * Create a CryptoError for invalid parameter values.
35
+ *
36
+ * @param message - Description of the invalid parameter
37
+ * @returns A CryptoError describing the invalid parameter
38
+ */
39
+ static invalidParameter(message) {
40
+ return new CryptoError(`Invalid parameter: ${message}`);
41
+ }
42
+ };
43
+
44
+ //#endregion
45
+ //#region src/memzero.ts
46
+ /**
47
+ * Securely zero out a typed array.
48
+ *
49
+ * **IMPORTANT: This is a best-effort implementation.** Unlike the Rust reference
50
+ * implementation which uses `std::ptr::write_volatile()` for guaranteed volatile
51
+ * writes, JavaScript engines and JIT compilers can still potentially optimize
52
+ * away these zeroing operations. The check at the end helps prevent optimization,
53
+ * but it is not foolproof.
54
+ *
55
+ * For truly sensitive cryptographic operations, consider using the Web Crypto API's
56
+ * `crypto.subtle` with non-extractable keys when possible, as it provides stronger
57
+ * guarantees than what can be achieved with pure JavaScript.
58
+ *
59
+ * This function attempts to prevent the compiler from optimizing away
60
+ * the zeroing operation by using a verification check after the zeroing loop.
61
+ */
62
+ function memzero(data) {
63
+ const len = data.length;
64
+ for (let i = 0; i < len; i++) data[i] = 0;
65
+ if (data.length > 0 && data[0] !== 0) throw new Error("memzero failed");
66
+ }
67
+ /**
68
+ * Securely zero out an array of Uint8Arrays.
69
+ */
70
+ function memzeroVecVecU8(arrays) {
71
+ for (const arr of arrays) memzero(arr);
72
+ }
73
+
74
+ //#endregion
75
+ //#region src/hash.ts
76
+ const CRC32_SIZE = 4;
77
+ const SHA256_SIZE = 32;
78
+ const SHA512_SIZE = 64;
79
+ const CRC32_TABLE = new Uint32Array(256);
80
+ for (let i = 0; i < 256; i++) {
81
+ let crc = i;
82
+ for (let j = 0; j < 8; j++) crc = (crc & 1) !== 0 ? crc >>> 1 ^ 3988292384 : crc >>> 1;
83
+ CRC32_TABLE[i] = crc >>> 0;
84
+ }
85
+ /**
86
+ * Calculate CRC-32 checksum
87
+ */
88
+ function crc32(data) {
89
+ let crc = 4294967295;
90
+ for (const byte of data) crc = CRC32_TABLE[(crc ^ byte) & 255] ^ crc >>> 8;
91
+ return (crc ^ 4294967295) >>> 0;
92
+ }
93
+ /**
94
+ * Calculate CRC-32 checksum and return as a 4-byte big-endian array
95
+ */
96
+ function crc32Data(data) {
97
+ return crc32DataOpt(data, false);
98
+ }
99
+ /**
100
+ * Calculate CRC-32 checksum and return as a 4-byte array
101
+ * @param data - Input data
102
+ * @param littleEndian - If true, returns little-endian; otherwise big-endian
103
+ */
104
+ function crc32DataOpt(data, littleEndian) {
105
+ const checksum = crc32(data);
106
+ const result = new Uint8Array(4);
107
+ new DataView(result.buffer).setUint32(0, checksum, littleEndian);
108
+ return result;
109
+ }
110
+ /**
111
+ * Calculate SHA-256 hash
112
+ */
113
+ function sha256(data) {
114
+ return (0, _noble_hashes_sha2_js.sha256)(data);
115
+ }
116
+ /**
117
+ * Calculate double SHA-256 hash (SHA-256 of SHA-256)
118
+ * This is the standard Bitcoin hashing function
119
+ */
120
+ function doubleSha256(message) {
121
+ return sha256(sha256(message));
122
+ }
123
+ /**
124
+ * Calculate SHA-512 hash
125
+ */
126
+ function sha512(data) {
127
+ return (0, _noble_hashes_sha2_js.sha512)(data);
128
+ }
129
+ /**
130
+ * Calculate HMAC-SHA-256
131
+ */
132
+ function hmacSha256(key, message) {
133
+ return (0, _noble_hashes_hmac_js.hmac)(_noble_hashes_sha2_js.sha256, key, message);
134
+ }
135
+ /**
136
+ * Calculate HMAC-SHA-512
137
+ */
138
+ function hmacSha512(key, message) {
139
+ return (0, _noble_hashes_hmac_js.hmac)(_noble_hashes_sha2_js.sha512, key, message);
140
+ }
141
+ /**
142
+ * Derive a key using PBKDF2 with HMAC-SHA-256
143
+ */
144
+ function pbkdf2HmacSha256(password, salt, iterations, keyLen) {
145
+ return (0, _noble_hashes_pbkdf2_js.pbkdf2)(_noble_hashes_sha2_js.sha256, password, salt, {
146
+ c: iterations,
147
+ dkLen: keyLen
148
+ });
149
+ }
150
+ /**
151
+ * Derive a key using PBKDF2 with HMAC-SHA-512
152
+ */
153
+ function pbkdf2HmacSha512(password, salt, iterations, keyLen) {
154
+ return (0, _noble_hashes_pbkdf2_js.pbkdf2)(_noble_hashes_sha2_js.sha512, password, salt, {
155
+ c: iterations,
156
+ dkLen: keyLen
157
+ });
158
+ }
159
+ /**
160
+ * Derive a key using HKDF with HMAC-SHA-256
161
+ */
162
+ function hkdfHmacSha256(keyMaterial, salt, keyLen) {
163
+ return (0, _noble_hashes_hkdf_js.hkdf)(_noble_hashes_sha2_js.sha256, keyMaterial, salt, void 0, keyLen);
164
+ }
165
+ /**
166
+ * Derive a key using HKDF with HMAC-SHA-512
167
+ */
168
+ function hkdfHmacSha512(keyMaterial, salt, keyLen) {
169
+ return (0, _noble_hashes_hkdf_js.hkdf)(_noble_hashes_sha2_js.sha512, keyMaterial, salt, void 0, keyLen);
170
+ }
171
+
172
+ //#endregion
173
+ //#region src/symmetric-encryption.ts
174
+ const SYMMETRIC_KEY_SIZE = 32;
175
+ const SYMMETRIC_NONCE_SIZE = 12;
176
+ const SYMMETRIC_AUTH_SIZE = 16;
177
+ /**
178
+ * Encrypt data using ChaCha20-Poly1305 AEAD cipher.
179
+ *
180
+ * **Security Warning**: The nonce MUST be unique for every encryption operation
181
+ * with the same key. Reusing a nonce completely breaks the security of the
182
+ * encryption scheme and can reveal plaintext.
183
+ *
184
+ * @param plaintext - The data to encrypt
185
+ * @param key - 32-byte encryption key
186
+ * @param nonce - 12-byte nonce (MUST be unique per encryption with the same key)
187
+ * @returns Tuple of [ciphertext, authTag] where authTag is 16 bytes
188
+ * @throws {CryptoError} If key is not 32 bytes or nonce is not 12 bytes
189
+ */
190
+ function aeadChaCha20Poly1305Encrypt(plaintext, key, nonce) {
191
+ return aeadChaCha20Poly1305EncryptWithAad(plaintext, key, nonce, new Uint8Array(0));
192
+ }
193
+ /**
194
+ * Encrypt data using ChaCha20-Poly1305 AEAD cipher with additional authenticated data.
195
+ *
196
+ * **Security Warning**: The nonce MUST be unique for every encryption operation
197
+ * with the same key. Reusing a nonce completely breaks the security of the
198
+ * encryption scheme and can reveal plaintext.
199
+ *
200
+ * @param plaintext - The data to encrypt
201
+ * @param key - 32-byte encryption key
202
+ * @param nonce - 12-byte nonce (MUST be unique per encryption with the same key)
203
+ * @param aad - Additional authenticated data (not encrypted, but integrity-protected)
204
+ * @returns Tuple of [ciphertext, authTag] where authTag is 16 bytes
205
+ * @throws {CryptoError} If key is not 32 bytes or nonce is not 12 bytes
206
+ */
207
+ function aeadChaCha20Poly1305EncryptWithAad(plaintext, key, nonce, aad) {
208
+ if (key.length !== SYMMETRIC_KEY_SIZE) throw CryptoError.invalidParameter(`Key must be ${SYMMETRIC_KEY_SIZE} bytes`);
209
+ if (nonce.length !== SYMMETRIC_NONCE_SIZE) throw CryptoError.invalidParameter(`Nonce must be ${SYMMETRIC_NONCE_SIZE} bytes`);
210
+ const sealed = (0, _noble_ciphers_chacha_js.chacha20poly1305)(key, nonce, aad).encrypt(plaintext);
211
+ return [sealed.slice(0, sealed.length - SYMMETRIC_AUTH_SIZE), sealed.slice(sealed.length - SYMMETRIC_AUTH_SIZE)];
212
+ }
213
+ /**
214
+ * Decrypt data using ChaCha20-Poly1305 AEAD cipher.
215
+ *
216
+ * @param ciphertext - The encrypted data
217
+ * @param key - 32-byte encryption key (must match key used for encryption)
218
+ * @param nonce - 12-byte nonce (must match nonce used for encryption)
219
+ * @param authTag - 16-byte authentication tag from encryption
220
+ * @returns Decrypted plaintext
221
+ * @throws {CryptoError} If key/nonce/authTag sizes are invalid
222
+ * @throws {CryptoError} If authentication fails (tampered data or wrong key/nonce)
223
+ */
224
+ function aeadChaCha20Poly1305Decrypt(ciphertext, key, nonce, authTag) {
225
+ return aeadChaCha20Poly1305DecryptWithAad(ciphertext, key, nonce, new Uint8Array(0), authTag);
226
+ }
227
+ /**
228
+ * Decrypt data using ChaCha20-Poly1305 AEAD cipher with additional authenticated data.
229
+ *
230
+ * @param ciphertext - The encrypted data
231
+ * @param key - 32-byte encryption key (must match key used for encryption)
232
+ * @param nonce - 12-byte nonce (must match nonce used for encryption)
233
+ * @param aad - Additional authenticated data (must exactly match AAD used for encryption)
234
+ * @param authTag - 16-byte authentication tag from encryption
235
+ * @returns Decrypted plaintext
236
+ * @throws {CryptoError} If key/nonce/authTag sizes are invalid
237
+ * @throws {CryptoError} If authentication fails (tampered data, wrong key/nonce, or AAD mismatch)
238
+ */
239
+ function aeadChaCha20Poly1305DecryptWithAad(ciphertext, key, nonce, aad, authTag) {
240
+ if (key.length !== SYMMETRIC_KEY_SIZE) throw CryptoError.invalidParameter(`Key must be ${SYMMETRIC_KEY_SIZE} bytes`);
241
+ if (nonce.length !== SYMMETRIC_NONCE_SIZE) throw CryptoError.invalidParameter(`Nonce must be ${SYMMETRIC_NONCE_SIZE} bytes`);
242
+ if (authTag.length !== SYMMETRIC_AUTH_SIZE) throw CryptoError.invalidParameter(`Auth tag must be ${SYMMETRIC_AUTH_SIZE} bytes`);
243
+ const sealed = new Uint8Array(ciphertext.length + authTag.length);
244
+ sealed.set(ciphertext);
245
+ sealed.set(authTag, ciphertext.length);
246
+ try {
247
+ return (0, _noble_ciphers_chacha_js.chacha20poly1305)(key, nonce, aad).decrypt(sealed);
248
+ } catch (error) {
249
+ const aeadError = new AeadError(`Decryption failed: ${error instanceof Error ? error.message : "authentication error"}`);
250
+ throw CryptoError.aead(aeadError);
251
+ }
252
+ }
253
+
254
+ //#endregion
255
+ //#region src/public-key-encryption.ts
256
+ const GENERIC_PRIVATE_KEY_SIZE = 32;
257
+ const GENERIC_PUBLIC_KEY_SIZE = 32;
258
+ const X25519_PRIVATE_KEY_SIZE = 32;
259
+ const X25519_PUBLIC_KEY_SIZE = 32;
260
+ /**
261
+ * Derive an X25519 agreement private key from key material.
262
+ * Uses HKDF with "agreement" as domain separation salt.
263
+ */
264
+ function deriveAgreementPrivateKey(keyMaterial) {
265
+ return hkdfHmacSha256(keyMaterial, new TextEncoder().encode("agreement"), X25519_PRIVATE_KEY_SIZE);
266
+ }
267
+ /**
268
+ * Derive a signing private key from key material.
269
+ * Uses HKDF with "signing" as domain separation salt.
270
+ */
271
+ function deriveSigningPrivateKey(keyMaterial) {
272
+ return hkdfHmacSha256(keyMaterial, new TextEncoder().encode("signing"), 32);
273
+ }
274
+ /**
275
+ * Generate a new random X25519 private key.
276
+ */
277
+ function x25519NewPrivateKeyUsing(rng) {
278
+ return rng.randomData(X25519_PRIVATE_KEY_SIZE);
279
+ }
280
+ /**
281
+ * Derive an X25519 public key from a private key.
282
+ */
283
+ function x25519PublicKeyFromPrivateKey(privateKey) {
284
+ if (privateKey.length !== X25519_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${X25519_PRIVATE_KEY_SIZE} bytes`);
285
+ return _noble_curves_ed25519_js.x25519.getPublicKey(privateKey);
286
+ }
287
+ /**
288
+ * Compute a shared secret using X25519 key agreement (ECDH).
289
+ *
290
+ * **Security Note**: The resulting shared secret should be used with a KDF
291
+ * (like HKDF) before using it as an encryption key. Never use the raw
292
+ * shared secret directly for encryption.
293
+ *
294
+ * @param x25519Private - 32-byte X25519 private key
295
+ * @param x25519Public - 32-byte X25519 public key from the other party
296
+ * @returns 32-byte shared secret
297
+ * @throws {Error} If private key is not 32 bytes or public key is not 32 bytes
298
+ */
299
+ function x25519SharedKey(x25519Private, x25519Public) {
300
+ if (x25519Private.length !== X25519_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${X25519_PRIVATE_KEY_SIZE} bytes`);
301
+ if (x25519Public.length !== X25519_PUBLIC_KEY_SIZE) throw new Error(`Public key must be ${X25519_PUBLIC_KEY_SIZE} bytes`);
302
+ return _noble_curves_ed25519_js.x25519.getSharedSecret(x25519Private, x25519Public);
303
+ }
304
+
305
+ //#endregion
306
+ //#region src/ecdsa-keys.ts
307
+ const ECDSA_PRIVATE_KEY_SIZE = 32;
308
+ const ECDSA_PUBLIC_KEY_SIZE = 33;
309
+ const ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE = 65;
310
+ const ECDSA_MESSAGE_HASH_SIZE = 32;
311
+ const ECDSA_SIGNATURE_SIZE = 64;
312
+ const SCHNORR_PUBLIC_KEY_SIZE = 32;
313
+ /**
314
+ * Generate a new random ECDSA private key using secp256k1.
315
+ *
316
+ * Note: Unlike some implementations, this directly returns the random bytes
317
+ * without validation. The secp256k1 library will handle any edge cases when
318
+ * the key is used.
319
+ */
320
+ function ecdsaNewPrivateKeyUsing(rng) {
321
+ return rng.randomData(ECDSA_PRIVATE_KEY_SIZE);
322
+ }
323
+ /**
324
+ * Derive a compressed ECDSA public key from a private key.
325
+ */
326
+ function ecdsaPublicKeyFromPrivateKey(privateKey) {
327
+ if (privateKey.length !== ECDSA_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);
328
+ return _noble_curves_secp256k1_js.secp256k1.getPublicKey(privateKey, true);
329
+ }
330
+ /**
331
+ * Decompress a compressed public key to uncompressed format.
332
+ */
333
+ function ecdsaDecompressPublicKey(compressed) {
334
+ if (compressed.length !== ECDSA_PUBLIC_KEY_SIZE) throw new Error(`Compressed public key must be ${ECDSA_PUBLIC_KEY_SIZE} bytes`);
335
+ return _noble_curves_secp256k1_js.secp256k1.Point.fromBytes(compressed).toBytes(false);
336
+ }
337
+ /**
338
+ * Compress an uncompressed public key.
339
+ */
340
+ function ecdsaCompressPublicKey(uncompressed) {
341
+ if (uncompressed.length !== ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE) throw new Error(`Uncompressed public key must be ${ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE} bytes`);
342
+ return _noble_curves_secp256k1_js.secp256k1.Point.fromBytes(uncompressed).toBytes(true);
343
+ }
344
+ /**
345
+ * Derive an ECDSA private key from key material using HKDF.
346
+ *
347
+ * Note: This directly returns the HKDF output without validation,
348
+ * matching the Rust reference implementation behavior.
349
+ */
350
+ function ecdsaDerivePrivateKey(keyMaterial) {
351
+ return hkdfHmacSha256(keyMaterial, new TextEncoder().encode("signing"), ECDSA_PRIVATE_KEY_SIZE);
352
+ }
353
+ /**
354
+ * Extract the x-only (Schnorr) public key from a private key.
355
+ * This is used for BIP-340 Schnorr signatures.
356
+ */
357
+ function schnorrPublicKeyFromPrivateKey(privateKey) {
358
+ if (privateKey.length !== ECDSA_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);
359
+ return _noble_curves_secp256k1_js.secp256k1.getPublicKey(privateKey, false).slice(1, 33);
360
+ }
361
+
362
+ //#endregion
363
+ //#region src/ecdsa-signing.ts
364
+ /**
365
+ * Sign a message using ECDSA with secp256k1.
366
+ *
367
+ * The message is hashed with double SHA-256 before signing (Bitcoin standard).
368
+ *
369
+ * **Security Note**: The private key must be kept secret. ECDSA requires
370
+ * cryptographically secure random nonces internally; this is handled by
371
+ * the underlying library using RFC 6979 deterministic nonces.
372
+ *
373
+ * @param privateKey - 32-byte secp256k1 private key
374
+ * @param message - Message to sign (any length, will be double-SHA256 hashed)
375
+ * @returns 64-byte compact signature (r || s format)
376
+ * @throws {Error} If private key is not 32 bytes
377
+ */
378
+ function ecdsaSign(privateKey, message) {
379
+ if (privateKey.length !== ECDSA_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);
380
+ const messageHash = doubleSha256(message);
381
+ return _noble_curves_secp256k1_js.secp256k1.sign(messageHash, privateKey, { prehash: false });
382
+ }
383
+ /**
384
+ * Verify an ECDSA signature with secp256k1.
385
+ *
386
+ * The message is hashed with double SHA-256 before verification (Bitcoin standard).
387
+ *
388
+ * @param publicKey - 33-byte compressed secp256k1 public key
389
+ * @param signature - 64-byte compact signature (r || s format)
390
+ * @param message - Original message that was signed
391
+ * @returns `true` if signature is valid, `false` if signature verification fails
392
+ * @throws {Error} If public key is not 33 bytes or signature is not 64 bytes
393
+ */
394
+ function ecdsaVerify(publicKey, signature, message) {
395
+ if (publicKey.length !== ECDSA_PUBLIC_KEY_SIZE) throw new Error(`Public key must be ${ECDSA_PUBLIC_KEY_SIZE} bytes`);
396
+ if (signature.length !== ECDSA_SIGNATURE_SIZE) throw new Error(`Signature must be ${ECDSA_SIGNATURE_SIZE} bytes`);
397
+ try {
398
+ const messageHash = doubleSha256(message);
399
+ return _noble_curves_secp256k1_js.secp256k1.verify(signature, messageHash, publicKey, { prehash: false });
400
+ } catch {
401
+ return false;
402
+ }
403
+ }
404
+
405
+ //#endregion
406
+ //#region src/schnorr-signing.ts
407
+ const SCHNORR_SIGNATURE_SIZE = 64;
408
+ /**
409
+ * Sign a message using Schnorr signature (BIP-340).
410
+ * Uses secure random auxiliary randomness.
411
+ *
412
+ * @param ecdsaPrivateKey - 32-byte private key
413
+ * @param message - Message to sign (not pre-hashed, per BIP-340)
414
+ * @returns 64-byte Schnorr signature
415
+ */
416
+ function schnorrSign(ecdsaPrivateKey, message) {
417
+ return schnorrSignUsing(ecdsaPrivateKey, message, new _bcts_rand.SecureRandomNumberGenerator());
418
+ }
419
+ /**
420
+ * Sign a message using Schnorr signature with a custom RNG.
421
+ *
422
+ * @param ecdsaPrivateKey - 32-byte private key
423
+ * @param message - Message to sign
424
+ * @param rng - Random number generator for auxiliary randomness
425
+ * @returns 64-byte Schnorr signature
426
+ */
427
+ function schnorrSignUsing(ecdsaPrivateKey, message, rng) {
428
+ return schnorrSignWithAuxRand(ecdsaPrivateKey, message, rng.randomData(32));
429
+ }
430
+ /**
431
+ * Sign a message using Schnorr signature with specific auxiliary randomness.
432
+ * This is useful for deterministic signing in tests.
433
+ *
434
+ * @param ecdsaPrivateKey - 32-byte private key
435
+ * @param message - Message to sign
436
+ * @param auxRand - 32-byte auxiliary randomness (per BIP-340)
437
+ * @returns 64-byte Schnorr signature
438
+ */
439
+ function schnorrSignWithAuxRand(ecdsaPrivateKey, message, auxRand) {
440
+ if (ecdsaPrivateKey.length !== ECDSA_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${ECDSA_PRIVATE_KEY_SIZE} bytes`);
441
+ if (auxRand.length !== 32) throw new Error("Auxiliary randomness must be 32 bytes");
442
+ return _noble_curves_secp256k1_js.schnorr.sign(message, ecdsaPrivateKey, auxRand);
443
+ }
444
+ /**
445
+ * Verify a Schnorr signature (BIP-340).
446
+ *
447
+ * @param schnorrPublicKey - 32-byte x-only public key
448
+ * @param signature - 64-byte Schnorr signature
449
+ * @param message - Original message
450
+ * @returns true if signature is valid
451
+ */
452
+ function schnorrVerify(schnorrPublicKey, signature, message) {
453
+ if (schnorrPublicKey.length !== SCHNORR_PUBLIC_KEY_SIZE) throw new Error(`Public key must be ${SCHNORR_PUBLIC_KEY_SIZE} bytes`);
454
+ if (signature.length !== SCHNORR_SIGNATURE_SIZE) throw new Error(`Signature must be ${SCHNORR_SIGNATURE_SIZE} bytes`);
455
+ try {
456
+ return _noble_curves_secp256k1_js.schnorr.verify(signature, message, schnorrPublicKey);
457
+ } catch {
458
+ return false;
459
+ }
460
+ }
461
+
462
+ //#endregion
463
+ //#region src/ed25519-signing.ts
464
+ const ED25519_PUBLIC_KEY_SIZE = 32;
465
+ const ED25519_PRIVATE_KEY_SIZE = 32;
466
+ const ED25519_SIGNATURE_SIZE = 64;
467
+ /**
468
+ * Generate a new random Ed25519 private key.
469
+ */
470
+ function ed25519NewPrivateKeyUsing(rng) {
471
+ return rng.randomData(ED25519_PRIVATE_KEY_SIZE);
472
+ }
473
+ /**
474
+ * Derive an Ed25519 public key from a private key.
475
+ */
476
+ function ed25519PublicKeyFromPrivateKey(privateKey) {
477
+ if (privateKey.length !== ED25519_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${ED25519_PRIVATE_KEY_SIZE} bytes`);
478
+ return _noble_curves_ed25519_js.ed25519.getPublicKey(privateKey);
479
+ }
480
+ /**
481
+ * Sign a message using Ed25519.
482
+ *
483
+ * **Security Note**: The private key must be kept secret. The same private key
484
+ * can safely sign multiple messages.
485
+ *
486
+ * @param privateKey - 32-byte Ed25519 private key
487
+ * @param message - Message to sign (any length)
488
+ * @returns 64-byte Ed25519 signature
489
+ * @throws {Error} If private key is not 32 bytes
490
+ */
491
+ function ed25519Sign(privateKey, message) {
492
+ if (privateKey.length !== ED25519_PRIVATE_KEY_SIZE) throw new Error(`Private key must be ${ED25519_PRIVATE_KEY_SIZE} bytes`);
493
+ return _noble_curves_ed25519_js.ed25519.sign(message, privateKey);
494
+ }
495
+ /**
496
+ * Verify an Ed25519 signature.
497
+ *
498
+ * @param publicKey - 32-byte Ed25519 public key
499
+ * @param message - Original message that was signed
500
+ * @param signature - 64-byte Ed25519 signature
501
+ * @returns `true` if signature is valid, `false` if signature verification fails
502
+ * @throws {Error} If public key is not 32 bytes or signature is not 64 bytes
503
+ */
504
+ function ed25519Verify(publicKey, message, signature) {
505
+ if (publicKey.length !== ED25519_PUBLIC_KEY_SIZE) throw new Error(`Public key must be ${ED25519_PUBLIC_KEY_SIZE} bytes`);
506
+ if (signature.length !== ED25519_SIGNATURE_SIZE) throw new Error(`Signature must be ${ED25519_SIGNATURE_SIZE} bytes`);
507
+ try {
508
+ return _noble_curves_ed25519_js.ed25519.verify(signature, message, publicKey);
509
+ } catch {
510
+ return false;
511
+ }
512
+ }
513
+
514
+ //#endregion
515
+ //#region src/scrypt.ts
516
+ /**
517
+ * Derive a key using Scrypt with recommended parameters.
518
+ * Uses N=2^15 (32768), r=8, p=1 as recommended defaults.
519
+ *
520
+ * @param password - Password or passphrase
521
+ * @param salt - Salt value
522
+ * @param outputLen - Desired output length
523
+ * @returns Derived key
524
+ */
525
+ function scrypt(password, salt, outputLen) {
526
+ return scryptOpt(password, salt, outputLen, 15, 8, 1);
527
+ }
528
+ /**
529
+ * Derive a key using Scrypt with custom parameters.
530
+ *
531
+ * @param password - Password or passphrase
532
+ * @param salt - Salt value
533
+ * @param outputLen - Desired output length
534
+ * @param logN - Log2 of the CPU/memory cost parameter N (must be <64)
535
+ * @param r - Block size parameter (must be >0)
536
+ * @param p - Parallelization parameter (must be >0)
537
+ * @returns Derived key
538
+ */
539
+ function scryptOpt(password, salt, outputLen, logN, r, p) {
540
+ if (logN >= 64) throw new Error("logN must be <64");
541
+ if (r === 0) throw new Error("r must be >0");
542
+ if (p === 0) throw new Error("p must be >0");
543
+ return (0, _noble_hashes_scrypt_js.scrypt)(password, salt, {
544
+ N: 1 << logN,
545
+ r,
546
+ p,
547
+ dkLen: outputLen
548
+ });
549
+ }
550
+
551
+ //#endregion
552
+ //#region src/argon.ts
553
+ /**
554
+ * Derive a key using Argon2id with default parameters.
555
+ *
556
+ * @param password - Password or passphrase
557
+ * @param salt - Salt value (must be at least 8 bytes)
558
+ * @param outputLen - Desired output length
559
+ * @returns Derived key
560
+ */
561
+ function argon2idHash(password, salt, outputLen) {
562
+ return argon2idHashOpt(password, salt, outputLen, 3, 65536, 4);
563
+ }
564
+ /**
565
+ * Derive a key using Argon2id with custom parameters.
566
+ *
567
+ * @param password - Password or passphrase
568
+ * @param salt - Salt value (must be at least 8 bytes)
569
+ * @param outputLen - Desired output length
570
+ * @param iterations - Number of iterations (t)
571
+ * @param memory - Memory in KiB (m)
572
+ * @param parallelism - Degree of parallelism (p)
573
+ * @returns Derived key
574
+ */
575
+ function argon2idHashOpt(password, salt, outputLen, iterations, memory, parallelism) {
576
+ return (0, _noble_hashes_argon2_js.argon2id)(password, salt, {
577
+ t: iterations,
578
+ m: memory,
579
+ p: parallelism,
580
+ dkLen: outputLen
581
+ });
582
+ }
583
+
584
+ //#endregion
585
+ exports.AeadError = AeadError;
586
+ exports.CRC32_SIZE = CRC32_SIZE;
587
+ exports.CryptoError = CryptoError;
588
+ exports.ECDSA_MESSAGE_HASH_SIZE = ECDSA_MESSAGE_HASH_SIZE;
589
+ exports.ECDSA_PRIVATE_KEY_SIZE = ECDSA_PRIVATE_KEY_SIZE;
590
+ exports.ECDSA_PUBLIC_KEY_SIZE = ECDSA_PUBLIC_KEY_SIZE;
591
+ exports.ECDSA_SIGNATURE_SIZE = ECDSA_SIGNATURE_SIZE;
592
+ exports.ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE = ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE;
593
+ exports.ED25519_PRIVATE_KEY_SIZE = ED25519_PRIVATE_KEY_SIZE;
594
+ exports.ED25519_PUBLIC_KEY_SIZE = ED25519_PUBLIC_KEY_SIZE;
595
+ exports.ED25519_SIGNATURE_SIZE = ED25519_SIGNATURE_SIZE;
596
+ exports.GENERIC_PRIVATE_KEY_SIZE = GENERIC_PRIVATE_KEY_SIZE;
597
+ exports.GENERIC_PUBLIC_KEY_SIZE = GENERIC_PUBLIC_KEY_SIZE;
598
+ exports.SCHNORR_PUBLIC_KEY_SIZE = SCHNORR_PUBLIC_KEY_SIZE;
599
+ exports.SCHNORR_SIGNATURE_SIZE = SCHNORR_SIGNATURE_SIZE;
600
+ exports.SHA256_SIZE = SHA256_SIZE;
601
+ exports.SHA512_SIZE = SHA512_SIZE;
602
+ exports.SYMMETRIC_AUTH_SIZE = SYMMETRIC_AUTH_SIZE;
603
+ exports.SYMMETRIC_KEY_SIZE = SYMMETRIC_KEY_SIZE;
604
+ exports.SYMMETRIC_NONCE_SIZE = SYMMETRIC_NONCE_SIZE;
605
+ exports.X25519_PRIVATE_KEY_SIZE = X25519_PRIVATE_KEY_SIZE;
606
+ exports.X25519_PUBLIC_KEY_SIZE = X25519_PUBLIC_KEY_SIZE;
607
+ exports.aeadChaCha20Poly1305Decrypt = aeadChaCha20Poly1305Decrypt;
608
+ exports.aeadChaCha20Poly1305DecryptWithAad = aeadChaCha20Poly1305DecryptWithAad;
609
+ exports.aeadChaCha20Poly1305Encrypt = aeadChaCha20Poly1305Encrypt;
610
+ exports.aeadChaCha20Poly1305EncryptWithAad = aeadChaCha20Poly1305EncryptWithAad;
611
+ exports.argon2idHash = argon2idHash;
612
+ exports.argon2idHashOpt = argon2idHashOpt;
613
+ exports.crc32 = crc32;
614
+ exports.crc32Data = crc32Data;
615
+ exports.crc32DataOpt = crc32DataOpt;
616
+ exports.deriveAgreementPrivateKey = deriveAgreementPrivateKey;
617
+ exports.deriveSigningPrivateKey = deriveSigningPrivateKey;
618
+ exports.doubleSha256 = doubleSha256;
619
+ exports.ecdsaCompressPublicKey = ecdsaCompressPublicKey;
620
+ exports.ecdsaDecompressPublicKey = ecdsaDecompressPublicKey;
621
+ exports.ecdsaDerivePrivateKey = ecdsaDerivePrivateKey;
622
+ exports.ecdsaNewPrivateKeyUsing = ecdsaNewPrivateKeyUsing;
623
+ exports.ecdsaPublicKeyFromPrivateKey = ecdsaPublicKeyFromPrivateKey;
624
+ exports.ecdsaSign = ecdsaSign;
625
+ exports.ecdsaVerify = ecdsaVerify;
626
+ exports.ed25519NewPrivateKeyUsing = ed25519NewPrivateKeyUsing;
627
+ exports.ed25519PublicKeyFromPrivateKey = ed25519PublicKeyFromPrivateKey;
628
+ exports.ed25519Sign = ed25519Sign;
629
+ exports.ed25519Verify = ed25519Verify;
630
+ exports.hkdfHmacSha256 = hkdfHmacSha256;
631
+ exports.hkdfHmacSha512 = hkdfHmacSha512;
632
+ exports.hmacSha256 = hmacSha256;
633
+ exports.hmacSha512 = hmacSha512;
634
+ exports.memzero = memzero;
635
+ exports.memzeroVecVecU8 = memzeroVecVecU8;
636
+ exports.pbkdf2HmacSha256 = pbkdf2HmacSha256;
637
+ exports.pbkdf2HmacSha512 = pbkdf2HmacSha512;
638
+ exports.schnorrPublicKeyFromPrivateKey = schnorrPublicKeyFromPrivateKey;
639
+ exports.schnorrSign = schnorrSign;
640
+ exports.schnorrSignUsing = schnorrSignUsing;
641
+ exports.schnorrSignWithAuxRand = schnorrSignWithAuxRand;
642
+ exports.schnorrVerify = schnorrVerify;
643
+ exports.scrypt = scrypt;
644
+ exports.scryptOpt = scryptOpt;
645
+ exports.sha256 = sha256;
646
+ exports.sha512 = sha512;
647
+ exports.x25519NewPrivateKeyUsing = x25519NewPrivateKeyUsing;
648
+ exports.x25519PublicKeyFromPrivateKey = x25519PublicKeyFromPrivateKey;
649
+ exports.x25519SharedKey = x25519SharedKey;
650
+ return exports;
651
+ })({}, nobleHashesSha2, nobleHashesHmac, nobleHashesPbkdf2, nobleHashesHkdf, nobleCiphersChacha, nobleCurvesEd25519, nobleCurvesSecp256k1, bctsRand, nobleHashesScrypt, nobleHashesArgon2);
652
+ //# sourceMappingURL=index.iife.js.map