@wishknish/knishio-client-js 0.9.3 → 1.0.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/src/Wallet.js CHANGED
@@ -59,7 +59,13 @@ import {
59
59
  } from './libraries/crypto.js'
60
60
  import TokenUnit from './TokenUnit.js'
61
61
  import WalletCredentialException from './exception/WalletCredentialException.js'
62
- import { ml_kem768 as MlKEM768 } from '@noble/post-quantum/ml-kem.js'
62
+ import { ml_kem768 as MlKEM768, ml_kem1024 as MlKEM1024 } from '@noble/post-quantum/ml-kem.js'
63
+
64
+ const ML_KEM_PARAMS = {
65
+ 1024: { kem: MlKEM1024, pkBytes: 1568, skBytes: 3168, ctBytes: 1568 },
66
+ 768: { kem: MlKEM768, pkBytes: 1184, skBytes: 2400, ctBytes: 1088 }
67
+ }
68
+ const DEFAULT_ML_KEM_PARAMETER_SET = 1024
63
69
 
64
70
  /**
65
71
  * Wallet class represents the set of public and private
@@ -84,8 +90,14 @@ export default class Wallet {
84
90
  address = null,
85
91
  position = null,
86
92
  batchId = null,
87
- characters = null
93
+ characters = null,
94
+ mlKemParameterSet = DEFAULT_ML_KEM_PARAMETER_SET
88
95
  }) {
96
+ const paramSetNum = Number(mlKemParameterSet)
97
+ if (!ML_KEM_PARAMS[paramSetNum]) {
98
+ throw new Error(`KnishIO: unsupported ML-KEM parameter set ${mlKemParameterSet}; expected 1024 or 768.`)
99
+ }
100
+ this.mlKemParameterSet = paramSetNum
89
101
  this.token = token
90
102
  this.balance = '0'
91
103
  this.molecules = {}
@@ -141,7 +153,8 @@ export default class Wallet {
141
153
  bundle = null,
142
154
  token,
143
155
  batchId = null,
144
- characters = null
156
+ characters = null,
157
+ mlKemParameterSet = DEFAULT_ML_KEM_PARAMETER_SET
145
158
  }) {
146
159
  let position = null
147
160
 
@@ -163,7 +176,8 @@ export default class Wallet {
163
176
  token,
164
177
  position,
165
178
  batchId,
166
- characters
179
+ characters,
180
+ mlKemParameterSet
167
181
  })
168
182
  }
169
183
 
@@ -280,23 +294,49 @@ export default class Wallet {
280
294
  }
281
295
 
282
296
  /**
283
- * Initializes the ML-KEM key pair
297
+ * Derive an ML-KEM keypair for an arbitrary parameter set from the wallet's key seed.
298
+ *
299
+ * Returns `null` when the wallet holds no key — a secret-less wallet, which is what
300
+ * {@link Molecule.fromJSON} builds for validation context. `generateSecret(null, …)` does NOT
301
+ * throw, so without this the wallet would derive a plausible-looking identity from a bogus seed
302
+ * and fail three layers down at AES-GCM instead of at the missing key. The guard lives here
303
+ * rather than at each call site so a new caller cannot miss it.
304
+ *
305
+ * @param {number} parameterSet - 1024 or 768
306
+ * @return {{pubkey: string, privkey: Uint8Array, params: object}|null}
284
307
  */
