@wishknish/knishio-client-ts 0.9.6 → 0.9.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -521,6 +521,55 @@ var init_TransferBalanceException = __esm({
521
521
  }
522
522
  });
523
523
 
524
+ // src/exception/SecretStorageException.ts
525
+ var SecretStorageException;
526
+ var init_SecretStorageException = __esm({
527
+ "src/exception/SecretStorageException.ts"() {
528
+ init_BaseException();
529
+ SecretStorageException = class _SecretStorageException extends BaseException {
530
+ constructor(message = "Secret storage operation failed", options = {}) {
531
+ super("WALLET_CREDENTIAL_ERROR", message, {
532
+ code: "SECRET_STORAGE_ERROR",
533
+ ...options
534
+ });
535
+ }
536
+ /**
537
+ * Secret not found for the requested bundle hash
538
+ */
539
+ static notFound(bundleHash) {
540
+ return new _SecretStorageException(`Secret not found for bundle: ${bundleHash}`, {
541
+ code: "SECRET_NOT_FOUND",
542
+ details: { bundleHash }
543
+ });
544
+ }
545
+ /**
546
+ * Decryption failed (wrong passphrase or corrupted payload)
547
+ */
548
+ static decryptionFailed(reason) {
549
+ return new _SecretStorageException(
550
+ `Failed to decrypt master secret: ${reason || "Invalid passphrase or corrupted ciphertext"}`,
551
+ {
552
+ code: "DECRYPTION_FAILED",
553
+ details: { reason }
554
+ }
555
+ );
556
+ }
557
+ /**
558
+ * Provider is unavailable in current platform
559
+ */
560
+ static unavailable(provider, reason) {
561
+ return new _SecretStorageException(
562
+ `Secret storage provider '${provider}' is unavailable: ${reason || "Hardware or API not accessible"}`,
563
+ {
564
+ code: "STORAGE_UNAVAILABLE",
565
+ details: { provider, reason }
566
+ }
567
+ );
568
+ }
569
+ };
570
+ }
571
+ });
572
+
524
573
  // src/exception/InvalidResponseException.ts
525
574
  var InvalidResponseException;
