@bcts/crypto 1.0.0-alpha.9 → 1.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +3 -2
- package/dist/chunk-DQk6qfdC.mjs +18 -0
- package/dist/index.cjs +263 -149
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +134 -73
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +134 -73
- package/dist/index.d.mts.map +1 -1
- package/dist/index.iife.js +255 -141
- package/dist/index.iife.js.map +1 -1
- package/dist/index.mjs +223 -124
- package/dist/index.mjs.map +1 -1
- package/package.json +18 -19
- package/src/argon.ts +14 -9
- package/src/ecdsa-keys.ts +11 -5
- package/src/ecdsa-signing.ts +11 -6
- package/src/ed25519-signing.ts +7 -1
- package/src/error.ts +15 -0
- package/src/hash.ts +10 -4
- package/src/index.ts +24 -18
- package/src/memzero.ts +38 -12
- package/src/public-key-encryption.ts +31 -7
- package/src/schnorr-signing.ts +7 -1
- package/src/scrypt.ts +12 -3
- package/src/symmetric-encryption.ts +7 -1
package/dist/index.iife.js
CHANGED
|
@@ -1,78 +1,47 @@
|
|
|
1
|
-
var
|
|
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
2
|
|
|
3
|
-
|
|
4
|
-
//#region
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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;
|
|
3
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
|
+
//#region \0rolldown/runtime.js
|
|
5
|
+
var __defProp = Object.defineProperty;
|
|
6
|
+
var __exportAll = (all, no_symbols) => {
|
|
7
|
+
let target = {};
|
|
8
|
+
for (var name in all) {
|
|
9
|
+
__defProp(target, name, {
|
|
10
|
+
get: all[name],
|
|
11
|
+
enumerable: true
|
|
12
|
+
});
|
|
23
13
|
}
|
|
24
|
-
|
|
25
|
-
|
|
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}`);
|
|
14
|
+
if (!no_symbols) {
|
|
15
|
+
__defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
41
16
|
}
|
|
17
|
+
return target;
|
|
42
18
|
};
|
|
43
19
|
|
|
44
20
|
//#endregion
|
|
45
|
-
|
|
21
|
+
|
|
22
|
+
//#region src/hash.ts
|
|
46
23
|
/**
|
|
47
|
-
*
|
|
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.
|
|
24
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
25
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
58
26
|
*
|
|
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
27
|
*/
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
28
|
+
var hash_exports = /* @__PURE__ */ __exportAll({
|
|
29
|
+
CRC32_SIZE: () => 4,
|
|
30
|
+
SHA256_SIZE: () => 32,
|
|
31
|
+
SHA512_SIZE: () => 64,
|
|
32
|
+
crc32: () => crc32,
|
|
33
|
+
crc32Data: () => crc32Data,
|
|
34
|
+
crc32DataOpt: () => crc32DataOpt,
|
|
35
|
+
doubleSha256: () => doubleSha256,
|
|
36
|
+
hkdfHmacSha256: () => hkdfHmacSha256,
|
|
37
|
+
hkdfHmacSha512: () => hkdfHmacSha512,
|
|
38
|
+
hmacSha256: () => hmacSha256,
|
|
39
|
+
hmacSha512: () => hmacSha512,
|
|
40
|
+
pbkdf2HmacSha256: () => pbkdf2HmacSha256,
|
|
41
|
+
pbkdf2HmacSha512: () => pbkdf2HmacSha512,
|
|
42
|
+
sha256: () => sha256,
|
|
43
|
+
sha512: () => sha512
|
|
44
|
+
});
|
|
76
45
|
const CRC32_SIZE = 4;
|
|
77
46
|
const SHA256_SIZE = 32;
|
|
78
47
|
const SHA512_SIZE = 64;
|
|
@@ -111,7 +80,7 @@ var BCCrypto = (function(exports, __noble_hashes_sha2, __noble_hashes_hmac, __no
|
|
|
111
80
|
* Calculate SHA-256 hash
|
|
112
81
|
*/
|
|
113
82
|
function sha256(data) {
|
|
114
|
-
return (0,
|
|
83
|
+
return (0, _noble_hashes_sha2_js.sha256)(data);
|
|
115
84
|
}
|
|
116
85
|
/**
|
|
117
86
|
* Calculate double SHA-256 hash (SHA-256 of SHA-256)
|
|
@@ -124,25 +93,25 @@ var BCCrypto = (function(exports, __noble_hashes_sha2, __noble_hashes_hmac, __no
|
|
|
124
93
|
* Calculate SHA-512 hash
|
|
125
94
|
*/
|
|
126
95
|
function sha512(data) {
|
|
127
|
-
return (0,
|
|
96
|
+
return (0, _noble_hashes_sha2_js.sha512)(data);
|
|
128
97
|
}
|
|
129
98
|
/**
|
|
130
99
|
* Calculate HMAC-SHA-256
|
|
131
100
|
*/
|
|
132
101
|
function hmacSha256(key, message) {
|
|
133
|
-
return (0,
|
|
102
|
+
return (0, _noble_hashes_hmac_js.hmac)(_noble_hashes_sha2_js.sha256, key, message);
|
|
134
103
|
}
|
|
135
104
|
/**
|
|
136
105
|
* Calculate HMAC-SHA-512
|
|
137
106
|
*/
|
|
138
107
|
function hmacSha512(key, message) {
|
|
139
|
-
return (0,
|
|
108
|
+
return (0, _noble_hashes_hmac_js.hmac)(_noble_hashes_sha2_js.sha512, key, message);
|
|
140
109
|
}
|
|
141
110
|
/**
|
|
142
111
|
* Derive a key using PBKDF2 with HMAC-SHA-256
|
|
143
112
|
*/
|
|
144
113
|
function pbkdf2HmacSha256(password, salt, iterations, keyLen) {
|
|
145
|
-
return (0,
|
|
114
|
+
return (0, _noble_hashes_pbkdf2_js.pbkdf2)(_noble_hashes_sha2_js.sha256, password, salt, {
|
|
146
115
|
c: iterations,
|
|
147
116
|
dkLen: keyLen
|
|
148
117
|
});
|
|
@@ -151,7 +120,7 @@ var BCCrypto = (function(exports, __noble_hashes_sha2, __noble_hashes_hmac, __no
|
|
|
151
120
|
* Derive a key using PBKDF2 with HMAC-SHA-512
|
|
152
121
|
*/
|
|
153
122
|
function pbkdf2HmacSha512(password, salt, iterations, keyLen) {
|
|
154
|
-
return (0,
|
|
123
|
+
return (0, _noble_hashes_pbkdf2_js.pbkdf2)(_noble_hashes_sha2_js.sha512, password, salt, {
|
|
155
124
|
c: iterations,
|
|
156
125
|
dkLen: keyLen
|
|
157
126
|
});
|
|
@@ -160,17 +129,112 @@ var BCCrypto = (function(exports, __noble_hashes_sha2, __noble_hashes_hmac, __no
|
|
|
160
129
|
* Derive a key using HKDF with HMAC-SHA-256
|
|
161
130
|
*/
|
|
162
131
|
function hkdfHmacSha256(keyMaterial, salt, keyLen) {
|
|
163
|
-
return (0,
|
|
132
|
+
return (0, _noble_hashes_hkdf_js.hkdf)(_noble_hashes_sha2_js.sha256, keyMaterial, salt, void 0, keyLen);
|
|
164
133
|
}
|
|
165
134
|
/**
|
|
166
135
|
* Derive a key using HKDF with HMAC-SHA-512
|
|
167
136
|
*/
|
|
168
137
|
function hkdfHmacSha512(keyMaterial, salt, keyLen) {
|
|
169
|
-
return (0,
|
|
138
|
+
return (0, _noble_hashes_hkdf_js.hkdf)(_noble_hashes_sha2_js.sha512, keyMaterial, salt, void 0, keyLen);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
//#endregion
|
|
142
|
+
//#region src/error.ts
|
|
143
|
+
/**
|
|
144
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
145
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
146
|
+
*
|
|
147
|
+
*/
|
|
148
|
+
/**
|
|
149
|
+
* AEAD-specific error for authentication failures
|
|
150
|
+
*/
|
|
151
|
+
var AeadError = class extends Error {
|
|
152
|
+
constructor(message = "AEAD authentication failed") {
|
|
153
|
+
super(message);
|
|
154
|
+
this.name = "AeadError";
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
/**
|
|
158
|
+
* Generic crypto error type
|
|
159
|
+
*/
|
|
160
|
+
var CryptoError = class CryptoError extends Error {
|
|
161
|
+
cause;
|
|
162
|
+
constructor(message, cause) {
|
|
163
|
+
super(message);
|
|
164
|
+
this.name = "CryptoError";
|
|
165
|
+
this.cause = cause;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Create a CryptoError for AEAD authentication failures.
|
|
169
|
+
*
|
|
170
|
+
* @param error - Optional underlying AeadError
|
|
171
|
+
* @returns A CryptoError wrapping the AEAD error
|
|
172
|
+
*/
|
|
173
|
+
static aead(error) {
|
|
174
|
+
return new CryptoError("AEAD error", error ?? new AeadError());
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Create a CryptoError for invalid parameter values.
|
|
178
|
+
*
|
|
179
|
+
* **TS-specific.** Rust's `bc_crypto::Error` enum has no
|
|
180
|
+
* `InvalidParameter` variant; size validation in Rust is enforced at
|
|
181
|
+
* compile time via fixed-size array references (e.g. `&[u8; 32]`) or
|
|
182
|
+
* via `panic!`/`expect(...)` for runtime checks. The TS port has no
|
|
183
|
+
* fixed-size array types, so it surfaces those same conditions through
|
|
184
|
+
* a thrown `CryptoError.invalidParameter(...)`. Catching this is
|
|
185
|
+
* equivalent to defensive guards around an `expect`-style panic on the
|
|
186
|
+
* Rust side.
|
|
187
|
+
*
|
|
188
|
+
* @param message - Description of the invalid parameter
|
|
189
|
+
* @returns A CryptoError describing the invalid parameter
|
|
190
|
+
*/
|
|
191
|
+
static invalidParameter(message) {
|
|
192
|
+
return new CryptoError(`Invalid parameter: ${message}`);
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
//#endregion
|
|
197
|
+
//#region src/memzero.ts
|
|
198
|
+
/**
|
|
199
|
+
* Securely zero out a typed array.
|
|
200
|
+
*
|
|
201
|
+
* Mirrors Rust `bc_crypto::memzero<T>(s: &mut [T])`. The Rust impl uses
|
|
202
|
+
* `std::ptr::write_volatile()` to guarantee the writes survive optimization;
|
|
203
|
+
* JavaScript has no equivalent primitive, so this is **best-effort** — JIT
|
|
204
|
+
* compilers may still elide the loop, though the post-hoc verification
|
|
205
|
+
* check forces the engine to keep the writes observable.
|
|
206
|
+
*
|
|
207
|
+
* For truly sensitive cryptographic operations, consider using the Web
|
|
208
|
+
* Crypto API's `crypto.subtle` with non-extractable keys when possible, as
|
|
209
|
+
* it provides stronger guarantees than what can be achieved with pure
|
|
210
|
+
* JavaScript.
|
|
211
|
+
*
|
|
212
|
+
* Accepts any of the standard numeric typed arrays — `Uint8Array`,
|
|
213
|
+
* `Uint8ClampedArray`, `Uint16Array`, `Uint32Array`, `Int8Array`,
|
|
214
|
+
* `Int16Array`, `Int32Array`, `Float32Array`, `Float64Array` — matching
|
|
215
|
+
* Rust's generic `&mut [T]`. (`BigInt64Array` / `BigUint64Array` are
|
|
216
|
+
* excluded because their elements are `bigint`, not `number`; if that
|
|
217
|
+
* support is needed, add a dedicated overload.)
|
|
218
|
+
*/
|
|
219
|
+
function memzero(data) {
|
|
220
|
+
const len = data.length;
|
|
221
|
+
for (let i = 0; i < len; i++) data[i] = 0;
|
|
222
|
+
if (data.length > 0 && data[0] !== 0) throw new Error("memzero failed");
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Securely zero out an array of Uint8Arrays.
|
|
226
|
+
*/
|
|
227
|
+
function memzeroVecVecU8(arrays) {
|
|
228
|
+
for (const arr of arrays) memzero(arr);
|
|
170
229
|
}
|
|
171
230
|
|
|
172
231
|
//#endregion
|
|
173
232
|
//#region src/symmetric-encryption.ts
|
|
233
|
+
/**
|
|
234
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
235
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
236
|
+
*
|
|
237
|
+
*/
|
|
174
238
|
const SYMMETRIC_KEY_SIZE = 32;
|
|
175
239
|
const SYMMETRIC_NONCE_SIZE = 12;
|
|
176
240
|
const SYMMETRIC_AUTH_SIZE = 16;
|
|
@@ -205,10 +269,10 @@ var BCCrypto = (function(exports, __noble_hashes_sha2, __noble_hashes_hmac, __no
|
|
|
205
269
|
* @throws {CryptoError} If key is not 32 bytes or nonce is not 12 bytes
|
|
206
270
|
*/
|
|
207
271
|
function aeadChaCha20Poly1305EncryptWithAad(plaintext, key, nonce, aad) {
|
|
208
|
-
if (key.length !==
|
|
209
|
-
if (nonce.length !==
|
|
210
|
-
const sealed = (0,
|
|
211
|
-
return [sealed.slice(0, sealed.length -
|
|
272
|
+
if (key.length !== 32) throw CryptoError.invalidParameter(`Key must be ${32} bytes`);
|
|
273
|
+
if (nonce.length !== 12) throw CryptoError.invalidParameter(`Nonce must be ${12} bytes`);
|
|
274
|
+
const sealed = (0, _noble_ciphers_chacha_js.chacha20poly1305)(key, nonce, aad).encrypt(plaintext);
|
|
275
|
+
return [sealed.slice(0, sealed.length - 16), sealed.slice(sealed.length - 16)];
|
|
212
276
|
}
|
|
213
277
|
/**
|
|
214
278
|
* Decrypt data using ChaCha20-Poly1305 AEAD cipher.
|
|
@@ -237,14 +301,14 @@ var BCCrypto = (function(exports, __noble_hashes_sha2, __noble_hashes_hmac, __no
|
|
|
237
301
|
* @throws {CryptoError} If authentication fails (tampered data, wrong key/nonce, or AAD mismatch)
|
|
238
302
|
*/
|
|
239
303
|
function aeadChaCha20Poly1305DecryptWithAad(ciphertext, key, nonce, aad, authTag) {
|
|
240
|
-
if (key.length !==
|
|
241
|
-
if (nonce.length !==
|
|
242
|
-
if (authTag.length !==
|
|
304
|
+
if (key.length !== 32) throw CryptoError.invalidParameter(`Key must be ${32} bytes`);
|
|
305
|
+
if (nonce.length !== 12) throw CryptoError.invalidParameter(`Nonce must be ${12} bytes`);
|
|
306
|
+
if (authTag.length !== 16) throw CryptoError.invalidParameter(`Auth tag must be ${16} bytes`);
|
|
243
307
|
const sealed = new Uint8Array(ciphertext.length + authTag.length);
|
|
244
308
|
sealed.set(ciphertext);
|
|
245
309
|
sealed.set(authTag, ciphertext.length);
|
|
246
310
|
try {
|
|
247
|
-
return (0,
|
|
311
|
+
return (0, _noble_ciphers_chacha_js.chacha20poly1305)(key, nonce, aad).decrypt(sealed);
|
|
248
312
|
} catch (error) {
|
|
249
313
|
const aeadError = new AeadError(`Decryption failed: ${error instanceof Error ? error.message : "authentication error"}`);
|
|
250
314
|
throw CryptoError.aead(aeadError);
|
|
@@ -253,8 +317,11 @@ var BCCrypto = (function(exports, __noble_hashes_sha2, __noble_hashes_hmac, __no
|
|
|
253
317
|
|
|
254
318
|
//#endregion
|
|
255
319
|
//#region src/public-key-encryption.ts
|
|
256
|
-
|
|
257
|
-
|
|
320
|
+
/**
|
|
321
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
322
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
323
|
+
*
|
|
324
|
+
*/
|
|
258
325
|
const X25519_PRIVATE_KEY_SIZE = 32;
|
|
259
326
|
const X25519_PUBLIC_KEY_SIZE = 32;
|
|
260
327
|
/**
|
|
@@ -262,7 +329,7 @@ var BCCrypto = (function(exports, __noble_hashes_sha2, __noble_hashes_hmac, __no
|
|
|
262
329
|
* Uses HKDF with "agreement" as domain separation salt.
|
|
263
330
|
*/
|
|
264
331
|
function deriveAgreementPrivateKey(keyMaterial) {
|
|
265
|
-
return hkdfHmacSha256(keyMaterial, new TextEncoder().encode("agreement"),
|
|
332
|
+
return hkdfHmacSha256(keyMaterial, new TextEncoder().encode("agreement"), 32);
|
|
266
333
|
}
|
|
267
334
|
/**
|
|
268
335
|
* Derive a signing private key from key material.
|
|
@@ -275,35 +342,52 @@ var BCCrypto = (function(exports, __noble_hashes_sha2, __noble_hashes_hmac, __no
|
|
|
275
342
|
* Generate a new random X25519 private key.
|
|
276
343
|
*/
|
|
277
344
|
function x25519NewPrivateKeyUsing(rng) {
|
|
278
|
-
return rng.randomData(
|
|
345
|
+
return rng.randomData(32);
|
|
279
346
|
}
|
|
280
347
|
/**
|
|
281
348
|
* Derive an X25519 public key from a private key.
|
|
282
349
|
*/
|
|
283
350
|
function x25519PublicKeyFromPrivateKey(privateKey) {
|
|
284
|
-
if (privateKey.length !==
|
|
285
|
-
return
|
|
351
|
+
if (privateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
|
|
352
|
+
return _noble_curves_ed25519_js.x25519.getPublicKey(privateKey);
|
|
286
353
|
}
|
|
354
|
+
const SYMMETRIC_KEY_SIZE$1 = 32;
|
|
287
355
|
/**
|
|
288
|
-
* Compute a shared
|
|
356
|
+
* Compute a shared symmetric key using X25519 key agreement (ECDH).
|
|
289
357
|
*
|
|
290
|
-
*
|
|
291
|
-
*
|
|
292
|
-
*
|
|
358
|
+
* This function performs X25519 Diffie-Hellman key agreement and then
|
|
359
|
+
* derives a symmetric key using HKDF-SHA256 with "agreement" as the salt.
|
|
360
|
+
* This matches the Rust bc-crypto implementation for cross-platform compatibility.
|
|
361
|
+
*
|
|
362
|
+
* **Low-order public key handling.** The underlying `@noble/curves` X25519
|
|
363
|
+
* implementation rejects low-order public keys (where the u-coordinate is
|
|
364
|
+
* `0`) by throwing `'invalid private or public key received'`. Rust's
|
|
365
|
+
* `x25519-dalek` (v2.0-rc.2) instead silently produces the all-zero shared
|
|
366
|
+
* secret. This means an adversarial low-order public key fed in via TS
|
|
367
|
+
* surfaces as an exception, while in Rust it would yield an HKDF-derived
|
|
368
|
+
* key from a zero shared secret. For honest inputs both implementations
|
|
369
|
+
* produce byte-identical results; the TS port's stricter behaviour is a
|
|
370
|
+
* security improvement, not a parity bug.
|
|
293
371
|
*
|
|
294
372
|
* @param x25519Private - 32-byte X25519 private key
|
|
295
373
|
* @param x25519Public - 32-byte X25519 public key from the other party
|
|
296
|
-
* @returns 32-byte
|
|
374
|
+
* @returns 32-byte derived symmetric key
|
|
297
375
|
* @throws {Error} If private key is not 32 bytes or public key is not 32 bytes
|
|
376
|
+
* @throws {Error} If the public key is low-order (`@noble/curves`-specific guard)
|
|
298
377
|
*/
|
|
299
378
|
function x25519SharedKey(x25519Private, x25519Public) {
|
|
300
|
-
if (x25519Private.length !==
|
|
301
|
-
if (x25519Public.length !==
|
|
302
|
-
return
|
|
379
|
+
if (x25519Private.length !== 32) throw new Error(`Private key must be ${32} bytes`);
|
|
380
|
+
if (x25519Public.length !== 32) throw new Error(`Public key must be ${32} bytes`);
|
|
381
|
+
return hkdfHmacSha256(_noble_curves_ed25519_js.x25519.getSharedSecret(x25519Private, x25519Public), new TextEncoder().encode("agreement"), SYMMETRIC_KEY_SIZE$1);
|
|
303
382
|
}
|
|
304
383
|
|
|
305
384
|
//#endregion
|
|
306
385
|
//#region src/ecdsa-keys.ts
|
|
386
|
+
/**
|
|
387
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
388
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
389
|
+
*
|
|
390
|
+
*/
|
|
307
391
|
const ECDSA_PRIVATE_KEY_SIZE = 32;
|
|
308
392
|
const ECDSA_PUBLIC_KEY_SIZE = 33;
|
|
309
393
|
const ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE = 65;
|
|
@@ -318,28 +402,28 @@ var BCCrypto = (function(exports, __noble_hashes_sha2, __noble_hashes_hmac, __no
|
|
|
318
402
|
* the key is used.
|
|
319
403
|
*/
|
|
320
404
|
function ecdsaNewPrivateKeyUsing(rng) {
|
|
321
|
-
return rng.randomData(
|
|
405
|
+
return rng.randomData(32);
|
|
322
406
|
}
|
|
323
407
|
/**
|
|
324
408
|
* Derive a compressed ECDSA public key from a private key.
|
|
325
409
|
*/
|
|
326
410
|
function ecdsaPublicKeyFromPrivateKey(privateKey) {
|
|
327
|
-
if (privateKey.length !==
|
|
328
|
-
return
|
|
411
|
+
if (privateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
|
|
412
|
+
return _noble_curves_secp256k1_js.secp256k1.getPublicKey(privateKey, true);
|
|
329
413
|
}
|
|
330
414
|
/**
|
|
331
415
|
* Decompress a compressed public key to uncompressed format.
|
|
332
416
|
*/
|
|
333
417
|
function ecdsaDecompressPublicKey(compressed) {
|
|
334
|
-
if (compressed.length !==
|
|
335
|
-
return
|
|
418
|
+
if (compressed.length !== 33) throw new Error(`Compressed public key must be ${33} bytes`);
|
|
419
|
+
return _noble_curves_secp256k1_js.secp256k1.Point.fromBytes(compressed).toBytes(false);
|
|
336
420
|
}
|
|
337
421
|
/**
|
|
338
422
|
* Compress an uncompressed public key.
|
|
339
423
|
*/
|
|
340
424
|
function ecdsaCompressPublicKey(uncompressed) {
|
|
341
|
-
if (uncompressed.length !==
|
|
342
|
-
return
|
|
425
|
+
if (uncompressed.length !== 65) throw new Error(`Uncompressed public key must be ${65} bytes`);
|
|
426
|
+
return _noble_curves_secp256k1_js.secp256k1.Point.fromBytes(uncompressed).toBytes(true);
|
|
343
427
|
}
|
|
344
428
|
/**
|
|
345
429
|
* Derive an ECDSA private key from key material using HKDF.
|
|
@@ -348,20 +432,25 @@ var BCCrypto = (function(exports, __noble_hashes_sha2, __noble_hashes_hmac, __no
|
|
|
348
432
|
* matching the Rust reference implementation behavior.
|
|
349
433
|
*/
|
|
350
434
|
function ecdsaDerivePrivateKey(keyMaterial) {
|
|
351
|
-
return hkdfHmacSha256(keyMaterial, new TextEncoder().encode("signing"),
|
|
435
|
+
return hkdfHmacSha256(keyMaterial, new TextEncoder().encode("signing"), 32);
|
|
352
436
|
}
|
|
353
437
|
/**
|
|
354
438
|
* Extract the x-only (Schnorr) public key from a private key.
|
|
355
439
|
* This is used for BIP-340 Schnorr signatures.
|
|
356
440
|
*/
|
|
357
441
|
function schnorrPublicKeyFromPrivateKey(privateKey) {
|
|
358
|
-
if (privateKey.length !==
|
|
359
|
-
return
|
|
442
|
+
if (privateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
|
|
443
|
+
return _noble_curves_secp256k1_js.secp256k1.getPublicKey(privateKey, false).slice(1, 33);
|
|
360
444
|
}
|
|
361
445
|
|
|
362
446
|
//#endregion
|
|
363
447
|
//#region src/ecdsa-signing.ts
|
|
364
448
|
/**
|
|
449
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
450
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
451
|
+
*
|
|
452
|
+
*/
|
|
453
|
+
/**
|
|
365
454
|
* Sign a message using ECDSA with secp256k1.
|
|
366
455
|
*
|
|
367
456
|
* The message is hashed with double SHA-256 before signing (Bitcoin standard).
|
|
@@ -376,9 +465,9 @@ var BCCrypto = (function(exports, __noble_hashes_sha2, __noble_hashes_hmac, __no
|
|
|
376
465
|
* @throws {Error} If private key is not 32 bytes
|
|
377
466
|
*/
|
|
378
467
|
function ecdsaSign(privateKey, message) {
|
|
379
|
-
if (privateKey.length !==
|
|
468
|
+
if (privateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
|
|
380
469
|
const messageHash = doubleSha256(message);
|
|
381
|
-
return
|
|
470
|
+
return _noble_curves_secp256k1_js.secp256k1.sign(messageHash, privateKey, { prehash: false });
|
|
382
471
|
}
|
|
383
472
|
/**
|
|
384
473
|
* Verify an ECDSA signature with secp256k1.
|
|
@@ -392,11 +481,11 @@ var BCCrypto = (function(exports, __noble_hashes_sha2, __noble_hashes_hmac, __no
|
|
|
392
481
|
* @throws {Error} If public key is not 33 bytes or signature is not 64 bytes
|
|
393
482
|
*/
|
|
394
483
|
function ecdsaVerify(publicKey, signature, message) {
|
|
395
|
-
if (publicKey.length !==
|
|
396
|
-
if (signature.length !==
|
|
484
|
+
if (publicKey.length !== 33) throw new Error(`Public key must be ${33} bytes`);
|
|
485
|
+
if (signature.length !== 64) throw new Error(`Signature must be ${64} bytes`);
|
|
397
486
|
try {
|
|
398
487
|
const messageHash = doubleSha256(message);
|
|
399
|
-
return
|
|
488
|
+
return _noble_curves_secp256k1_js.secp256k1.verify(signature, messageHash, publicKey, { prehash: false });
|
|
400
489
|
} catch {
|
|
401
490
|
return false;
|
|
402
491
|
}
|
|
@@ -404,6 +493,11 @@ var BCCrypto = (function(exports, __noble_hashes_sha2, __noble_hashes_hmac, __no
|
|
|
404
493
|
|
|
405
494
|
//#endregion
|
|
406
495
|
//#region src/schnorr-signing.ts
|
|
496
|
+
/**
|
|
497
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
498
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
499
|
+
*
|
|
500
|
+
*/
|
|
407
501
|
const SCHNORR_SIGNATURE_SIZE = 64;
|
|
408
502
|
/**
|
|
409
503
|
* Sign a message using Schnorr signature (BIP-340).
|
|
@@ -414,7 +508,7 @@ var BCCrypto = (function(exports, __noble_hashes_sha2, __noble_hashes_hmac, __no
|
|
|
414
508
|
* @returns 64-byte Schnorr signature
|
|
415
509
|
*/
|
|
416
510
|
function schnorrSign(ecdsaPrivateKey, message) {
|
|
417
|
-
return schnorrSignUsing(ecdsaPrivateKey, message, new
|
|
511
|
+
return schnorrSignUsing(ecdsaPrivateKey, message, new _bcts_rand.SecureRandomNumberGenerator());
|
|
418
512
|
}
|
|
419
513
|
/**
|
|
420
514
|
* Sign a message using Schnorr signature with a custom RNG.
|
|
@@ -437,9 +531,9 @@ var BCCrypto = (function(exports, __noble_hashes_sha2, __noble_hashes_hmac, __no
|
|
|
437
531
|
* @returns 64-byte Schnorr signature
|
|
438
532
|
*/
|
|
439
533
|
function schnorrSignWithAuxRand(ecdsaPrivateKey, message, auxRand) {
|
|
440
|
-
if (ecdsaPrivateKey.length !==
|
|
534
|
+
if (ecdsaPrivateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
|
|
441
535
|
if (auxRand.length !== 32) throw new Error("Auxiliary randomness must be 32 bytes");
|
|
442
|
-
return
|
|
536
|
+
return _noble_curves_secp256k1_js.schnorr.sign(message, ecdsaPrivateKey, auxRand);
|
|
443
537
|
}
|
|
444
538
|
/**
|
|
445
539
|
* Verify a Schnorr signature (BIP-340).
|
|
@@ -450,10 +544,10 @@ var BCCrypto = (function(exports, __noble_hashes_sha2, __noble_hashes_hmac, __no
|
|
|
450
544
|
* @returns true if signature is valid
|
|
451
545
|
*/
|
|
452
546
|
function schnorrVerify(schnorrPublicKey, signature, message) {
|
|
453
|
-
if (schnorrPublicKey.length !==
|
|
454
|
-
if (signature.length !==
|
|
547
|
+
if (schnorrPublicKey.length !== 32) throw new Error(`Public key must be ${32} bytes`);
|
|
548
|
+
if (signature.length !== 64) throw new Error(`Signature must be ${64} bytes`);
|
|
455
549
|
try {
|
|
456
|
-
return
|
|
550
|
+
return _noble_curves_secp256k1_js.schnorr.verify(signature, message, schnorrPublicKey);
|
|
457
551
|
} catch {
|
|
458
552
|
return false;
|
|
459
553
|
}
|
|
@@ -461,6 +555,11 @@ var BCCrypto = (function(exports, __noble_hashes_sha2, __noble_hashes_hmac, __no
|
|
|
461
555
|
|
|
462
556
|
//#endregion
|
|
463
557
|
//#region src/ed25519-signing.ts
|
|
558
|
+
/**
|
|
559
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
560
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
561
|
+
*
|
|
562
|
+
*/
|
|
464
563
|
const ED25519_PUBLIC_KEY_SIZE = 32;
|
|
465
564
|
const ED25519_PRIVATE_KEY_SIZE = 32;
|
|
466
565
|
const ED25519_SIGNATURE_SIZE = 64;
|
|
@@ -468,14 +567,14 @@ var BCCrypto = (function(exports, __noble_hashes_sha2, __noble_hashes_hmac, __no
|
|
|
468
567
|
* Generate a new random Ed25519 private key.
|
|
469
568
|
*/
|
|
470
569
|
function ed25519NewPrivateKeyUsing(rng) {
|
|
471
|
-
return rng.randomData(
|
|
570
|
+
return rng.randomData(32);
|
|
472
571
|
}
|
|
473
572
|
/**
|
|
474
573
|
* Derive an Ed25519 public key from a private key.
|
|
475
574
|
*/
|
|
476
575
|
function ed25519PublicKeyFromPrivateKey(privateKey) {
|
|
477
|
-
if (privateKey.length !==
|
|
478
|
-
return
|
|
576
|
+
if (privateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
|
|
577
|
+
return _noble_curves_ed25519_js.ed25519.getPublicKey(privateKey);
|
|
479
578
|
}
|
|
480
579
|
/**
|
|
481
580
|
* Sign a message using Ed25519.
|
|
@@ -489,8 +588,8 @@ var BCCrypto = (function(exports, __noble_hashes_sha2, __noble_hashes_hmac, __no
|
|
|
489
588
|
* @throws {Error} If private key is not 32 bytes
|
|
490
589
|
*/
|
|
491
590
|
function ed25519Sign(privateKey, message) {
|
|
492
|
-
if (privateKey.length !==
|
|
493
|
-
return
|
|
591
|
+
if (privateKey.length !== 32) throw new Error(`Private key must be ${32} bytes`);
|
|
592
|
+
return _noble_curves_ed25519_js.ed25519.sign(message, privateKey);
|
|
494
593
|
}
|
|
495
594
|
/**
|
|
496
595
|
* Verify an Ed25519 signature.
|
|
@@ -502,10 +601,10 @@ var BCCrypto = (function(exports, __noble_hashes_sha2, __noble_hashes_hmac, __no
|
|
|
502
601
|
* @throws {Error} If public key is not 32 bytes or signature is not 64 bytes
|
|
503
602
|
*/
|
|
504
603
|
function ed25519Verify(publicKey, message, signature) {
|
|
505
|
-
if (publicKey.length !==
|
|
506
|
-
if (signature.length !==
|
|
604
|
+
if (publicKey.length !== 32) throw new Error(`Public key must be ${32} bytes`);
|
|
605
|
+
if (signature.length !== 64) throw new Error(`Signature must be ${64} bytes`);
|
|
507
606
|
try {
|
|
508
|
-
return
|
|
607
|
+
return _noble_curves_ed25519_js.ed25519.verify(signature, message, publicKey);
|
|
509
608
|
} catch {
|
|
510
609
|
return false;
|
|
511
610
|
}
|
|
@@ -514,8 +613,16 @@ var BCCrypto = (function(exports, __noble_hashes_sha2, __noble_hashes_hmac, __no
|
|
|
514
613
|
//#endregion
|
|
515
614
|
//#region src/scrypt.ts
|
|
516
615
|
/**
|
|
616
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
617
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
618
|
+
*
|
|
619
|
+
*/
|
|
620
|
+
/**
|
|
517
621
|
* Derive a key using Scrypt with recommended parameters.
|
|
518
|
-
*
|
|
622
|
+
*
|
|
623
|
+
* Mirrors Rust `bc_crypto::scrypt` which calls `scrypt::Params::recommended()`.
|
|
624
|
+
* The recommended parameters per the upstream `scrypt` crate are
|
|
625
|
+
* `log_n = 17` (N = 2^17 = 131072), `r = 8`, `p = 1`.
|
|
519
626
|
*
|
|
520
627
|
* @param password - Password or passphrase
|
|
521
628
|
* @param salt - Salt value
|
|
@@ -523,7 +630,7 @@ var BCCrypto = (function(exports, __noble_hashes_sha2, __noble_hashes_hmac, __no
|
|
|
523
630
|
* @returns Derived key
|
|
524
631
|
*/
|
|
525
632
|
function scrypt(password, salt, outputLen) {
|
|
526
|
-
return scryptOpt(password, salt, outputLen,
|
|
633
|
+
return scryptOpt(password, salt, outputLen, 17, 8, 1);
|
|
527
634
|
}
|
|
528
635
|
/**
|
|
529
636
|
* Derive a key using Scrypt with custom parameters.
|
|
@@ -540,7 +647,7 @@ var BCCrypto = (function(exports, __noble_hashes_sha2, __noble_hashes_hmac, __no
|
|
|
540
647
|
if (logN >= 64) throw new Error("logN must be <64");
|
|
541
648
|
if (r === 0) throw new Error("r must be >0");
|
|
542
649
|
if (p === 0) throw new Error("p must be >0");
|
|
543
|
-
return (0,
|
|
650
|
+
return (0, _noble_hashes_scrypt_js.scrypt)(password, salt, {
|
|
544
651
|
N: 1 << logN,
|
|
545
652
|
r,
|
|
546
653
|
p,
|
|
@@ -551,15 +658,24 @@ var BCCrypto = (function(exports, __noble_hashes_sha2, __noble_hashes_hmac, __no
|
|
|
551
658
|
//#endregion
|
|
552
659
|
//#region src/argon.ts
|
|
553
660
|
/**
|
|
661
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
662
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
663
|
+
*
|
|
664
|
+
*/
|
|
665
|
+
/**
|
|
554
666
|
* Derive a key using Argon2id with default parameters.
|
|
555
667
|
*
|
|
668
|
+
* Mirrors Rust `bc_crypto::argon2id` which calls `Argon2::default()`. The
|
|
669
|
+
* upstream `argon2` crate's defaults are `t = 2` iterations, `m = 19 * 1024
|
|
670
|
+
* = 19456` KiB of memory, `p = 1` lane (per `argon2-0.5.x/src/params.rs`).
|
|
671
|
+
*
|
|
556
672
|
* @param password - Password or passphrase
|
|
557
673
|
* @param salt - Salt value (must be at least 8 bytes)
|
|
558
674
|
* @param outputLen - Desired output length
|
|
559
675
|
* @returns Derived key
|
|
560
676
|
*/
|
|
561
|
-
function
|
|
562
|
-
return argon2idHashOpt(password, salt, outputLen,
|
|
677
|
+
function argon2id(password, salt, outputLen) {
|
|
678
|
+
return argon2idHashOpt(password, salt, outputLen, 2, 19456, 1);
|
|
563
679
|
}
|
|
564
680
|
/**
|
|
565
681
|
* Derive a key using Argon2id with custom parameters.
|
|
@@ -573,7 +689,7 @@ var BCCrypto = (function(exports, __noble_hashes_sha2, __noble_hashes_hmac, __no
|
|
|
573
689
|
* @returns Derived key
|
|
574
690
|
*/
|
|
575
691
|
function argon2idHashOpt(password, salt, outputLen, iterations, memory, parallelism) {
|
|
576
|
-
return (0,
|
|
692
|
+
return (0, _noble_hashes_argon2_js.argon2id)(password, salt, {
|
|
577
693
|
t: iterations,
|
|
578
694
|
m: memory,
|
|
579
695
|
p: parallelism,
|
|
@@ -593,8 +709,6 @@ exports.ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE = ECDSA_UNCOMPRESSED_PUBLIC_KEY_SIZE;
|
|
|
593
709
|
exports.ED25519_PRIVATE_KEY_SIZE = ED25519_PRIVATE_KEY_SIZE;
|
|
594
710
|
exports.ED25519_PUBLIC_KEY_SIZE = ED25519_PUBLIC_KEY_SIZE;
|
|
595
711
|
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
712
|
exports.SCHNORR_PUBLIC_KEY_SIZE = SCHNORR_PUBLIC_KEY_SIZE;
|
|
599
713
|
exports.SCHNORR_SIGNATURE_SIZE = SCHNORR_SIGNATURE_SIZE;
|
|
600
714
|
exports.SHA256_SIZE = SHA256_SIZE;
|
|
@@ -608,11 +722,7 @@ exports.aeadChaCha20Poly1305Decrypt = aeadChaCha20Poly1305Decrypt;
|
|
|
608
722
|
exports.aeadChaCha20Poly1305DecryptWithAad = aeadChaCha20Poly1305DecryptWithAad;
|
|
609
723
|
exports.aeadChaCha20Poly1305Encrypt = aeadChaCha20Poly1305Encrypt;
|
|
610
724
|
exports.aeadChaCha20Poly1305EncryptWithAad = aeadChaCha20Poly1305EncryptWithAad;
|
|
611
|
-
exports.
|
|
612
|
-
exports.argon2idHashOpt = argon2idHashOpt;
|
|
613
|
-
exports.crc32 = crc32;
|
|
614
|
-
exports.crc32Data = crc32Data;
|
|
615
|
-
exports.crc32DataOpt = crc32DataOpt;
|
|
725
|
+
exports.argon2id = argon2id;
|
|
616
726
|
exports.deriveAgreementPrivateKey = deriveAgreementPrivateKey;
|
|
617
727
|
exports.deriveSigningPrivateKey = deriveSigningPrivateKey;
|
|
618
728
|
exports.doubleSha256 = doubleSha256;
|
|
@@ -627,14 +737,18 @@ exports.ed25519NewPrivateKeyUsing = ed25519NewPrivateKeyUsing;
|
|
|
627
737
|
exports.ed25519PublicKeyFromPrivateKey = ed25519PublicKeyFromPrivateKey;
|
|
628
738
|
exports.ed25519Sign = ed25519Sign;
|
|
629
739
|
exports.ed25519Verify = ed25519Verify;
|
|
740
|
+
Object.defineProperty(exports, 'hash', {
|
|
741
|
+
enumerable: true,
|
|
742
|
+
get: function () {
|
|
743
|
+
return hash_exports;
|
|
744
|
+
}
|
|
745
|
+
});
|
|
630
746
|
exports.hkdfHmacSha256 = hkdfHmacSha256;
|
|
631
|
-
exports.hkdfHmacSha512 = hkdfHmacSha512;
|
|
632
747
|
exports.hmacSha256 = hmacSha256;
|
|
633
748
|
exports.hmacSha512 = hmacSha512;
|
|
634
749
|
exports.memzero = memzero;
|
|
635
750
|
exports.memzeroVecVecU8 = memzeroVecVecU8;
|
|
636
751
|
exports.pbkdf2HmacSha256 = pbkdf2HmacSha256;
|
|
637
|
-
exports.pbkdf2HmacSha512 = pbkdf2HmacSha512;
|
|
638
752
|
exports.schnorrPublicKeyFromPrivateKey = schnorrPublicKeyFromPrivateKey;
|
|
639
753
|
exports.schnorrSign = schnorrSign;
|
|
640
754
|
exports.schnorrSignUsing = schnorrSignUsing;
|
|
@@ -648,5 +762,5 @@ exports.x25519NewPrivateKeyUsing = x25519NewPrivateKeyUsing;
|
|
|
648
762
|
exports.x25519PublicKeyFromPrivateKey = x25519PublicKeyFromPrivateKey;
|
|
649
763
|
exports.x25519SharedKey = x25519SharedKey;
|
|
650
764
|
return exports;
|
|
651
|
-
})({}, nobleHashesSha2, nobleHashesHmac, nobleHashesPbkdf2, nobleHashesHkdf, nobleCiphersChacha, nobleCurvesEd25519, nobleCurvesSecp256k1,
|
|
765
|
+
})({}, nobleHashesSha2, nobleHashesHmac, nobleHashesPbkdf2, nobleHashesHkdf, nobleCiphersChacha, nobleCurvesEd25519, nobleCurvesSecp256k1, bctsRand, nobleHashesScrypt, nobleHashesArgon2);
|
|
652
766
|
//# sourceMappingURL=index.iife.js.map
|