285
- initializeMLKEM () {
286
- // Generate a 64-byte (512-bit) seed from the Knish.IO private key
287
- // Use deterministic approach: generateSecret(key, 128) → 128 hex chars = 64 bytes
308
+ _deriveMlKemKeypair (parameterSet) {
309
+ const params = ML_KEM_PARAMS[parameterSet]
310
+ if (!params) {
311
+ throw new Error(`KnishIO: unsupported ML-KEM parameter set ${parameterSet}; expected 1024 or 768.`)
312
+ }
313
+ if (!this.key) {
314
+ return null
315
+ }
288
316
  const seedHex = generateSecret(this.key, 128) // 128 hex chars = 64 bytes
289
-
290
- // Convert the hex string to a Uint8Array
291
317
  const seed = new Uint8Array(64)
292
318
  for (let i = 0; i < 64; i++) {
293
319
  seed[i] = parseInt(seedHex.substr(i * 2, 2), 16)
294
320
  }
321
+ const { publicKey, secretKey } = params.kem.keygen(seed)
322
+ return {
323
+ pubkey: this.serializeKey(publicKey),
324
+ privkey: secretKey,
325
+ params
326
+ }
327
+ }
295
328
 
296
- const { publicKey, secretKey } = MlKEM768.keygen(seed)
297
-
298
- this.pubkey = this.serializeKey(publicKey)
299
- this.privkey = secretKey // Note: We're keeping privkey as UInt8Array for security
329
+ /**
330
+ * Initializes the ML-KEM key pair. Only ever reached from the constructor's `secret` branch,
331
+ * so the derivation cannot come back empty here.
332
+ */
333
+ initializeMLKEM () {
334
+ const derived = this._deriveMlKemKeypair(this.mlKemParameterSet)
335
+ if (!derived) {
336
+ return
337
+ }
338
+ this.pubkey = derived.pubkey
339
+ this.privkey = derived.privkey
300
340
  }
301
341
 
302
342
  serializeKey (key) {
@@ -321,6 +361,35 @@ export default class Wallet {
321
361
  return new Uint8Array(binaryString.length).map((_, i) => binaryString.charCodeAt(i))
322
362
  }
323
363
 
364
+ /**
365
+ * ML-KEM parameter set implied by a serialized public key's raw byte length. FIPS 203's
366
+ * key lengths are disjoint (1568 bytes → ML-KEM-1024, 1184 bytes → ML-KEM-768), so a stored
367
+ * peer key recovers the parameter set of the session it belongs to without a wire-format
368
+ * change. Used by {@link AuthToken.restore} to resolve a snapshot that predates the field.
369
+ *
370
+ * @param {string|null} pubkey - Base64-serialized ML-KEM public key
371
+ * @return {number|null} 1024, 768, or null when the length matches neither
372
+ */
373
+ static mlKemParameterSetFromPubkey (pubkey) {
374
+ if (!pubkey) {
375
+ return null
376
+ }
377
+ let byteLength
378
+ try {
379
+ byteLength = typeof Buffer !== 'undefined'
380
+ ? Buffer.from(pubkey, 'base64').length
381
+ : atob(pubkey).length
382
+ } catch (e) {
383
+ return null
384
+ }
385
+ for (const [set, params] of Object.entries(ML_KEM_PARAMS)) {
386
+ if (params.pkBytes === byteLength) {
387
+ return Number(set)
388
+ }
389
+ }
390
+ return null
391
+ }
392
+
324
393
  /**
325
394
  * Returns balance as a Number for arithmetic operations.
326
395
  * WARNING: Precision loss for values > 2^53.
@@ -499,19 +568,19 @@ export default class Wallet {
499
568
  const messageString = JSON.stringify(message)
500
569
  const messageUint8 = new TextEncoder().encode(messageString)
501
570
  const deserializedPubkey = this.deserializeKey(recipientPubkey)
502
- // ML-KEM-768 public keys are exactly 1184 bytes. A wrong-length key here almost always means the
503
- // node did not advertise an ML-KEM public key in its auth `key` field (e.g. a validator predating
504
- // the PQ-transport build). Fail with an actionable message rather than the crypto lib's cryptic
505
- // `"publicKey" expected Uint8Array of length 1184, got length=N` assertion.
506
- const ML_KEM_768_PUBLIC_KEY_BYTES = 1184
507
- if (deserializedPubkey.length !== ML_KEM_768_PUBLIC_KEY_BYTES) {
571
+ // ML-KEM public keys are exactly 1568 bytes (ML-KEM-1024) or 1184 bytes (ML-KEM-768). A wrong-length key here
572
+ // almost always means the node did not advertise an ML-KEM public key in its auth `key` field (e.g. a validator
573
+ // predating the PQ-transport build). Fail with an actionable message rather than the crypto lib's cryptic
574
+ // `"publicKey" expected Uint8Array of length N, got length=M` assertion.
575
+ const params = ML_KEM_PARAMS[this.mlKemParameterSet]
576
+ if (deserializedPubkey.length !== params.pkBytes) {
508
577
  throw new Error(
509
578
  `KnishIO: cannot ML-KEM-encrypt — recipient public key is ${deserializedPubkey.length} bytes, ` +
510
- `expected ${ML_KEM_768_PUBLIC_KEY_BYTES} (ML-KEM-768). The node likely did not advertise an ML-KEM ` +
511
- 'public key (upgrade the validator to a PQ-transport build), or authenticate with { encrypt: false }.'
579
+ `expected ${params.pkBytes} (ML-KEM-${this.mlKemParameterSet}). The peer is not running ML-KEM-${this.mlKemParameterSet}; ` +
580
+ 'upgrade the peer, or step this client back to the other parameter set.'
512
581
  )
513
582
  }
514
- const { cipherText, sharedSecret } = MlKEM768.encapsulate(deserializedPubkey)
583
+ const { cipherText, sharedSecret } = params.kem.encapsulate(deserializedPubkey)
515
584
  const encryptedMessage = await this.encryptWithSharedSecret(messageUint8, sharedSecret)
516
585
  return {
517
586
  cipherText: this.serializeKey(cipherText),
@@ -525,17 +594,46 @@ export default class Wallet {
525
594
  }
526
595
 
527
596
  /**
528
- * ML-KEM768 decapsulate + AES-256-GCM decrypt → the RAW decrypted UTF-8 string
597
+ * ML-KEM decapsulate + AES-256-GCM decrypt → the RAW decrypted UTF-8 string
529
598
  * (no JSON.parse). Shared by {@link decryptMessage} (which JSON.parses the result)
530
- * and the PQ CipherHash transport ({@link decryptMyMessageML768}, which needs the raw
599
+ * and the PQ CipherHash transport ({@link decryptMyMessageML}, which needs the raw
531
600
  * response JSON text). PQ-transport Phase E (cycle 163).
532
601
  */
533
602
  async _mlkemDecryptToString (encryptedData) {
534
603
  const { cipherText, encryptedMessage } = encryptedData
535
604
 
605
+ const deserializedCipherText = this.deserializeKey(cipherText)
606
+ const configuredParams = ML_KEM_PARAMS[this.mlKemParameterSet]
607
+ const otherSet = this.mlKemParameterSet === 1024 ? 768 : 1024
608
+
609
+ // Inbound is PERMISSIVE: a ciphertext at either parameter set decrypts, provided it is addressed
610
+ // to one of THIS wallet's own ML-KEM identities. The 64-byte seed is parameter-set-independent,
611
+ // so the other identity is derived on demand and its private key is released with this call's
612
+ // scope — never cached on the wallet. Outbound encapsulation stays STRICT (see encryptMessage);
613
+ // reading a 768 record we own downgrades nothing, but encapsulating at 768 would.
614
+ let decapsParams = configuredParams
615
+ let decapsPrivkey = this.privkey
616
+ if (deserializedCipherText.length !== configuredParams.ctBytes) {
617
+ if (deserializedCipherText.length !== ML_KEM_PARAMS[otherSet].ctBytes) {
618
+ console.error(
619
+ `Wallet::decryptMessage() - Ciphertext length mismatch: got ${deserializedCipherText.length}, expected ${configuredParams.ctBytes}`
620
+ )
621
+ return null
622
+ }
623
+ // `null` here means the wallet holds no key to derive from (a secret-less validation
624
+ // wallet); preserve the existing failure observable rather than decapsulating with nothing.
625
+ const derived = this._deriveMlKemKeypair(otherSet)
626
+ if (!derived) {
627
+ console.error(`Wallet::decryptMessage() - cannot derive the ML-KEM-${otherSet} identity: wallet has no key`)
628
+ return null
629
+ }
630
+ decapsParams = derived.params
631
+ decapsPrivkey = derived.privkey
632
+ }
633
+
536
634
  let sharedSecret
537
635
  try {
538
- sharedSecret = MlKEM768.decapsulate(this.deserializeKey(cipherText), this.privkey)
636
+ sharedSecret = decapsParams.kem.decapsulate(deserializedCipherText, decapsPrivkey)
539
637
  } catch (e) {
540
638
  console.error('Wallet::decryptMessage() - Decapsulation failed', e)
541
639
  console.info('Wallet::decryptMessage() - my public key', this.pubkey)
@@ -587,11 +685,11 @@ export default class Wallet {
587
685
  }
588
686
 
589
687
  /**
590
- * Post-quantum (ML-KEM768) `CipherHash` request envelope: a stringified single-recipient
688
+ * Post-quantum (ML-KEM) `CipherHash` request envelope: a stringified single-recipient
591
689
  * map `{ "<hashShare(recipientPubkey)>": {cipherText, encryptedMessage} }` (object-valued,
592
690
  * via {@link encryptMessage}). Matches the Rust validator's CipherHash handler. PQ Phase E.
593
691
  */
594
- async encryptStringML768 (message, recipientPubkey) {
692
+ async encryptStringML (message, recipientPubkey) {
595
693
  const envelope = await this.encryptMessage(message, recipientPubkey)
596
694
  return JSON.stringify({ [this.hashShare(recipientPubkey)]: envelope })
597
695
  }
@@ -601,8 +699,17 @@ export default class Wallet {
601
699
  * (`hashShare(this.pubkey)`) → the RAW decrypted GraphQL response JSON text (NOT JSON.parsed;
602
700
  * it replaces the HTTP response body for the normal parser). `null` if no entry / decrypt fails.
603
701
  */
604
- async decryptMyMessageML768 (map) {
605
- const envelope = map[this.hashShare(this.pubkey)]
702
+ async decryptMyMessageML (map) {
703
+ let envelope = map[this.hashShare(this.pubkey)]
704
+ if (!envelope) {
705
+ // Inbound permissive: try the hash share of the on-demand derived other-set pubkey.
706
+ // A secret-less wallet derives nothing, so the lookup is simply skipped.
707
+ const otherSet = this.mlKemParameterSet === 1024 ? 768 : 1024
708
+ const other = this._deriveMlKemKeypair(otherSet)
709
+ if (other) {
710
+ envelope = map[this.hashShare(other.pubkey)]
711
+ }
712
+ }
606
713
  if (!envelope) {
607
714
  return null
608
715
  }
@@ -0,0 +1,95 @@
1
+ /*
2
+ (
3
+ (/(
4
+ (//(
5
+ (///(
6
+ (/////(
7
+ (//////( )
8
+ (////////( (/)
9
+ (////////( (///)
10
+ (//////////( (////)
11
+ (//////////( (//////)
12
+ (////////////( (///////)
13
+ (/////////////( (/////////)
14
+ (//////////////( (///////////)
15
+ (///////////////( (/////////////)
16
+ (////////////////( (//////////////)
17
+ ((((((((((((((((((( (((((((((((((((
18
+ ((((((((((((((((((( ((((((((((((((
19
+ ((((((((((((((((((( ((((((((((((((
20
+ (((((((((((((((((((( (((((((((((((
21
+ (((((((((((((((((((( ((((((((((((
22
+ ((((((((((((((((((( ((((((((((((
23
+ ((((((((((((((((((( ((((((((((
24
+ ((((((((((((((((((/ (((((((((
25
+ (((((((((((((((((( ((((((((
26
+ ((((((((((((((((( (((((((
27
+ (((((((((((((((((( (((((
28
+ ################# ##
29
+ ################ #
30
+ ################# ##
31
+ %################ ###
32
+ ###############( ####
33
+ ############### ####
34
+ ############### ######
35
+ %#############( (#######
36
+ %############# #########
37
+ ############( ##########
38
+ ########### #############
39
+ ######### ##############
40
+ %######
41
+
42
+ Powered by Knish.IO: Connecting a Decentralized World
43
+
44
+ Please visit https://github.com/WishKnish/KnishIO-Client-JS for information.
45
+
46
+ License: https://github.com/WishKnish/KnishIO-Client-JS/blob/master/LICENSE
47
+ */
48
+
49
+ import BaseException from './BaseException.js'
50
+
51
+ /**
52
+ * Exception thrown when secret storage or hardware envelope encryption fails
53
+ */
54
+ export default class SecretStorageException extends BaseException {
55
+ /**
56
+ * @param {string} message
57
+ * @param {string|null} fileName
58
+ * @param {number|null} lineNumber
59
+ */
60
+ constructor (message = 'Secret storage operation failed', fileName = null, lineNumber = null) {
61
+ super(message, fileName, lineNumber)
62
+ this.name = 'SecretStorageException'
63
+ }
64
+
65
+ /**
66
+ * Factory method: secret not found for bundle
67
+ *
68
+ * @param {string} bundleHash
69
+ * @returns {SecretStorageException}
70
+ */
71
+ static notFound (bundleHash) {
72
+ return new SecretStorageException(`Secret not found for bundle: ${bundleHash}`)
73
+ }
74
+
75
+ /**
76
+ * Factory method: decryption failed
77
+ *
78
+ * @param {string} [reason]
79
+ * @returns {SecretStorageException}
80
+ */
81
+ static decryptionFailed (reason = 'Invalid passphrase or corrupted ciphertext') {
82
+ return new SecretStorageException(`Failed to decrypt master secret: ${reason}`)
83
+ }
84
+
85
+ /**
86
+ * Factory method: provider unavailable
87
+ *
88
+ * @param {string} provider
89
+ * @param {string} [reason]
90
+ * @returns {SecretStorageException}
91
+ */
92
+ static unavailable (provider, reason = 'Hardware or API not accessible') {
93
+ return new SecretStorageException(`Secret storage provider '${provider}' is unavailable: ${reason}`)
94
+ }
95
+ }
@@ -70,6 +70,7 @@ import TransferUnbalancedException from './TransferUnbalancedException.js'
70
70
  import UnauthenticatedException from './UnauthenticatedException.js'
71
71
  import WalletShadowException from './WalletShadowException.js'
72
72
  import WrongTokenTypeException from './WrongTokenTypeException.js'
73
+ import SecretStorageException from './SecretStorageException.js'
73
74
 
74
75
  export {
75
76
  AtomIndexException,
@@ -96,5 +97,6 @@ export {
96
97
  TransferUnbalancedException,
97
98
  UnauthenticatedException,
98
99
  WalletShadowException,
100
+ SecretStorageException,
99
101
  WrongTokenTypeException
100
102
  }
package/src/index.js CHANGED
@@ -207,6 +207,7 @@ export {
207
207
  TransferUnbalancedException,
208
208
  UnauthenticatedException,
209
209
  WalletShadowException,
210
+ SecretStorageException,
210
211
  WrongTokenTypeException
211
212
  } from './exception/index.js'
212
213
 
@@ -325,3 +326,17 @@ export {
325
326
  diff,
326
327
  intersect
327
328
  }
329
+
330
+ export {
331
+ MemorySecretStorageProvider,
332
+ WebCryptoSecretStorageProvider,
333
+ MemoryStorageBackend,
334
+ createDefaultSecretStorage
335
+ } from './storage/index.js'
336
+
337
+ export {
338
+ zeroizeBytes,
339
+ withSecureBytes,
340
+ withSecureString,
341
+ constantTimeCompare
342
+ } from './libraries/secureMemory.js'
@@ -0,0 +1,125 @@
1
+ /*
2
+ (
3
+ (/(
4
+ (//(
5
+ (///(
6
+ (/////(
7
+ (//////( )
8
+ (////////( (/)
9
+ (////////( (///)
10
+ (//////////( (////)
11
+ (//////////( (//////)
12
+ (////////////( (///////)
13
+ (/////////////( (/////////)
14
+ (//////////////( (///////////)
15
+ (///////////////( (/////////////)
16
+ (////////////////( (//////////////)
17
+ ((((((((((((((((((( (((((((((((((((
18
+ ((((((((((((((((((( ((((((((((((((
19
+ ((((((((((((((((((( ((((((((((((((
20
+ (((((((((((((((((((( (((((((((((((
21
+ (((((((((((((((((((( ((((((((((((
22
+ ((((((((((((((((((( ((((((((((((
23
+ ((((((((((((((((((( ((((((((((
24
+ ((((((((((((((((((/ (((((((((
25
+ (((((((((((((((((( ((((((((
26
+ ((((((((((((((((( (((((((
27
+ (((((((((((((((((( (((((
28
+ ################# ##
29
+ ################ #
30
+ ################# ##
31
+ %################ ###
32
+ ###############( ####
33
+ ############### ####
34
+ ############### ######
35
+ %#############( (#######
36
+ %############# #########
37
+ ############( ##########
38
+ ########### #############
39
+ ######### ##############
40
+ %######
41
+
42
+ Powered by Knish.IO: Connecting a Decentralized World
43
+
44
+ Please visit https://github.com/WishKnish/KnishIO-Client-JS for information.
45
+
46
+ License: https://github.com/WishKnish/KnishIO-Client-JS/blob/master/LICENSE
47
+ */
48
+
49
+ /**
50
+ * Memory hygiene and zeroization utilities for sensitive cryptographic material
51
+ */
52
+
53
+ const textEncoder = new TextEncoder()
54
+
55
+ /**
56
+ * Overwrite byte array contents with zeros
57
+ *
58
+ * @param {Uint8Array|number[]} buffer
59
+ */
60
+ export function zeroizeBytes (buffer) {
61
+ if (buffer instanceof Uint8Array) {
62
+ buffer.fill(0)
63
+ } else if (Array.isArray(buffer)) {
64
+ for (let i = 0; i < buffer.length; i++) {
65
+ buffer[i] = 0
66
+ }
67
+ }
68
+ }
69
+
70
+ /**
71
+ * Execute a callback with a byte buffer and guarantee zeroization upon completion
72
+ *
73
+ * @template T
74
+ * @param {Uint8Array} bytes
75
+ * @param {(bytes: Uint8Array) => Promise<T>|T} fn
76
+ * @returns {Promise<T>}
77
+ */
78
+ export async function withSecureBytes (bytes, fn) {
79
+ try {
80
+ return await fn(bytes)
81
+ } finally {
82
+ zeroizeBytes(bytes)
83
+ }
84
+ }
85
+
86
+ /**
87
+ * Execute a callback with a secret string, ensuring temporary byte buffers are cleared
88
+ *
89
+ * @template T
90
+ * @param {string} secret
91
+ * @param {(cleanSecret: string) => Promise<T>|T} fn
92
+ * @returns {Promise<T>}
93
+ */
94
+ export async function withSecureString (secret, fn) {
95
+ const bytes = textEncoder.encode(secret)
96
+ try {
97
+ return await fn(secret)
98
+ } finally {
99
+ zeroizeBytes(bytes)
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Constant-time comparison of two byte arrays or strings to prevent timing attacks
105
+ *
106
+ * @param {Uint8Array|string} a
107
+ * @param {Uint8Array|string} b
108
+ * @returns {boolean}
109
+ */
110
+ export function constantTimeCompare (a, b) {
111
+ const bytesA = typeof a === 'string' ? textEncoder.encode(a) : a
112
+ const bytesB = typeof b === 'string' ? textEncoder.encode(b) : b
113
+
114
+ let result = bytesA.length === bytesB.length ? 0 : 1
115
+ const len = Math.min(bytesA.length, bytesB.length)
116
+
117
+ for (let i = 0; i < len; i++) {
118
+ result |= (bytesA[i] ?? 0) ^ (bytesB[i] ?? 0)
119
+ }
120
+
121
+ if (typeof a === 'string') zeroizeBytes(bytesA)
122
+ if (typeof b === 'string') zeroizeBytes(bytesB)
123
+
124
+ return result === 0
125
+ }
@@ -63,6 +63,11 @@ class UrqlClientWrapper {
63
63
  return createClient({
64
64
  url: serverUri,
65
65
  exchanges,
66
+ // urql 5 had no default and always POSTed; urql 6 defaults to 'within-url-limit', which
67
+ // URL-encodes short queries and sends NO body. That would silently disable the CipherHash
68
+ // envelope below — cipherFetch's `typeof init.body === 'string'` guard fails on a GET, so
69
+ // the query would leave as plaintext URL parameters with no error. Pin POST explicitly.
70
+ preferGetMethod: false,
66
71
  // PQ-transport Phase E: when encryption is on, route fetch through the CipherHash
67
72
  // wrapper (encrypt the request body to the validator's ML-KEM pubkey, decrypt the
68
73
  // response). Undefined → urql uses the global fetch (plaintext).
@@ -114,7 +119,7 @@ class UrqlClientWrapper {
114
119
  let requestInit = init
115
120
 
116
121
  if (wallet && serverPubkey && init && typeof init.body === 'string' && this.shouldEncrypt(init.body)) {
117
- const hashVar = await wallet.encryptStringML768(init.body, serverPubkey)
122
+ const hashVar = await wallet.encryptStringML(init.body, serverPubkey)
118
123
  requestInit = { ...init, body: JSON.stringify({ query: CIPHER_HASH_QUERY, variables: { Hash: hashVar } }) }
119
124
  encryptedRequest = true
120
125
  }
@@ -138,7 +143,7 @@ class UrqlClientWrapper {
138
143
  // Plaintext (e.g. a validator-side error response) — pass through unchanged.
139
144
  return new Response(text, init2)
140
145
  }
141
- const decrypted = await wallet.decryptMyMessageML768(JSON.parse(hash))
146
+ const decrypted = await wallet.decryptMyMessageML(JSON.parse(hash))
142
147
  return new Response(decrypted != null ? decrypted : text, init2)
143
148
  }
144
149