526
575
  var init_InvalidResponseException = __esm({
@@ -983,6 +1032,7 @@ var init_exception = __esm({
983
1032
  init_SignatureMismatchException();
984
1033
  init_TransferBalanceException();
985
1034
  init_WalletCredentialException();
1035
+ init_SecretStorageException();
986
1036
  init_InvalidResponseException();
987
1037
  init_BalanceInsufficientException();
988
1038
  init_BatchIdException();
@@ -4109,7 +4159,8 @@ z.object({
4109
4159
  socket: z.unknown().optional(),
4110
4160
  serverSdkVersion: z.number().int().min(1).optional(),
4111
4161
  logging: z.boolean().optional(),
4112
- defaultRequestPolicy: z.enum(["cache-first", "cache-only", "network-only", "cache-and-network"]).nullable().optional()
4162
+ defaultRequestPolicy: z.enum(["cache-first", "cache-only", "network-only", "cache-and-network"]).nullable().optional(),
4163
+ secretStorage: z.unknown().optional()
4113
4164
  }).strict();
4114
4165
  z.object({
4115
4166
  token: z.string().min(1, "Auth token cannot be empty"),
@@ -6909,7 +6960,9 @@ var KnishIOClientConfigSchema2 = z.object({
6909
6960
  // Optional default urql request policy for reads (server/sync clients pass
6910
6961
  // 'network-only'). Permitted by the strict schema so the constructor option
6911
6962
  // isn't rejected.
6912
- defaultRequestPolicy: z.enum(["cache-first", "cache-only", "network-only", "cache-and-network"]).nullable().optional()
6963
+ defaultRequestPolicy: z.enum(["cache-first", "cache-only", "network-only", "cache-and-network"]).nullable().optional(),
6964
+ // Pluggable hardware envelope encryption secret storage provider
6965
+ secretStorage: z.unknown().optional()
6913
6966
  }).strict();
6914
6967
  var EnvironmentConfigSchema = z.object({
6915
6968
  NODE_ENV: z.enum(["development", "production", "test"]).optional(),
@@ -10447,9 +10500,134 @@ var ActiveSessionSubscribe = class extends Subscribe {
10447
10500
 
10448
10501
  // src/KnishIOClient.ts
10449
10502
  init_exception();
10503
+
10504
+ // src/storage/MemorySecretStorageProvider.ts
10505
+ init_SecretStorageException();
10506
+
10507
+ // src/libraries/secureMemory.ts
10508
+ var textEncoder = new TextEncoder();
10509
+ function zeroizeBytes(buffer) {
10510
+ if (buffer instanceof Uint8Array) {
10511
+ buffer.fill(0);
10512
+ } else if (Array.isArray(buffer)) {
10513
+ for (let i = 0; i < buffer.length; i++) {
10514
+ buffer[i] = 0;
10515
+ }
10516
+ }
10517
+ }
10518
+ async function withSecureBytes(bytes, fn) {
10519
+ try {
10520
+ return await fn(bytes);
10521
+ } finally {
10522
+ zeroizeBytes(bytes);
10523
+ }
10524
+ }
10525
+ async function withSecureString(secret, fn) {
10526
+ const bytes = textEncoder.encode(secret);
10527
+ try {
10528
+ return await fn(secret);
10529
+ } finally {
10530
+ zeroizeBytes(bytes);
10531
+ }
10532
+ }
10533
+ function constantTimeCompare(a, b) {
10534
+ const bytesA = typeof a === "string" ? textEncoder.encode(a) : a;
10535
+ const bytesB = typeof b === "string" ? textEncoder.encode(b) : b;
10536
+ let result = bytesA.length === bytesB.length ? 0 : 1;
10537
+ const len = Math.min(bytesA.length, bytesB.length);
10538
+ for (let i = 0; i < len; i++) {
10539
+ const byteA = bytesA[i] ?? 0;
10540
+ const byteB = bytesB[i] ?? 0;
10541
+ result |= byteA ^ byteB;
10542
+ }
10543
+ if (typeof a === "string") zeroizeBytes(bytesA);
10544
+ if (typeof b === "string") zeroizeBytes(bytesB);
10545
+ return result === 0;
10546
+ }
10547
+
10548
+ // src/storage/MemorySecretStorageProvider.ts
10549
+ var MemorySecretStorageProvider = class {
10550
+ providerType = "memory";
10551
+ secrets = /* @__PURE__ */ new Map();
10552
+ /**
10553
+ * Memory storage is not hardware backed
10554
+ */
10555
+ isHardwareBacked() {
10556
+ return false;
10557
+ }
10558
+ /**
10559
+ * Memory storage is always available
10560
+ */
10561
+ async isAvailable() {
10562
+ return true;
10563
+ }
10564
+ /**
10565
+ * Store a secret in memory
10566
+ */
10567
+ async storeSecret(bundleHash, secret, options) {
10568
+ if (!bundleHash) {
10569
+ throw new SecretStorageException("Bundle hash cannot be empty");
10570
+ }
10571
+ if (!secret) {
10572
+ throw new SecretStorageException("Secret cannot be empty");
10573
+ }
10574
+ const metadata = {
10575
+ bundleHash,
10576
+ label: options?.label,
10577
+ createdAt: Date.now(),
10578
+ hardwareBacked: false,
10579
+ providerType: this.providerType
10580
+ };
10581
+ this.secrets.set(bundleHash, { secret, metadata });
10582
+ }
10583
+ /**
10584
+ * Retrieve a secret from memory
10585
+ */
10586
+ async retrieveSecret(bundleHash) {
10587
+ const entry = this.secrets.get(bundleHash);
10588
+ return entry ? entry.secret : null;
10589
+ }
10590
+ /**
10591
+ * Delete a stored secret
10592
+ */
10593
+ async deleteSecret(bundleHash) {
10594
+ return this.secrets.delete(bundleHash);
10595
+ }
10596
+ /**
10597
+ * Check if a secret exists
10598
+ */
10599
+ async hasSecret(bundleHash) {
10600
+ return this.secrets.has(bundleHash);
10601
+ }
10602
+ /**
10603
+ * List all stored secret metadata
10604
+ */
10605
+ async listSecrets() {
10606
+ return Array.from(this.secrets.values()).map((entry) => ({ ...entry.metadata }));
10607
+ }
10608
+ /**
10609
+ * Execute callback with unwrapped secret and ensure cleanup
10610
+ */
10611
+ async withSecret(bundleHash, fn) {
10612
+ const entry = this.secrets.get(bundleHash);
10613
+ if (!entry) {
10614
+ throw SecretStorageException.notFound(bundleHash);
10615
+ }
10616
+ return withSecureString(entry.secret, fn);
10617
+ }
10618
+ /**
10619
+ * Clear all secrets from memory
10620
+ */
10621
+ clear() {
10622
+ this.secrets.clear();
10623
+ }
10624
+ };
10625
+
10626
+ // src/KnishIOClient.ts
10450
10627
  var KnishIOClient = class {
10451
10628
  $__secret = "";
10452
10629
  $__bundle = "";
10630
+ $__secretStorage = null;
10453
10631
  $__cellSlug = null;
10454
10632
  $__encrypt = false;
10455
10633
  $__uris = [];
@@ -10509,6 +10687,9 @@ var KnishIOClient = class {
10509
10687
  logging,
10510
10688
  defaultRequestPolicy
10511
10689
  });
10690
+ if (config.secretStorage) {
10691
+ this.$__secretStorage = config.secretStorage;
10692
+ }
10512
10693
  }
10513
10694
  /**
10514
10695
  * Initializes a new Knish.IO client session
@@ -10610,6 +10791,7 @@ var KnishIOClient = class {
10610
10791
  reset() {
10611
10792
  this.$__secret = "";
10612
10793
  this.$__bundle = "";
10794
+ this.$__secretStorage = null;
10613
10795
  this.$__encrypt = false;
10614
10796
  this.$__cellSlug = null;
10615
10797
  this.$__authToken = null;
@@ -10671,7 +10853,7 @@ var KnishIOClient = class {
10671
10853
  * Returns whether a secret is stored for this session
10672
10854
  */
10673
10855
  hasSecret() {
10674
- return !!this.$__secret && this.$__secret.length > 0;
10856
+ return !!this.$__secret && this.$__secret.length > 0 || !!this.$__secretStorage && !!this.$__bundle && this.$__bundle.length > 0;
10675
10857
  }
10676
10858
  /**
10677
10859
  * Returns the stored secret
@@ -10682,6 +10864,33 @@ var KnishIOClient = class {
10682
10864
  }
10683
10865
  return this.$__secret;
10684
10866
  }
10867
+ /**
10868
+ * Sets the secret storage provider and optionally sets the bundle hash
10869
+ */
10870
+ setSecretStorage(storage, bundleHash) {
10871
+ this.$__secretStorage = storage;
10872
+ if (bundleHash) {
10873
+ this.$__bundle = bundleHash;
10874
+ }
10875
+ }
10876
+ /**
10877
+ * Returns current secret storage provider
10878
+ */
10879
+ getSecretStorage() {
10880
+ return this.$__secretStorage;
10881
+ }
10882
+ /**
10883
+ * Asynchronously retrieves the secret from storage or returns in-memory secret
10884
+ */
10885
+ async retrieveSecret(options) {
10886
+ if (this.$__secret && this.$__secret.length > 0) {
10887
+ return this.$__secret;
10888
+ }
10889
+ if (this.$__secretStorage && this.$__bundle && this.$__bundle.length > 0) {
10890
+ return await this.$__secretStorage.retrieveSecret(this.$__bundle, options);
10891
+ }
10892
+ return null;
10893
+ }
10685
10894
  /**
10686
10895
  * Returns whether a bundle hash is being stored for this session
10687
10896
  */
@@ -10720,6 +10929,13 @@ var KnishIOClient = class {
10720
10929
  remainderWallet = null
10721
10930
  } = {}) {
10722
10931
  this.log("info", "KnishIOClient::createMolecule() - Creating a new molecule...");
10932
+ if (!secret) {
10933
+ if (this.$__secret && this.$__secret.length > 0) {
10934
+ secret = this.getSecret();
10935
+ } else if (this.$__secretStorage && this.$__bundle && this.$__bundle.length > 0) {
10936
+ secret = await this.$__secretStorage.retrieveSecret(this.$__bundle);
10937
+ }
10938
+ }
10723
10939
  secret = secret || this.getSecret();
10724
10940
  bundle = bundle || this.getBundle();
10725
10941
  let continuIdPosition = null;
@@ -10749,6 +10965,7 @@ var KnishIOClient = class {
10749
10965
  }));
10750
10966
  return new Molecule({
10751
10967
  secret,
10968
+ bundle,
10752
10969
  sourceWallet,
10753
10970
  remainderWallet: this.getRemainderWallet(),
10754
10971
  cellSlug: this.getCellSlug(),
@@ -10795,8 +11012,9 @@ var KnishIOClient = class {
10795
11012
  async executeQuery(query, variables = null, context = {}) {
10796
11013
  if (this.$__authToken && this.$__authToken.isExpired() && !this.$__authInProcess) {
10797
11014
  this.log("info", "KnishIOClient::executeQuery() - Access token is expired. Getting new one...");
11015
+ const authSecret = this.$__secret || await this.retrieveSecret() || "";
10798
11016
  await this.requestAuthToken({
10799
- secret: this.$__secret,
11017
+ secret: authSecret,
10800
11018
  cellSlug: this.$__cellSlug,
10801
11019
  encrypt: this.$__encrypt
10802
11020
  });
@@ -10836,6 +11054,13 @@ var KnishIOClient = class {
10836
11054
  setSecret(secret) {
10837
11055
  this.$__secret = secret;
10838
11056
  this.$__bundle = generateBundleHash(secret);
11057
+ if (!this.$__secretStorage) {
11058
+ const memStorage = new MemorySecretStorageProvider();
11059
+ memStorage.storeSecret(this.$__bundle, secret);
11060
+ this.$__secretStorage = memStorage;
11061
+ } else {
11062
+ this.$__secretStorage.storeSecret(this.$__bundle, secret);
11063
+ }
10839
11064
  }
10840
11065
  /**
10841
11066
  * Sets the auth token for this session
@@ -11019,6 +11244,9 @@ var KnishIOClient = class {
11019
11244
  if (secret === null && seed) {
11020
11245
  secret = generateSecret(seed);
11021
11246
  }
11247
+ if (secret === null && this.$__secretStorage && this.$__bundle) {
11248
+ secret = await this.$__secretStorage.retrieveSecret(this.$__bundle);
11249
+ }
11022
11250
  if (cellSlug) {
11023
11251
  this.setCellSlug(cellSlug);
11024
11252
  }
@@ -12156,7 +12384,297 @@ var KnishIOClient = class {
12156
12384
  // src/index.ts
12157
12385
  init_Response();
12158
12386
  init_exception();
12159
- var SDK_VERSION = "0.9.6";
12387
+
12388
+ // src/storage/WebCryptoSecretStorageProvider.ts
12389
+ init_SecretStorageException();
12390
+ var MemoryStorageBackend = class {
12391
+ store = /* @__PURE__ */ new Map();
12392
+ getItem(key) {
12393
+ return this.store.get(key) ?? null;
12394
+ }
12395
+ setItem(key, value) {
12396
+ this.store.set(key, value);
12397
+ }
12398
+ removeItem(key) {
12399
+ return this.store.delete(key);
12400
+ }
12401
+ keys() {
12402
+ return Array.from(this.store.keys());
12403
+ }
12404
+ };
12405
+ function uint8ArrayToBase64(bytes) {
12406
+ let binary = "";
12407
+ const len = bytes.byteLength;
12408
+ for (let i = 0; i < len; i++) {
12409
+ const byte = bytes[i];
12410
+ if (byte !== void 0) {
12411
+ binary += String.fromCharCode(byte);
12412
+ }
12413
+ }
12414
+ return btoa(binary);
12415
+ }
12416
+ function base64ToUint8Array(base64) {
12417
+ const binary = atob(base64);
12418
+ const len = binary.length;
12419
+ const bytes = new Uint8Array(len);
12420
+ for (let i = 0; i < len; i++) {
12421
+ bytes[i] = binary.charCodeAt(i);
12422
+ }
12423
+ return bytes;
12424
+ }
12425
+ var textEncoder2 = new TextEncoder();
12426
+ var textDecoder = new TextDecoder();
12427
+ var KEY_PREFIX = "knishio:secret:";
12428
+ var DEFAULT_ITERATIONS = 1e5;
12429
+ var WebCryptoSecretStorageProvider = class {
12430
+ providerType = "webcrypto-aes-gcm";
12431
+ backend;
12432
+ defaultPassphrase;
12433
+ hardwareBacked;
12434
+ constructor(options = {}) {
12435
+ this.backend = options.backend ?? new MemoryStorageBackend();
12436
+ this.defaultPassphrase = options.defaultPassphrase;
12437
+ this.hardwareBacked = options.hardwareBacked ?? false;
12438
+ }
12439
+ /**
12440
+ * Whether this provider is backed by hardware (e.g. WebAuthn PRF wrapping)
12441
+ */
12442
+ isHardwareBacked() {
12443
+ return this.hardwareBacked;
12444
+ }
12445
+ /**
12446
+ * Check if WebCrypto subtle API is available
12447
+ */
12448
+ async isAvailable() {
12449
+ return typeof globalThis.crypto !== "undefined" && typeof globalThis.crypto.subtle !== "undefined";
12450
+ }
12451
+ /**
12452
+ * Derive an AES-GCM CryptoKey from a passphrase and salt using PBKDF2
12453
+ */
12454
+ async deriveKey(passphrase, salt, iterations = DEFAULT_ITERATIONS) {
12455
+ if (!await this.isAvailable()) {
12456
+ throw SecretStorageException.unavailable(this.providerType, "WebCrypto API is not available");
12457
+ }
12458
+ const passphraseBytes = textEncoder2.encode(passphrase);
12459
+ try {
12460
+ const baseKey = await globalThis.crypto.subtle.importKey(
12461
+ "raw",
12462
+ passphraseBytes,
12463
+ "PBKDF2",
12464
+ false,
12465
+ ["deriveKey"]
12466
+ );
12467
+ return await globalThis.crypto.subtle.deriveKey(
12468
+ {
12469
+ name: "PBKDF2",
12470
+ salt,
12471
+ iterations,
12472
+ hash: "SHA-256"
12473
+ },
12474
+ baseKey,
12475
+ { name: "AES-GCM", length: 256 },
12476
+ false,
12477
+ ["encrypt", "decrypt"]
12478
+ );
12479
+ } finally {
12480
+ zeroizeBytes(passphraseBytes);
12481
+ }
12482
+ }
12483
+ /**
12484
+ * Store and encrypt a master secret
12485
+ */
12486
+ async storeSecret(bundleHash, secret, options) {
12487
+ if (!bundleHash) {
12488
+ throw new SecretStorageException("Bundle hash cannot be empty");
12489
+ }
12490
+ if (!secret) {
12491
+ throw new SecretStorageException("Secret cannot be empty");
12492
+ }
12493
+ const passphrase = options?.passphrase ?? this.defaultPassphrase;
12494
+ if (!passphrase) {
12495
+ throw new SecretStorageException("Passphrase required for envelope encryption");
12496
+ }
12497
+ const salt = new Uint8Array(16);
12498
+ const iv = new Uint8Array(12);
12499
+ globalThis.crypto.getRandomValues(salt);
12500
+ globalThis.crypto.getRandomValues(iv);
12501
+ const key = await this.deriveKey(passphrase, salt, DEFAULT_ITERATIONS);
12502
+ const secretBytes = textEncoder2.encode(secret);
12503
+ try {
12504
+ const encryptedBuffer = await globalThis.crypto.subtle.encrypt(
12505
+ {
12506
+ name: "AES-GCM",
12507
+ iv
12508
+ },
12509
+ key,
12510
+ secretBytes
12511
+ );
12512
+ const ciphertext = uint8ArrayToBase64(new Uint8Array(encryptedBuffer));
12513
+ const metadata = {
12514
+ bundleHash,
12515
+ label: options?.label,
12516
+ createdAt: Date.now(),
12517
+ hardwareBacked: this.hardwareBacked,
12518
+ providerType: this.providerType
12519
+ };
12520
+ const payload = {
12521
+ version: 1,
12522
+ ciphertext,
12523
+ iv: uint8ArrayToBase64(iv),
12524
+ salt: uint8ArrayToBase64(salt),
12525
+ algorithm: "AES-GCM",
12526
+ iterations: DEFAULT_ITERATIONS,
12527
+ metadata
12528
+ };
12529
+ await this.backend.setItem(`${KEY_PREFIX}${bundleHash}`, JSON.stringify(payload));
12530
+ } catch (err) {
12531
+ const msg = err instanceof Error ? err.message : String(err);
12532
+ throw new SecretStorageException(`Encryption failed: ${msg}`);
12533
+ } finally {
12534
+ zeroizeBytes(secretBytes);
12535
+ }
12536
+ }
12537
+ /**
12538
+ * Retrieve and decrypt the master secret
12539
+ */
12540
+ async retrieveSecret(bundleHash, options) {
12541
+ const raw = await this.backend.getItem(`${KEY_PREFIX}${bundleHash}`);
12542
+ if (!raw) {
12543
+ return null;
12544
+ }
12545
+ let payload;
12546
+ try {
12547
+ payload = JSON.parse(raw);
12548
+ } catch {
12549
+ throw SecretStorageException.decryptionFailed("Corrupted payload format");
12550
+ }
12551
+ const passphrase = options?.passphrase ?? this.defaultPassphrase;
12552
+ if (!passphrase) {
12553
+ throw new SecretStorageException("Passphrase required for secret decryption");
12554
+ }
12555
+ const salt = base64ToUint8Array(payload.salt);
12556
+ const iv = base64ToUint8Array(payload.iv);
12557
+ const ciphertext = base64ToUint8Array(payload.ciphertext);
12558
+ try {
12559
+ const key = await this.deriveKey(passphrase, salt, payload.iterations ?? DEFAULT_ITERATIONS);
12560
+ const decryptedBuffer = await globalThis.crypto.subtle.decrypt(
12561
+ {
12562
+ name: "AES-GCM",
12563
+ iv
12564
+ },
12565
+ key,
12566
+ ciphertext
12567
+ );
12568
+ const decryptedBytes = new Uint8Array(decryptedBuffer);
12569
+ try {
12570
+ return textDecoder.decode(decryptedBytes);
12571
+ } finally {
12572
+ zeroizeBytes(decryptedBytes);
12573
+ }
12574
+ } catch (err) {
12575
+ const msg = err instanceof Error ? err.message : String(err);
12576
+ throw SecretStorageException.decryptionFailed(msg);
12577
+ }
12578
+ }
12579
+ /**
12580
+ * Delete a stored secret
12581
+ */
12582
+ async deleteSecret(bundleHash) {
12583
+ const key = `${KEY_PREFIX}${bundleHash}`;
12584
+ const result = await this.backend.removeItem(key);
12585
+ return result !== false;
12586
+ }
12587
+ /**
12588
+ * Check if a secret exists
12589
+ */
12590
+ async hasSecret(bundleHash) {
12591
+ const raw = await this.backend.getItem(`${KEY_PREFIX}${bundleHash}`);
12592
+ return raw !== null;
12593
+ }
12594
+ /**
12595
+ * List all stored secret metadata
12596
+ */
12597
+ async listSecrets() {
12598
+ const keys = await this.backend.keys();
12599
+ const matchingKeys = keys.filter((k) => k.startsWith(KEY_PREFIX));
12600
+ const results = [];
12601
+ for (const key of matchingKeys) {
12602
+ const raw = await this.backend.getItem(key);
12603
+ if (raw) {
12604
+ try {
12605
+ const payload = JSON.parse(raw);
12606
+ if (payload.metadata) {
12607
+ results.push(payload.metadata);
12608
+ }
12609
+ } catch {
12610
+ }
12611
+ }
12612
+ }
12613
+ return results;
12614
+ }
12615
+ /**
12616
+ * Execute callback with unwrapped secret, zeroizing the decrypted buffer upon completion
12617
+ */
12618
+ async withSecret(bundleHash, fn, options) {
12619
+ const raw = await this.backend.getItem(`${KEY_PREFIX}${bundleHash}`);
12620
+ if (!raw) {
12621
+ throw SecretStorageException.notFound(bundleHash);
12622
+ }
12623
+ let payload;
12624
+ try {
12625
+ payload = JSON.parse(raw);
12626
+ } catch {
12627
+ throw SecretStorageException.decryptionFailed("Corrupted payload format");
12628
+ }
12629
+ const passphrase = options?.passphrase ?? this.defaultPassphrase;
12630
+ if (!passphrase) {
12631
+ throw new SecretStorageException("Passphrase required for secret decryption");
12632
+ }
12633
+ const salt = base64ToUint8Array(payload.salt);
12634
+ const iv = base64ToUint8Array(payload.iv);
12635
+ const ciphertext = base64ToUint8Array(payload.ciphertext);
12636
+ try {
12637
+ const key = await this.deriveKey(passphrase, salt, payload.iterations ?? DEFAULT_ITERATIONS);
12638
+ const decryptedBuffer = await globalThis.crypto.subtle.decrypt(
12639
+ {
12640
+ name: "AES-GCM",
12641
+ iv
12642
+ },
12643
+ key,
12644
+ ciphertext
12645
+ );
12646
+ const decryptedBytes = new Uint8Array(decryptedBuffer);
12647
+ return await withSecureBytes(decryptedBytes, async (bytes) => {
12648
+ const secretString = textDecoder.decode(bytes);
12649
+ return await fn(secretString);
12650
+ });
12651
+ } catch (err) {
12652
+ if (err instanceof SecretStorageException) {
12653
+ throw err;
12654
+ }
12655
+ const msg = err instanceof Error ? err.message : String(err);
12656
+ throw SecretStorageException.decryptionFailed(msg);
12657
+ }
12658
+ }
12659
+ };
12660
+
12661
+ // src/storage/index.ts
12662
+ function createDefaultSecretStorage(options = {}) {
12663
+ if (options.type === "memory") {
12664
+ return new MemorySecretStorageProvider();
12665
+ }
12666
+ if (typeof globalThis.crypto !== "undefined" && typeof globalThis.crypto.subtle !== "undefined") {
12667
+ return new WebCryptoSecretStorageProvider({
12668
+ backend: options.backend,
12669
+ defaultPassphrase: options.defaultPassphrase,
12670
+ hardwareBacked: options.hardwareBacked
12671
+ });
12672
+ }
12673
+ return new MemorySecretStorageProvider();
12674
+ }
12675
+
12676
+ // src/index.ts
12677
+ var SDK_VERSION = "0.9.7";
12160
12678
  var SDK_NAME = "KnishIO-Client-TS";
12161
12679
  var COMPATIBLE_SERVER_VERSIONS = [4, 5];
12162
12680
  var SDK_INFO = {
@@ -12246,6 +12764,6 @@ var KnishIO = {
12246
12764
  SDK_INFO
12247
12765
  };
12248
12766
 
12249
- export { Atom, AtomIndexException, AtomMeta, AtomsMissingException, AuthToken, BaseException, COMPATIBLE_SERVER_VERSIONS, CRYPTO_CONSTANTS, CheckMolecule, DevUtils, Dot, EXCEPTION_CODES, EXCEPTION_TYPES, EXTENDED_COMPATIBILITY_TEST_VECTORS, ExceptionFactory, GraphQLClient, InvalidResponseException, KnishIO, KnishIOClient, Meta, MolecularHashMismatchException, Molecule, Mutation, MutationAppendRequest, MutationCreateMeta, MutationCreateToken, MutationCreateWallet, MutationPeering, MutationProposeMolecule, MutationRequestAuthorization, MutationRequestTokens, MutationTransferTokens, PolicyMeta, Query, QueryAtom, QueryBalance, QueryBatch, QueryContinuId, QueryEmbeddingStatus, QueryMetaType, QueryMetaTypeViaAtom, QueryWalletBundle, QueryWalletList, Response2 as Response, ResponseAppendRequest, ResponseAtom, ResponseBalance, ResponseContinuId, ResponseCreateMeta, ResponseCreateToken, ResponseCreateWallet, ResponseEmbeddingStatus, ResponseMetaType, ResponseMetaTypeViaAtom, ResponsePeering, ResponseProposeMolecule, ResponseRequestAuthorization, ResponseRequestTokens, ResponseTransferTokens, ResponseWalletBundle, ResponseWalletList, SDK_INFO, SDK_NAME, SDK_VERSION, SignatureMismatchException, TokenUnit, TransferBalanceException, Wallet, WalletCredentialException, base64ToHex, bufferToHexString, capitalize, charsetBaseConvert, chunkArray, chunkSubstr, configureSDK, convertToBase17, createBundleHash, createMolecularHash, createPosition, createTokenSlug, createWalletAddress, deepCloning, diff, enumerateMolecularHash, generateBatchId, generateBundleHash, generateOTSSignature, generatePosition, generateSecret, generateWalletAddress, generateWalletKey, getSDKConfig, hexStringToBuffer, hexToBase64, intersect, isAtomIsotope, isBundleHash, isHex, isHexString, isMolecularHash, isNumeric, isPosition2 as isPosition, isWalletAddress2 as isWalletAddress, normalizeMolecularHash, randomString, runCompatibilityTests, runExtendedCompatibilityTests, shake256, toCamelCase, toSnakeCase, truncate, validateBundleHash, validateMolecularHashForSignature, validateOTSSignature, validatePosition, validateSecret, validateWalletAddress, verifyOTSSignature };
12767
+ export { Atom, AtomIndexException, AtomMeta, AtomsMissingException, AuthToken, BaseException, COMPATIBLE_SERVER_VERSIONS, CRYPTO_CONSTANTS, CheckMolecule, DevUtils, Dot, EXCEPTION_CODES, EXCEPTION_TYPES, EXTENDED_COMPATIBILITY_TEST_VECTORS, ExceptionFactory, GraphQLClient, InvalidResponseException, KnishIO, KnishIOClient, MemorySecretStorageProvider, MemoryStorageBackend, Meta, MolecularHashMismatchException, Molecule, Mutation, MutationAppendRequest, MutationCreateMeta, MutationCreateToken, MutationCreateWallet, MutationPeering, MutationProposeMolecule, MutationRequestAuthorization, MutationRequestTokens, MutationTransferTokens, PolicyMeta, Query, QueryAtom, QueryBalance, QueryBatch, QueryContinuId, QueryEmbeddingStatus, QueryMetaType, QueryMetaTypeViaAtom, QueryWalletBundle, QueryWalletList, Response2 as Response, ResponseAppendRequest, ResponseAtom, ResponseBalance, ResponseContinuId, ResponseCreateMeta, ResponseCreateToken, ResponseCreateWallet, ResponseEmbeddingStatus, ResponseMetaType, ResponseMetaTypeViaAtom, ResponsePeering, ResponseProposeMolecule, ResponseRequestAuthorization, ResponseRequestTokens, ResponseTransferTokens, ResponseWalletBundle, ResponseWalletList, SDK_INFO, SDK_NAME, SDK_VERSION, SecretStorageException, SignatureMismatchException, TokenUnit, TransferBalanceException, Wallet, WalletCredentialException, WebCryptoSecretStorageProvider, base64ToHex, bufferToHexString, capitalize, charsetBaseConvert, chunkArray, chunkSubstr, configureSDK, constantTimeCompare, convertToBase17, createBundleHash, createDefaultSecretStorage, createMolecularHash, createPosition, createTokenSlug, createWalletAddress, deepCloning, diff, enumerateMolecularHash, generateBatchId, generateBundleHash, generateOTSSignature, generatePosition, generateSecret, generateWalletAddress, generateWalletKey, getSDKConfig, hexStringToBuffer, hexToBase64, intersect, isAtomIsotope, isBundleHash, isHex, isHexString, isMolecularHash, isNumeric, isPosition2 as isPosition, isWalletAddress2 as isWalletAddress, normalizeMolecularHash, randomString, runCompatibilityTests, runExtendedCompatibilityTests, shake256, toCamelCase, toSnakeCase, truncate, validateBundleHash, validateMolecularHashForSignature, validateOTSSignature, validatePosition, validateSecret, validateWalletAddress, verifyOTSSignature, withSecureBytes, withSecureString, zeroizeBytes };
12250
12768
  //# sourceMappingURL=index.js.map
12251
12769
  //# sourceMappingURL=index.js.map