@opendatalabs/vana-sdk 0.1.0-alpha.5f8458e → 0.1.0-alpha.606fa2d

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.
Files changed (50) hide show
  1. package/README.md +55 -4
  2. package/dist/{browser-cRpdLQ3-.d.ts → browser-Bb8gLWHp.d.ts} +61 -10
  3. package/dist/browser.d.ts +1 -1
  4. package/dist/browser.js +745 -113
  5. package/dist/browser.js.map +1 -1
  6. package/dist/chains.browser.cjs +2 -2
  7. package/dist/chains.browser.cjs.map +1 -1
  8. package/dist/chains.browser.js +2 -2
  9. package/dist/chains.browser.js.map +1 -1
  10. package/dist/chains.cjs +2 -2
  11. package/dist/chains.cjs.map +1 -1
  12. package/dist/chains.js +2 -2
  13. package/dist/chains.js.map +1 -1
  14. package/dist/chains.node.cjs +2 -2
  15. package/dist/chains.node.cjs.map +1 -1
  16. package/dist/chains.node.js +2 -2
  17. package/dist/chains.node.js.map +1 -1
  18. package/dist/index.browser.d.ts +1348 -243
  19. package/dist/index.browser.js +35080 -32770
  20. package/dist/index.browser.js.map +1 -1
  21. package/dist/index.node.cjs +35587 -33174
  22. package/dist/index.node.cjs.map +1 -1
  23. package/dist/index.node.d.cts +1136 -250
  24. package/dist/index.node.d.ts +1136 -250
  25. package/dist/index.node.js +35459 -33037
  26. package/dist/index.node.js.map +1 -1
  27. package/dist/{node-CkdgwBiv.d.cts → node-D9-F9uEP.d.cts} +3 -2
  28. package/dist/{node-CkdgwBiv.d.ts → node-D9-F9uEP.d.ts} +3 -2
  29. package/dist/node.cjs +704 -67
  30. package/dist/node.cjs.map +1 -1
  31. package/dist/node.d.cts +1 -1
  32. package/dist/node.d.ts +1 -1
  33. package/dist/node.js +716 -66
  34. package/dist/node.js.map +1 -1
  35. package/dist/platform.browser.d.ts +2 -2
  36. package/dist/platform.browser.js +808 -121
  37. package/dist/platform.browser.js.map +1 -1
  38. package/dist/platform.cjs +973 -186
  39. package/dist/platform.cjs.map +1 -1
  40. package/dist/platform.d.cts +1 -1
  41. package/dist/platform.d.ts +1 -1
  42. package/dist/platform.js +985 -186
  43. package/dist/platform.js.map +1 -1
  44. package/dist/platform.node.cjs +973 -186
  45. package/dist/platform.node.cjs.map +1 -1
  46. package/dist/platform.node.d.cts +63 -12
  47. package/dist/platform.node.d.ts +63 -12
  48. package/dist/platform.node.js +985 -186
  49. package/dist/platform.node.js.map +1 -1
  50. package/package.json +40 -23
package/dist/node.js CHANGED
@@ -1,26 +1,9 @@
1
- // src/platform/node.ts
2
- import { randomBytes } from "crypto";
3
- import * as openpgp from "openpgp";
4
-
5
- // src/platform/shared/crypto-utils.ts
6
- function processWalletPublicKey(publicKey) {
7
- const publicKeyHex = publicKey.startsWith("0x") ? publicKey.slice(2) : publicKey;
8
- const publicKeyBytes = Buffer.from(publicKeyHex, "hex");
9
- return publicKeyBytes.length === 64 ? Buffer.concat([Buffer.from([4]), publicKeyBytes]) : publicKeyBytes;
10
- }
11
- function processWalletPrivateKey(privateKey) {
12
- const privateKeyHex = privateKey.startsWith("0x") ? privateKey.slice(2) : privateKey;
13
- return Buffer.from(privateKeyHex, "hex");
14
- }
15
- function parseEncryptedDataBuffer(encryptedBuffer) {
16
- return {
17
- iv: encryptedBuffer.slice(0, 16),
18
- ephemPublicKey: encryptedBuffer.slice(16, 81),
19
- // 65 bytes for uncompressed public key
20
- ciphertext: encryptedBuffer.slice(81, -32),
21
- mac: encryptedBuffer.slice(-32)
22
- };
23
- }
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
24
7
 
25
8
  // src/platform/shared/pgp-utils.ts
26
9
  var STANDARD_PGP_CONFIG = {
@@ -76,30 +59,683 @@ async function streamToUint8Array(stream) {
76
59
  return result;
77
60
  }
78
61
 
79
- // src/platform/node.ts
80
- var eccrypto = null;
81
- async function getEccrypto() {
82
- if (!eccrypto) {
62
+ // src/utils/lazy-import.ts
63
+ function lazyImport(importFn) {
64
+ let cached = null;
65
+ return () => {
66
+ if (!cached) {
67
+ cached = importFn().catch((err) => {
68
+ cached = null;
69
+ throw new Error("Failed to load module", { cause: err });
70
+ });
71
+ }
72
+ return cached;
73
+ };
74
+ }
75
+
76
+ // src/utils/encoding.ts
77
+ function toHex(data) {
78
+ if (typeof Buffer !== "undefined" && Buffer.from) {
79
+ return Buffer.from(data).toString("hex");
80
+ }
81
+ return Array.from(data, (byte) => byte.toString(16).padStart(2, "0")).join(
82
+ ""
83
+ );
84
+ }
85
+ function fromHex(hex) {
86
+ const cleanHex = hex.startsWith("0x") ? hex.slice(2) : hex;
87
+ if (cleanHex.length % 2 !== 0) {
88
+ throw new Error("Invalid hex string: odd length");
89
+ }
90
+ if (!/^[0-9a-fA-F]*$/.test(cleanHex)) {
91
+ throw new Error("Invalid hex string: contains non-hex characters");
92
+ }
93
+ if (typeof Buffer !== "undefined" && Buffer.from) {
94
+ return new Uint8Array(Buffer.from(cleanHex, "hex"));
95
+ }
96
+ const bytes = new Uint8Array(cleanHex.length / 2);
97
+ for (let i = 0; i < cleanHex.length; i += 2) {
98
+ bytes[i / 2] = parseInt(cleanHex.substr(i, 2), 16);
99
+ }
100
+ return bytes;
101
+ }
102
+ function stringToBytes(str) {
103
+ if (typeof Buffer !== "undefined" && Buffer.from) {
104
+ return new Uint8Array(Buffer.from(str, "utf8"));
105
+ }
106
+ if (typeof TextEncoder !== "undefined") {
107
+ return new TextEncoder().encode(str);
108
+ }
109
+ const bytes = [];
110
+ for (let i = 0; i < str.length; i++) {
111
+ const char = str.charCodeAt(i);
112
+ if (char < 128) {
113
+ bytes.push(char);
114
+ } else if (char < 2048) {
115
+ bytes.push(192 | char >> 6, 128 | char & 63);
116
+ } else if (char < 55296 || char >= 57344) {
117
+ bytes.push(
118
+ 224 | char >> 12,
119
+ 128 | char >> 6 & 63,
120
+ 128 | char & 63
121
+ );
122
+ } else {
123
+ i++;
124
+ const char2 = str.charCodeAt(i);
125
+ const codePoint = 65536 + ((char & 1023) << 10 | char2 & 1023);
126
+ bytes.push(
127
+ 240 | codePoint >> 18,
128
+ 128 | codePoint >> 12 & 63,
129
+ 128 | codePoint >> 6 & 63,
130
+ 128 | codePoint & 63
131
+ );
132
+ }
133
+ }
134
+ return new Uint8Array(bytes);
135
+ }
136
+ function bytesToString(bytes) {
137
+ if (typeof Buffer !== "undefined" && Buffer.from) {
138
+ return Buffer.from(bytes).toString("utf8");
139
+ }
140
+ if (typeof TextDecoder !== "undefined") {
141
+ return new TextDecoder().decode(bytes);
142
+ }
143
+ let str = "";
144
+ let i = 0;
145
+ while (i < bytes.length) {
146
+ const byte = bytes[i];
147
+ if (byte < 128) {
148
+ str += String.fromCharCode(byte);
149
+ i++;
150
+ } else if ((byte & 224) === 192) {
151
+ str += String.fromCharCode((byte & 31) << 6 | bytes[i + 1] & 63);
152
+ i += 2;
153
+ } else if ((byte & 240) === 224) {
154
+ str += String.fromCharCode(
155
+ (byte & 15) << 12 | (bytes[i + 1] & 63) << 6 | bytes[i + 2] & 63
156
+ );
157
+ i += 3;
158
+ } else {
159
+ const codePoint = ((byte & 7) << 18 | (bytes[i + 1] & 63) << 12 | (bytes[i + 2] & 63) << 6 | bytes[i + 3] & 63) - 65536;
160
+ str += String.fromCharCode(
161
+ 55296 + (codePoint >> 10),
162
+ 56320 + (codePoint & 1023)
163
+ );
164
+ i += 4;
165
+ }
166
+ }
167
+ return str;
168
+ }
169
+
170
+ // src/utils/crypto-utils.ts
171
+ function concatBytes(...arrays) {
172
+ const totalLength = arrays.reduce((sum, arr) => sum + arr.length, 0);
173
+ const result = new Uint8Array(totalLength);
174
+ let offset = 0;
175
+ for (const arr of arrays) {
176
+ result.set(arr, offset);
177
+ offset += arr.length;
178
+ }
179
+ return result;
180
+ }
181
+ function hexToBytes(hex) {
182
+ return fromHex(hex);
183
+ }
184
+ function bytesToHex(bytes) {
185
+ return toHex(bytes);
186
+ }
187
+ function processWalletPublicKey(publicKey) {
188
+ const publicKeyHex = typeof publicKey === "string" ? publicKey.startsWith("0x") ? publicKey.slice(2) : publicKey : bytesToHex(publicKey);
189
+ const publicKeyBytes = hexToBytes(publicKeyHex);
190
+ return publicKeyBytes.length === 64 ? concatBytes(new Uint8Array([4]), publicKeyBytes) : publicKeyBytes;
191
+ }
192
+ function processWalletPrivateKey(privateKey) {
193
+ const privateKeyHex = typeof privateKey === "string" ? privateKey.startsWith("0x") ? privateKey.slice(2) : privateKey : bytesToHex(privateKey);
194
+ return hexToBytes(privateKeyHex);
195
+ }
196
+ function parseEncryptedDataBuffer(encryptedBuffer) {
197
+ return {
198
+ iv: encryptedBuffer.slice(0, 16),
199
+ ephemPublicKey: encryptedBuffer.slice(16, 81),
200
+ // 65 bytes for uncompressed public key
201
+ ciphertext: encryptedBuffer.slice(81, -32),
202
+ mac: encryptedBuffer.slice(-32)
203
+ };
204
+ }
205
+
206
+ // src/crypto/services/WalletKeyEncryptionService.ts
207
+ var WalletKeyEncryptionService = class {
208
+ eciesProvider;
209
+ constructor(config) {
210
+ this.eciesProvider = config.eciesProvider;
211
+ }
212
+ /**
213
+ * Encrypts data using a wallet's public key.
214
+ *
215
+ * @param data - The plaintext message to encrypt for the wallet owner.
216
+ * @param publicKey - The recipient wallet's public key for encryption.
217
+ * @returns A promise that resolves to the encrypted data as a hex string.
218
+ * @throws {Error} When encryption fails due to invalid key format.
219
+ *
220
+ * @example
221
+ * ```typescript
222
+ * const encrypted = await processor.encryptWithWalletPublicKey(
223
+ * "Secret message",
224
+ * "0x04..." // 65-byte uncompressed public key
225
+ * );
226
+ * console.log(`Encrypted: ${encrypted}`);
227
+ * ```
228
+ */
229
+ async encryptWithWalletPublicKey(data, publicKey) {
230
+ const publicKeyBytes = processWalletPublicKey(publicKey);
231
+ const dataBytes = stringToBytes(data);
232
+ const encrypted = await this.eciesProvider.encrypt(
233
+ publicKeyBytes,
234
+ dataBytes
235
+ );
236
+ const result = concatBytes(
237
+ encrypted.iv,
238
+ encrypted.ephemPublicKey,
239
+ encrypted.ciphertext,
240
+ encrypted.mac
241
+ );
242
+ return bytesToHex(result);
243
+ }
244
+ /**
245
+ * Decrypts data using a wallet's private key.
246
+ *
247
+ * @param encryptedData - The hex-encoded encrypted data to decrypt.
248
+ * @param privateKey - The wallet's private key for decryption.
249
+ * @returns A promise that resolves to the decrypted plaintext message.
250
+ * @throws {Error} When decryption fails due to invalid data or key format.
251
+ *
252
+ * @example
253
+ * ```typescript
254
+ * const decrypted = await processor.decryptWithWalletPrivateKey(
255
+ * encryptedHexString,
256
+ * "0x..." // 32-byte private key
257
+ * );
258
+ * console.log(`Decrypted: ${decrypted}`);
259
+ * ```
260
+ */
261
+ async decryptWithWalletPrivateKey(encryptedData, privateKey) {
262
+ const privateKeyBytes = processWalletPrivateKey(privateKey);
263
+ const encryptedBytes = hexToBytes(encryptedData);
264
+ const encrypted = parseEncryptedDataBuffer(encryptedBytes);
265
+ const decrypted = await this.eciesProvider.decrypt(
266
+ privateKeyBytes,
267
+ encrypted
268
+ );
269
+ return bytesToString(decrypted);
270
+ }
271
+ /**
272
+ * Encrypts a Uint8Array with a wallet public key
273
+ *
274
+ * @param data - Binary data to encrypt
275
+ * @param publicKey - Public key as hex string or Uint8Array
276
+ * @returns Encrypted data structure
277
+ */
278
+ async encryptBinary(data, publicKey) {
279
+ const publicKeyBytes = processWalletPublicKey(publicKey);
280
+ return this.eciesProvider.encrypt(publicKeyBytes, data);
281
+ }
282
+ /**
283
+ * Decrypts to a Uint8Array with a wallet private key
284
+ *
285
+ * @param encrypted - Encrypted data structure
286
+ * @param privateKey - Private key as hex string or Uint8Array
287
+ * @returns Decrypted binary data
288
+ */
289
+ async decryptBinary(encrypted, privateKey) {
290
+ const privateKeyBytes = processWalletPrivateKey(privateKey);
291
+ return this.eciesProvider.decrypt(privateKeyBytes, encrypted);
292
+ }
293
+ /**
294
+ * Gets the underlying ECIES provider
295
+ *
296
+ * @returns The ECIES provider instance
297
+ */
298
+ getECIESProvider() {
299
+ return this.eciesProvider;
300
+ }
301
+ };
302
+
303
+ // src/crypto/ecies/node.ts
304
+ import {
305
+ randomBytes,
306
+ createHash,
307
+ createHmac,
308
+ createCipheriv,
309
+ createDecipheriv
310
+ } from "crypto";
311
+
312
+ // src/crypto/ecies/constants.ts
313
+ var CURVE = {
314
+ /** The elliptic curve used (secp256k1 - same as Bitcoin/Ethereum) */
315
+ name: "secp256k1",
316
+ /** Private key length in bytes */
317
+ PRIVATE_KEY_LENGTH: 32,
318
+ /** Compressed public key length in bytes (0x02 or 0x03 prefix + 32 bytes) */
319
+ COMPRESSED_PUBLIC_KEY_LENGTH: 33,
320
+ /** Uncompressed public key length in bytes (0x04 prefix + 64 bytes) */
321
+ UNCOMPRESSED_PUBLIC_KEY_LENGTH: 65,
322
+ /** ECDH shared secret X coordinate length */
323
+ SHARED_SECRET_LENGTH: 32,
324
+ /** Public key prefixes */
325
+ PREFIX: {
326
+ /** Uncompressed public key prefix */
327
+ UNCOMPRESSED: 4,
328
+ /** Compressed public key prefix for even Y */
329
+ COMPRESSED_EVEN: 2,
330
+ /** Compressed public key prefix for odd Y */
331
+ COMPRESSED_ODD: 3
332
+ },
333
+ /** X coordinate starts at byte 1 (after prefix) */
334
+ X_COORDINATE_OFFSET: 1,
335
+ /** X coordinate ends at byte 33 (1 + 32) */
336
+ X_COORDINATE_END: 33
337
+ };
338
+ var CIPHER = {
339
+ /** Cipher algorithm - must match eccrypto */
340
+ algorithm: "aes-256-cbc",
341
+ /** AES key length in bytes */
342
+ KEY_LENGTH: 32,
343
+ /** Initialization vector length in bytes */
344
+ IV_LENGTH: 16,
345
+ /** Block size for AES */
346
+ BLOCK_SIZE: 16
347
+ };
348
+ var KDF = {
349
+ /** Hash algorithm for key derivation - must match eccrypto */
350
+ algorithm: "sha512",
351
+ /** Output length of SHA-512 in bytes */
352
+ OUTPUT_LENGTH: 64,
353
+ /** Encryption key slice (first 32 bytes of KDF output) */
354
+ ENCRYPTION_KEY_OFFSET: 0,
355
+ ENCRYPTION_KEY_LENGTH: 32,
356
+ /** MAC key slice (last 32 bytes of KDF output) */
357
+ MAC_KEY_OFFSET: 32,
358
+ MAC_KEY_LENGTH: 32
359
+ };
360
+ var MAC = {
361
+ /** MAC algorithm - must match eccrypto */
362
+ algorithm: "sha256",
363
+ /** HMAC-SHA256 output length in bytes */
364
+ LENGTH: 32
365
+ };
366
+ var FORMAT = {
367
+ /** Offsets for each component in serialized format */
368
+ IV_OFFSET: 0,
369
+ IV_LENGTH: CIPHER.IV_LENGTH,
370
+ /** Ephemeral public key (always uncompressed in eccrypto format) */
371
+ EPHEMERAL_KEY_OFFSET: CIPHER.IV_LENGTH,
372
+ EPHEMERAL_KEY_LENGTH: CURVE.UNCOMPRESSED_PUBLIC_KEY_LENGTH,
373
+ /** Ciphertext starts after IV and ephemeral key */
374
+ CIPHERTEXT_OFFSET: CIPHER.IV_LENGTH + CURVE.UNCOMPRESSED_PUBLIC_KEY_LENGTH,
375
+ /** MAC is always the last 32 bytes */
376
+ MAC_LENGTH: MAC.LENGTH,
377
+ /** Minimum size of encrypted data (IV + ephemKey + MAC, no ciphertext) */
378
+ MIN_ENCRYPTED_LENGTH: CIPHER.IV_LENGTH + CURVE.UNCOMPRESSED_PUBLIC_KEY_LENGTH + MAC.LENGTH,
379
+ /**
380
+ * Helper to calculate total length of encrypted data
381
+ *
382
+ * @param ciphertextLength - Length of the ciphertext portion
383
+ * @returns Total length including all components
384
+ */
385
+ getTotalLength: (ciphertextLength) => CIPHER.IV_LENGTH + CURVE.UNCOMPRESSED_PUBLIC_KEY_LENGTH + ciphertextLength + MAC.LENGTH
386
+ };
387
+
388
+ // src/crypto/ecies/interface.ts
389
+ var ECIESError = class extends Error {
390
+ constructor(message, code, cause) {
391
+ super(message);
392
+ this.code = code;
393
+ this.cause = cause;
394
+ this.name = "ECIESError";
395
+ }
396
+ };
397
+ function isECIESEncrypted(obj) {
398
+ if (!obj || typeof obj !== "object") return false;
399
+ const enc = obj;
400
+ const isUint8Array = (value) => {
401
+ return value instanceof Uint8Array || typeof Buffer !== "undefined" && Buffer.isBuffer(value);
402
+ };
403
+ return isUint8Array(enc.iv) && enc.iv.length === CIPHER.IV_LENGTH && isUint8Array(enc.ephemPublicKey) && (enc.ephemPublicKey.length === CURVE.UNCOMPRESSED_PUBLIC_KEY_LENGTH || enc.ephemPublicKey.length === CURVE.COMPRESSED_PUBLIC_KEY_LENGTH) && isUint8Array(enc.ciphertext) && enc.ciphertext.length > 0 && isUint8Array(enc.mac) && enc.mac.length === MAC.LENGTH;
404
+ }
405
+
406
+ // src/crypto/ecies/utils.ts
407
+ function concatBytes2(...arrays) {
408
+ const totalLength = arrays.reduce((sum, arr) => sum + arr.length, 0);
409
+ const result = new Uint8Array(totalLength);
410
+ let offset = 0;
411
+ for (const arr of arrays) {
412
+ result.set(arr, offset);
413
+ offset += arr.length;
414
+ }
415
+ return result;
416
+ }
417
+ function constantTimeEqual(a, b) {
418
+ if (a.length !== b.length) return false;
419
+ let result = 0;
420
+ for (let i = 0; i < a.length; i++) {
421
+ result |= a[i] ^ b[i];
422
+ }
423
+ return result === 0;
424
+ }
425
+
426
+ // src/crypto/ecies/base.ts
427
+ var BaseECIESUint8 = class _BaseECIESUint8 {
428
+ // Cache for validated public keys to avoid repeated validation
429
+ static validatedKeys = /* @__PURE__ */ new WeakMap();
430
+ /**
431
+ * Normalizes a public key to uncompressed format.
432
+ *
433
+ * @param publicKey - Public key in any format.
434
+ * @returns Uncompressed public key (65 bytes).
435
+ * @throws {ECIESError} If key format is invalid.
436
+ */
437
+ normalizePublicKey(publicKey) {
438
+ if (_BaseECIESUint8.validatedKeys.has(publicKey)) {
439
+ return publicKey;
440
+ }
441
+ if (publicKey.length === CURVE.UNCOMPRESSED_PUBLIC_KEY_LENGTH) {
442
+ if (publicKey[0] !== CURVE.PREFIX.UNCOMPRESSED) {
443
+ throw new ECIESError(
444
+ "Invalid uncompressed public key prefix",
445
+ "INVALID_KEY"
446
+ );
447
+ }
448
+ if (!this.validatePublicKey(publicKey)) {
449
+ throw new ECIESError("Invalid public key", "INVALID_KEY");
450
+ }
451
+ _BaseECIESUint8.validatedKeys.set(publicKey, true);
452
+ return publicKey;
453
+ }
454
+ if (publicKey.length === CURVE.COMPRESSED_PUBLIC_KEY_LENGTH) {
455
+ const decompressed = this.decompressPublicKey(publicKey);
456
+ if (!decompressed) {
457
+ throw new ECIESError("Failed to decompress public key", "INVALID_KEY");
458
+ }
459
+ _BaseECIESUint8.validatedKeys.set(decompressed, true);
460
+ return decompressed;
461
+ }
462
+ throw new ECIESError(
463
+ `Invalid public key length: ${publicKey.length}`,
464
+ "INVALID_KEY"
465
+ );
466
+ }
467
+ /**
468
+ * Encrypts data using ECIES.
469
+ *
470
+ * @param publicKey - The recipient's public key (compressed or uncompressed)
471
+ * @param message - The data to encrypt
472
+ * @returns Promise resolving to encrypted data structure
473
+ */
474
+ async encrypt(publicKey, message) {
83
475
  try {
84
- const eccryptoLib = await import("eccrypto");
85
- eccrypto = {
86
- encrypt: eccryptoLib.encrypt,
87
- decrypt: eccryptoLib.decrypt,
88
- getPublicCompressed: eccryptoLib.getPublicCompressed
476
+ if (!(publicKey instanceof Uint8Array)) {
477
+ throw new ECIESError("Public key must be a Uint8Array", "INVALID_KEY");
478
+ }
479
+ if (!(message instanceof Uint8Array)) {
480
+ throw new ECIESError(
481
+ "Message must be a Uint8Array",
482
+ "ENCRYPTION_FAILED"
483
+ );
484
+ }
485
+ if (publicKey.length === 0) {
486
+ throw new ECIESError("Public key cannot be empty", "INVALID_KEY");
487
+ }
488
+ const pubKey = this.normalizePublicKey(publicKey);
489
+ let ephemeralPrivateKey;
490
+ do {
491
+ ephemeralPrivateKey = this.generateRandomBytes(
492
+ CURVE.PRIVATE_KEY_LENGTH
493
+ );
494
+ } while (!this.verifyPrivateKey(ephemeralPrivateKey));
495
+ const ephemeralPublicKey = this.createPublicKey(
496
+ ephemeralPrivateKey,
497
+ false
498
+ );
499
+ if (!ephemeralPublicKey) {
500
+ throw new ECIESError(
501
+ "Failed to generate ephemeral public key",
502
+ "ENCRYPTION_FAILED"
503
+ );
504
+ }
505
+ const sharedSecret = this.performECDH(pubKey, ephemeralPrivateKey);
506
+ const kdf = this.sha512(sharedSecret);
507
+ const encryptionKey = kdf.slice(
508
+ KDF.ENCRYPTION_KEY_OFFSET,
509
+ KDF.ENCRYPTION_KEY_OFFSET + KDF.ENCRYPTION_KEY_LENGTH
510
+ );
511
+ const macKey = kdf.slice(
512
+ KDF.MAC_KEY_OFFSET,
513
+ KDF.MAC_KEY_OFFSET + KDF.MAC_KEY_LENGTH
514
+ );
515
+ const iv = this.generateRandomBytes(CIPHER.IV_LENGTH);
516
+ const ciphertext = await this.aesEncrypt(encryptionKey, iv, message);
517
+ const macData = concatBytes2(iv, ephemeralPublicKey, ciphertext);
518
+ const mac = this.hmacSha256(macKey, macData);
519
+ this.clearBuffer(ephemeralPrivateKey);
520
+ this.clearBuffer(sharedSecret);
521
+ this.clearBuffer(kdf);
522
+ return {
523
+ iv,
524
+ ephemPublicKey: ephemeralPublicKey,
525
+ ciphertext,
526
+ mac
89
527
  };
90
528
  } catch (error) {
91
- throw new Error(`Failed to load eccrypto library: ${error}`);
529
+ if (error instanceof ECIESError) throw error;
530
+ throw new ECIESError(
531
+ `Encryption failed: ${error instanceof Error ? error.message : "Unknown error"}`,
532
+ "ENCRYPTION_FAILED",
533
+ error instanceof Error ? error : void 0
534
+ );
535
+ }
536
+ }
537
+ /**
538
+ * Decrypts ECIES encrypted data.
539
+ *
540
+ * @param privateKey - The recipient's private key (32 bytes)
541
+ * @param encrypted - The encrypted data structure from encrypt()
542
+ * @returns Promise resolving to the original plaintext
543
+ */
544
+ async decrypt(privateKey, encrypted) {
545
+ try {
546
+ if (!(privateKey instanceof Uint8Array)) {
547
+ throw new ECIESError("Private key must be a Uint8Array", "INVALID_KEY");
548
+ }
549
+ if (!isECIESEncrypted(encrypted)) {
550
+ throw new ECIESError(
551
+ "Invalid encrypted data structure",
552
+ "DECRYPTION_FAILED"
553
+ );
554
+ }
555
+ if (privateKey.length !== CURVE.PRIVATE_KEY_LENGTH) {
556
+ throw new ECIESError(
557
+ `Invalid private key length: ${privateKey.length}`,
558
+ "INVALID_KEY"
559
+ );
560
+ }
561
+ if (!this.verifyPrivateKey(privateKey)) {
562
+ throw new ECIESError("Invalid private key", "INVALID_KEY");
563
+ }
564
+ const ephemeralPublicKey = this.normalizePublicKey(
565
+ encrypted.ephemPublicKey
566
+ );
567
+ const sharedSecret = this.performECDH(ephemeralPublicKey, privateKey);
568
+ const kdf = this.sha512(sharedSecret);
569
+ const encryptionKey = kdf.slice(
570
+ KDF.ENCRYPTION_KEY_OFFSET,
571
+ KDF.ENCRYPTION_KEY_OFFSET + KDF.ENCRYPTION_KEY_LENGTH
572
+ );
573
+ const macKey = kdf.slice(
574
+ KDF.MAC_KEY_OFFSET,
575
+ KDF.MAC_KEY_OFFSET + KDF.MAC_KEY_LENGTH
576
+ );
577
+ const macData = concatBytes2(
578
+ encrypted.iv,
579
+ encrypted.ephemPublicKey,
580
+ encrypted.ciphertext
581
+ );
582
+ const expectedMac = this.hmacSha256(macKey, macData);
583
+ if (!constantTimeEqual(encrypted.mac, expectedMac)) {
584
+ throw new ECIESError("MAC verification failed", "MAC_MISMATCH");
585
+ }
586
+ const decrypted = await this.aesDecrypt(
587
+ encryptionKey,
588
+ encrypted.iv,
589
+ encrypted.ciphertext
590
+ );
591
+ this.clearBuffer(sharedSecret);
592
+ this.clearBuffer(kdf);
593
+ return decrypted;
594
+ } catch (error) {
595
+ if (error instanceof ECIESError) throw error;
596
+ throw new ECIESError(
597
+ `Decryption failed: ${error instanceof Error ? error.message : "Unknown error"}`,
598
+ "DECRYPTION_FAILED",
599
+ error instanceof Error ? error : void 0
600
+ );
92
601
  }
93
602
  }
94
- return eccrypto;
603
+ /**
604
+ * Clears sensitive data from memory using multi-pass overwrite.
605
+ *
606
+ * @remarks
607
+ * Uses multiple passes with different patterns to make it harder
608
+ * for JIT compilers to optimize away the operation. While not
609
+ * guaranteed in JavaScript, this is a best-effort approach to
610
+ * clear sensitive data from memory.
611
+ *
612
+ * @param buffer - The buffer to clear
613
+ */
614
+ clearBuffer(buffer) {
615
+ if (buffer && buffer.length > 0) {
616
+ buffer.fill(0);
617
+ buffer.fill(255);
618
+ buffer.fill(170);
619
+ buffer.fill(0);
620
+ for (let i = 0; i < buffer.length; i++) {
621
+ buffer[i] = i & 255 ^ 90;
622
+ }
623
+ buffer.fill(0);
624
+ }
625
+ }
626
+ };
627
+
628
+ // src/crypto/ecies/node.ts
629
+ var secp256k1;
630
+ try {
631
+ secp256k1 = __require("secp256k1");
632
+ } catch {
633
+ throw new Error(
634
+ "Native secp256k1 module not found. Please install with: npm install secp256k1\nThis is required for optimal performance in Node.js environments."
635
+ );
95
636
  }
637
+ var NodeECIESUint8Provider = class extends BaseECIESUint8 {
638
+ // Identity hash function for ECDH - returns raw X coordinate
639
+ // CRITICAL: Must handle (x, y, output) signature correctly
640
+ identityHashFn = (x, y, output) => {
641
+ if (output && output.length >= 32) {
642
+ output.set(x);
643
+ return output;
644
+ }
645
+ return x;
646
+ };
647
+ generateRandomBytes(length) {
648
+ return new Uint8Array(randomBytes(length));
649
+ }
650
+ verifyPrivateKey(privateKey) {
651
+ return secp256k1.privateKeyVerify(Buffer.from(privateKey)) === true;
652
+ }
653
+ createPublicKey(privateKey, compressed) {
654
+ try {
655
+ return new Uint8Array(
656
+ secp256k1.publicKeyCreate(Buffer.from(privateKey), compressed)
657
+ );
658
+ } catch {
659
+ return null;
660
+ }
661
+ }
662
+ validatePublicKey(publicKey) {
663
+ return secp256k1.publicKeyVerify(Buffer.from(publicKey)) === true;
664
+ }
665
+ decompressPublicKey(publicKey) {
666
+ try {
667
+ return new Uint8Array(
668
+ secp256k1.publicKeyConvert(Buffer.from(publicKey), false)
669
+ );
670
+ } catch {
671
+ return null;
672
+ }
673
+ }
674
+ performECDH(publicKey, privateKey) {
675
+ try {
676
+ const output = Buffer.alloc(32);
677
+ secp256k1.ecdh(
678
+ Buffer.from(publicKey),
679
+ Buffer.from(privateKey),
680
+ { hashfn: this.identityHashFn },
681
+ output
682
+ );
683
+ return new Uint8Array(output);
684
+ } catch (error) {
685
+ throw new Error(
686
+ `ECDH failed: ${error instanceof Error ? error.message : "Unknown error"}`
687
+ );
688
+ }
689
+ }
690
+ sha512(data) {
691
+ return new Uint8Array(
692
+ createHash("sha512").update(Buffer.from(data)).digest()
693
+ );
694
+ }
695
+ hmacSha256(key, data) {
696
+ return new Uint8Array(
697
+ createHmac("sha256", Buffer.from(key)).update(Buffer.from(data)).digest()
698
+ );
699
+ }
700
+ async aesEncrypt(key, iv, plaintext) {
701
+ const cipher = createCipheriv(
702
+ "aes-256-cbc",
703
+ Buffer.from(key),
704
+ Buffer.from(iv)
705
+ );
706
+ const encrypted = Buffer.concat([
707
+ cipher.update(Buffer.from(plaintext)),
708
+ cipher.final()
709
+ ]);
710
+ return new Uint8Array(encrypted);
711
+ }
712
+ async aesDecrypt(key, iv, ciphertext) {
713
+ const decipher = createDecipheriv(
714
+ "aes-256-cbc",
715
+ Buffer.from(key),
716
+ Buffer.from(iv)
717
+ );
718
+ const decrypted = Buffer.concat([
719
+ decipher.update(Buffer.from(ciphertext)),
720
+ decipher.final()
721
+ ]);
722
+ return new Uint8Array(decrypted);
723
+ }
724
+ // No Buffer compatibility methods - Uint8Array only public API
725
+ };
726
+
727
+ // src/platform/node.ts
728
+ var getOpenPGP = lazyImport(() => import("openpgp"));
96
729
  var NodeCryptoAdapter = class {
730
+ eciesProvider = new NodeECIESUint8Provider();
731
+ walletKeyEncryptionService = new WalletKeyEncryptionService({
732
+ eciesProvider: this.eciesProvider
733
+ });
97
734
  async encryptWithPublicKey(data, publicKeyHex) {
98
735
  try {
99
- const eccryptoLib = await getEccrypto();
100
736
  const publicKey = Buffer.from(publicKeyHex, "hex");
101
737
  const message = Buffer.from(data, "utf8");
102
- const encrypted = await eccryptoLib.encrypt(publicKey, message);
738
+ const encrypted = await this.eciesProvider.encrypt(publicKey, message);
103
739
  const result = Buffer.concat([
104
740
  encrypted.iv,
105
741
  encrypted.ephemPublicKey,
@@ -108,30 +744,54 @@ var NodeCryptoAdapter = class {
108
744
  ]);
109
745
  return result.toString("hex");
110
746
  } catch (error) {
111
- throw new Error(`Encryption failed: ${error}`);
747
+ if (error instanceof ECIESError) {
748
+ throw error;
749
+ }
750
+ throw new ECIESError(
751
+ `Encryption failed: ${error instanceof Error ? error.message : String(error)}`,
752
+ "ENCRYPTION_FAILED",
753
+ error instanceof Error ? error : void 0
754
+ );
112
755
  }
113
756
  }
114
757
  async decryptWithPrivateKey(encryptedData, privateKeyHex) {
115
758
  try {
116
- const eccryptoLib = await getEccrypto();
117
759
  const privateKeyBuffer = processWalletPrivateKey(privateKeyHex);
118
760
  const encryptedBuffer = Buffer.from(encryptedData, "hex");
119
761
  const { iv, ephemPublicKey, ciphertext, mac } = parseEncryptedDataBuffer(encryptedBuffer);
120
- const encryptedObj = { iv, ephemPublicKey, ciphertext, mac };
121
- const decrypted = await eccryptoLib.decrypt(
762
+ const encryptedObj = {
763
+ iv,
764
+ ephemPublicKey,
765
+ ciphertext,
766
+ mac
767
+ };
768
+ const decrypted = await this.eciesProvider.decrypt(
122
769
  privateKeyBuffer,
123
770
  encryptedObj
124
771
  );
125
- return decrypted.toString("utf8");
772
+ return new TextDecoder().decode(decrypted);
126
773
  } catch (error) {
127
- throw new Error(`Decryption failed: ${error}`);
774
+ if (error instanceof ECIESError) {
775
+ throw error;
776
+ }
777
+ throw new ECIESError(
778
+ `Decryption failed: ${error instanceof Error ? error.message : String(error)}`,
779
+ "DECRYPTION_FAILED",
780
+ error instanceof Error ? error : void 0
781
+ );
128
782
  }
129
783
  }
130
784
  async generateKeyPair() {
131
785
  try {
132
- const eccryptoLib = await getEccrypto();
133
- const privateKey = randomBytes(32);
134
- const publicKey = eccryptoLib.getPublicCompressed(privateKey);
786
+ const { randomBytes: randomBytes2 } = await import("crypto");
787
+ const secp256k12 = await import("secp256k1");
788
+ let privateKey;
789
+ do {
790
+ privateKey = randomBytes2(32);
791
+ } while (!secp256k12.privateKeyVerify(privateKey));
792
+ const publicKey = Buffer.from(
793
+ secp256k12.publicKeyCreate(privateKey, true)
794
+ );
135
795
  return {
136
796
  privateKey: privateKey.toString("hex"),
137
797
  publicKey: publicKey.toString("hex")
@@ -142,41 +802,27 @@ var NodeCryptoAdapter = class {
142
802
  }
143
803
  async encryptWithWalletPublicKey(data, publicKey) {
144
804
  try {
145
- const eccryptoLib = await getEccrypto();
146
- const uncompressedKey = processWalletPublicKey(publicKey);
147
- const encrypted = await eccryptoLib.encrypt(
148
- uncompressedKey,
149
- Buffer.from(data)
805
+ return await this.walletKeyEncryptionService.encryptWithWalletPublicKey(
806
+ data,
807
+ publicKey
150
808
  );
151
- const result = Buffer.concat([
152
- encrypted.iv,
153
- encrypted.ephemPublicKey,
154
- encrypted.ciphertext,
155
- encrypted.mac
156
- ]);
157
- return result.toString("hex");
158
809
  } catch (error) {
159
810
  throw wrapCryptoError("encrypt with wallet public key", error);
160
811
  }
161
812
  }
162
813
  async decryptWithWalletPrivateKey(encryptedData, privateKey) {
163
814
  try {
164
- const eccryptoLib = await getEccrypto();
165
- const privateKeyBuffer = processWalletPrivateKey(privateKey);
166
- const encryptedBuffer = Buffer.from(encryptedData, "hex");
167
- const { iv, ephemPublicKey, ciphertext, mac } = parseEncryptedDataBuffer(encryptedBuffer);
168
- const encryptedObj = { iv, ephemPublicKey, ciphertext, mac };
169
- const decryptedBuffer = await eccryptoLib.decrypt(
170
- privateKeyBuffer,
171
- encryptedObj
815
+ return await this.walletKeyEncryptionService.decryptWithWalletPrivateKey(
816
+ encryptedData,
817
+ privateKey
172
818
  );
173
- return decryptedBuffer.toString("utf8");
174
819
  } catch (error) {
175
820
  throw wrapCryptoError("decrypt with wallet private key", error);
176
821
  }
177
822
  }
178
823
  async encryptWithPassword(data, password) {
179
824
  try {
825
+ const openpgp = await getOpenPGP();
180
826
  const message = await openpgp.createMessage({
181
827
  binary: data
182
828
  });
@@ -200,6 +846,7 @@ var NodeCryptoAdapter = class {
200
846
  }
201
847
  async decryptWithPassword(encryptedData, password) {
202
848
  try {
849
+ const openpgp = await getOpenPGP();
203
850
  const message = await openpgp.readMessage({
204
851
  binaryMessage: encryptedData
205
852
  });
@@ -217,6 +864,7 @@ var NodeCryptoAdapter = class {
217
864
  var NodePGPAdapter = class {
218
865
  async encrypt(data, publicKeyArmored) {
219
866
  try {
867
+ const openpgp = await getOpenPGP();
220
868
  const publicKey = await openpgp.readKey({ armoredKey: publicKeyArmored });
221
869
  const encrypted = await openpgp.encrypt({
222
870
  message: await openpgp.createMessage({ text: data }),
@@ -232,6 +880,7 @@ var NodePGPAdapter = class {
232
880
  }
233
881
  async decrypt(encryptedData, privateKeyArmored) {
234
882
  try {
883
+ const openpgp = await getOpenPGP();
235
884
  const privateKey = await openpgp.readPrivateKey({
236
885
  armoredKey: privateKeyArmored
237
886
  });
@@ -249,6 +898,7 @@ var NodePGPAdapter = class {
249
898
  }
250
899
  async generateKeyPair(options) {
251
900
  try {
901
+ const openpgp = await getOpenPGP();
252
902
  const keyGenParams = getPGPKeyGenParams(options);
253
903
  const { privateKey, publicKey } = await openpgp.generateKey(keyGenParams);
254
904
  return { publicKey, privateKey };