@private.me/xbind 3.0.2 → 3.0.3

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 (221) hide show
  1. package/README.md +2366 -204
  2. package/README.md.backup +2121 -0
  3. package/dist-standalone/_deps/mldsa-wasm/dist/mldsa.js +1 -1920
  4. package/dist-standalone/_deps/shared/cjs/errors.js +1 -729
  5. package/dist-standalone/_deps/shared/cjs/index.js +1 -463
  6. package/dist-standalone/_deps/shared/cjs/types.js +1 -315
  7. package/dist-standalone/_deps/shared/errors.js +1 -244
  8. package/dist-standalone/_deps/shared/index.js +1 -72
  9. package/dist-standalone/_deps/shared/types.js +1 -86
  10. package/dist-standalone/_deps/ux-helpers/cjs/errors.js +1 -1
  11. package/dist-standalone/_deps/ux-helpers/cjs/index.js +1 -1
  12. package/dist-standalone/_deps/ux-helpers/cjs/pagination.js +1 -1
  13. package/dist-standalone/_deps/ux-helpers/cjs/progress.js +1 -1
  14. package/dist-standalone/_deps/ux-helpers/cjs/search.js +1 -1
  15. package/dist-standalone/_deps/ux-helpers/cjs/types.js +1 -1
  16. package/dist-standalone/_deps/ux-helpers/errors.js +1 -1
  17. package/dist-standalone/_deps/ux-helpers/index.js +1 -1
  18. package/dist-standalone/_deps/ux-helpers/pagination.js +1 -1
  19. package/dist-standalone/_deps/ux-helpers/progress.js +1 -1
  20. package/dist-standalone/_deps/ux-helpers/search.js +1 -1
  21. package/dist-standalone/_deps/xchange/auto-accept.js +1 -1
  22. package/dist-standalone/_deps/xchange/cjs/auto-accept.js +1 -1
  23. package/dist-standalone/_deps/xchange/cjs/errors.js +1 -1
  24. package/dist-standalone/_deps/xchange/cjs/index.js +1 -1
  25. package/dist-standalone/_deps/xchange/cjs/invite-client.js +1 -1
  26. package/dist-standalone/_deps/xchange/cjs/lazy-init.js +1 -1
  27. package/dist-standalone/_deps/xchange/cjs/trust-integration.js +1 -1
  28. package/dist-standalone/_deps/xchange/cjs/xchange.js +1 -1
  29. package/dist-standalone/_deps/xchange/errors.js +1 -1
  30. package/dist-standalone/_deps/xchange/index.js +1 -1
  31. package/dist-standalone/_deps/xchange/invite-client.js +1 -1
  32. package/dist-standalone/_deps/xchange/lazy-init.js +1 -1
  33. package/dist-standalone/_deps/xchange/trust-integration.js +1 -1
  34. package/dist-standalone/_deps/xchange/xchange.js +1 -1
  35. package/dist-standalone/_deps/xregistry/cjs/discovery.js +1 -1
  36. package/dist-standalone/_deps/xregistry/cjs/errors.js +1 -1
  37. package/dist-standalone/_deps/xregistry/cjs/index.js +1 -1
  38. package/dist-standalone/_deps/xregistry/cjs/registry.js +1 -1
  39. package/dist-standalone/_deps/xregistry/cjs/schema.js +1 -1
  40. package/dist-standalone/_deps/xregistry/cjs/types.js +1 -1
  41. package/dist-standalone/_deps/xregistry/discovery.js +1 -1
  42. package/dist-standalone/_deps/xregistry/errors.js +1 -1
  43. package/dist-standalone/_deps/xregistry/index.js +1 -1
  44. package/dist-standalone/_deps/xregistry/registry.js +1 -1
  45. package/dist-standalone/_deps/xregistry/schema.js +1 -1
  46. package/dist-standalone/_deps/xregistry/types.js +1 -1
  47. package/dist-standalone/agent-call.d.ts +2 -2
  48. package/dist-standalone/agent-call.js +1 -659
  49. package/dist-standalone/agent-sdk.js +1 -328
  50. package/dist-standalone/agent.d.ts +2 -0
  51. package/dist-standalone/agent.js +1 -1800
  52. package/dist-standalone/approval.js +1 -193
  53. package/dist-standalone/async-iterators.d.ts +3 -3
  54. package/dist-standalone/async-iterators.js +1 -382
  55. package/dist-standalone/auth.js +1 -219
  56. package/dist-standalone/auto-accept.js +1 -229
  57. package/dist-standalone/backup-config.js +1 -201
  58. package/dist-standalone/backup.js +1 -326
  59. package/dist-standalone/batch-operations.js +1 -388
  60. package/dist-standalone/cancellation.js +1 -477
  61. package/dist-standalone/checkpoint.js +1 -186
  62. package/dist-standalone/circuit-breaker.js +1 -468
  63. package/dist-standalone/cjs/agent-call.js +1 -701
  64. package/dist-standalone/cjs/agent-sdk.js +1 -332
  65. package/dist-standalone/cjs/agent.js +1 -1837
  66. package/dist-standalone/cjs/approval.js +1 -199
  67. package/dist-standalone/cjs/async-iterators.js +1 -392
  68. package/dist-standalone/cjs/auth.js +1 -225
  69. package/dist-standalone/cjs/auto-accept.js +1 -233
  70. package/dist-standalone/cjs/backup-config.js +1 -207
  71. package/dist-standalone/cjs/backup.js +1 -330
  72. package/dist-standalone/cjs/batch-operations.js +1 -397
  73. package/dist-standalone/cjs/cancellation.js +1 -490
  74. package/dist-standalone/cjs/checkpoint.js +1 -193
  75. package/dist-standalone/cjs/circuit-breaker.js +1 -476
  76. package/dist-standalone/cjs/cli/init.js +1 -492
  77. package/dist-standalone/cjs/config-validation.js +1 -522
  78. package/dist-standalone/cjs/connect.js +1 -312
  79. package/dist-standalone/cjs/connection-pool.js +1 -506
  80. package/dist-standalone/cjs/correlation-id.js +1 -339
  81. package/dist-standalone/cjs/crypto-utils.js +1 -176
  82. package/dist-standalone/cjs/debug-mode.js +1 -534
  83. package/dist-standalone/cjs/did-document.js +1 -101
  84. package/dist-standalone/cjs/did-privateme.js +1 -130
  85. package/dist-standalone/cjs/did-web.js +1 -201
  86. package/dist-standalone/cjs/discovery.js +1 -462
  87. package/dist-standalone/cjs/dual-mode.js +1 -251
  88. package/dist-standalone/cjs/email-templates.js +1 -313
  89. package/dist-standalone/cjs/email-transport.js +1 -239
  90. package/dist-standalone/cjs/envelope.js +1 -538
  91. package/dist-standalone/cjs/errors.js +1 -913
  92. package/dist-standalone/cjs/event-emitter.js +1 -461
  93. package/dist-standalone/cjs/gateway-state.js +1 -55
  94. package/dist-standalone/cjs/gateway-transport.js +1 -120
  95. package/dist-standalone/cjs/graceful-degradation.js +1 -403
  96. package/dist-standalone/cjs/guardrails.js +1 -223
  97. package/dist-standalone/cjs/health-check.js +1 -336
  98. package/dist-standalone/cjs/http-compat.js +1 -272
  99. package/dist-standalone/cjs/http-status-map.js +1 -571
  100. package/dist-standalone/cjs/identity.js +1 -645
  101. package/dist-standalone/cjs/index.js +1 -406
  102. package/dist-standalone/cjs/invitation.js +1 -421
  103. package/dist-standalone/cjs/invite.js +1 -328
  104. package/dist-standalone/cjs/key-agreement.js +1 -335
  105. package/dist-standalone/cjs/lazy-init.js +1 -300
  106. package/dist-standalone/cjs/logger.js +1 -291
  107. package/dist-standalone/cjs/loopback-transport.js +1 -0
  108. package/dist-standalone/cjs/mdns-discovery.js +1 -202
  109. package/dist-standalone/cjs/nonce-store.js +1 -80
  110. package/dist-standalone/cjs/pairing-manager.js +1 -223
  111. package/dist-standalone/cjs/plugin-system.js +1 -264
  112. package/dist-standalone/cjs/plugins/logging.js +1 -168
  113. package/dist-standalone/cjs/plugins/metrics.js +1 -181
  114. package/dist-standalone/cjs/plugins/validation.js +1 -302
  115. package/dist-standalone/cjs/policy.js +1 -320
  116. package/dist-standalone/cjs/progress-callbacks.js +1 -583
  117. package/dist-standalone/cjs/redis-nonce-store.js +1 -76
  118. package/dist-standalone/cjs/registry-middleware.js +1 -50
  119. package/dist-standalone/cjs/retry-strategies.js +1 -544
  120. package/dist-standalone/cjs/retry-transport.js +1 -102
  121. package/dist-standalone/cjs/runtime/browser.js +1 -533
  122. package/dist-standalone/cjs/runtime/edge.js +1 -526
  123. package/dist-standalone/cjs/runtime/react-native.js +1 -394
  124. package/dist-standalone/cjs/security-policy.js +1 -245
  125. package/dist-standalone/cjs/serialization.js +1 -1040
  126. package/dist-standalone/cjs/split-channel.js +1 -225
  127. package/dist-standalone/cjs/subscription-proof.js +1 -230
  128. package/dist-standalone/cjs/succession.js +1 -148
  129. package/dist-standalone/cjs/timeouts.js +1 -412
  130. package/dist-standalone/cjs/trace-context.js +1 -424
  131. package/dist-standalone/cjs/trace-spans.js +1 -495
  132. package/dist-standalone/cjs/transport.js +1 -63
  133. package/dist-standalone/cjs/trust-registry.js +1 -991
  134. package/dist-standalone/cjs/types/error-response.js +1 -56
  135. package/dist-standalone/cjs/vault-auth.js +1 -178
  136. package/dist-standalone/cjs/vault-store-loader.js +1 -194
  137. package/dist-standalone/cjs/verify.js +1 -25
  138. package/dist-standalone/cjs/version-info.js +1 -543
  139. package/dist-standalone/cjs/xfetch.js +1 -340
  140. package/dist-standalone/cli/init.js +1 -455
  141. package/dist-standalone/cli/setup.js +1 -514
  142. package/dist-standalone/cli/types.js +1 -27
  143. package/dist-standalone/cli/xbind.js +1 -148
  144. package/dist-standalone/config-validation.js +1 -513
  145. package/dist-standalone/connect.js +1 -274
  146. package/dist-standalone/connection-pool.js +1 -500
  147. package/dist-standalone/correlation-id.js +1 -326
  148. package/dist-standalone/crypto-utils.d.ts +2 -7
  149. package/dist-standalone/crypto-utils.js +1 -157
  150. package/dist-standalone/debug-mode.js +1 -510
  151. package/dist-standalone/did-document.js +1 -96
  152. package/dist-standalone/did-privateme.js +1 -121
  153. package/dist-standalone/did-web.js +1 -196
  154. package/dist-standalone/discovery.js +1 -458
  155. package/dist-standalone/dual-mode.js +1 -247
  156. package/dist-standalone/email-templates.js +1 -309
  157. package/dist-standalone/email-transport.d.ts +2 -2
  158. package/dist-standalone/email-transport.js +1 -232
  159. package/dist-standalone/envelope.js +1 -525
  160. package/dist-standalone/errors.d.ts +13 -3
  161. package/dist-standalone/errors.js +1 -896
  162. package/dist-standalone/event-emitter.js +1 -456
  163. package/dist-standalone/gateway-state.d.ts +1 -1
  164. package/dist-standalone/gateway-state.js +1 -51
  165. package/dist-standalone/gateway-transport.js +1 -116
  166. package/dist-standalone/graceful-degradation.js +1 -396
  167. package/dist-standalone/guardrails.js +1 -216
  168. package/dist-standalone/health-check.d.ts +5 -1
  169. package/dist-standalone/health-check.js +1 -332
  170. package/dist-standalone/http-compat.d.ts +1 -1
  171. package/dist-standalone/http-compat.js +1 -267
  172. package/dist-standalone/http-status-map.js +1 -561
  173. package/dist-standalone/identity.js +1 -619
  174. package/dist-standalone/index.d.ts +15 -4
  175. package/dist-standalone/index.js +1 -78
  176. package/dist-standalone/invitation.js +1 -415
  177. package/dist-standalone/invite.js +1 -324
  178. package/dist-standalone/key-agreement.js +1 -325
  179. package/dist-standalone/lazy-init.d.ts +11 -6
  180. package/dist-standalone/lazy-init.js +1 -295
  181. package/dist-standalone/logger.js +1 -285
  182. package/dist-standalone/loopback-transport.d.ts +87 -0
  183. package/dist-standalone/loopback-transport.js +1 -0
  184. package/dist-standalone/mdns-discovery.js +1 -195
  185. package/dist-standalone/nonce-store.js +1 -76
  186. package/dist-standalone/pairing-manager.js +1 -219
  187. package/dist-standalone/plugin-system.js +1 -257
  188. package/dist-standalone/plugins/logging.js +1 -163
  189. package/dist-standalone/plugins/metrics.d.ts +4 -4
  190. package/dist-standalone/plugins/metrics.js +1 -176
  191. package/dist-standalone/plugins/validation.js +1 -297
  192. package/dist-standalone/policy.js +1 -315
  193. package/dist-standalone/progress-callbacks.js +1 -576
  194. package/dist-standalone/redis-nonce-store.js +1 -72
  195. package/dist-standalone/registry-middleware.js +1 -47
  196. package/dist-standalone/retry-strategies.js +1 -534
  197. package/dist-standalone/retry-transport.js +1 -98
  198. package/dist-standalone/runtime/browser.js +1 -516
  199. package/dist-standalone/runtime/edge.js +1 -511
  200. package/dist-standalone/runtime/react-native.d.ts +1 -1
  201. package/dist-standalone/runtime/react-native.js +1 -383
  202. package/dist-standalone/security-policy.js +1 -239
  203. package/dist-standalone/serialization.js +1 -1031
  204. package/dist-standalone/split-channel.js +1 -219
  205. package/dist-standalone/subscription-proof.js +1 -224
  206. package/dist-standalone/succession.js +1 -142
  207. package/dist-standalone/timeouts.js +1 -398
  208. package/dist-standalone/trace-context.js +1 -414
  209. package/dist-standalone/trace-spans.js +1 -488
  210. package/dist-standalone/transport.js +1 -59
  211. package/dist-standalone/trust-registry.d.ts +3 -3
  212. package/dist-standalone/trust-registry.js +1 -950
  213. package/dist-standalone/types/error-response.js +1 -52
  214. package/dist-standalone/vault-auth.js +1 -174
  215. package/dist-standalone/vault-store-loader.d.ts +9 -0
  216. package/dist-standalone/vault-store-loader.js +1 -187
  217. package/dist-standalone/verify.js +1 -16
  218. package/dist-standalone/version-info.js +1 -530
  219. package/dist-standalone/xfetch.js +1 -335
  220. package/package.json +1 -1
  221. package/share1.dat +0 -0
@@ -1,330 +1 @@
1
- "use strict";
2
- /**
3
- * Encrypted Backup and Restore (RCV-3)
4
- *
5
- * Exports and imports encrypted identity and cryptographic state.
6
- * Uses PBKDF2 (NIST SP 800-132) for key derivation and AES-256-GCM
7
- * for authenticated encryption.
8
- *
9
- * @module backup
10
- */
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.exportBackup = exportBackup;
13
- exports.importBackup = importBackup;
14
- const shared_1 = require("../_deps/shared/index.js");
15
- const crypto_utils_js_1 = require("./crypto-utils.js");
16
- const identity_js_1 = require("./identity.js");
17
- /* ── Constants ── */
18
- /** PBKDF2 iterations for key derivation (NIST SP 800-132 minimum: 100,000). */
19
- const PBKDF2_ITERATIONS = 310_000;
20
- /** PBKDF2 salt length in bytes. */
21
- const SALT_LENGTH = 16;
22
- /** AES-256-GCM IV length in bytes. */
23
- const IV_LENGTH = 12;
24
- /** AES-256-GCM key length in bytes. */
25
- const KEY_LENGTH = 32;
26
- /* ── Utility Functions ── */
27
- /**
28
- * Copy Uint8Array to fresh ArrayBuffer (avoids SharedArrayBuffer type issues).
29
- */
30
- function toArrayBuffer(data) {
31
- const buf = new ArrayBuffer(data.byteLength);
32
- new Uint8Array(buf).set(data);
33
- return buf;
34
- }
35
- /**
36
- * Derive a 256-bit AES key from password using PBKDF2-SHA256.
37
- *
38
- * Uses NIST SP 800-132 recommended parameters:
39
- * - 310,000 iterations (as of 2025, recommended for 100ms delay on modern hardware)
40
- * - SHA-256 as PRF
41
- * - 16-byte salt
42
- *
43
- * @param password - User password (UTF-8 string).
44
- * @param salt - 16-byte random salt.
45
- * @returns AES-256 key or error.
46
- */
47
- async function deriveKey(password, salt) {
48
- try {
49
- if (salt.length !== SALT_LENGTH) {
50
- return (0, shared_1.err)('INVALID_BACKUP');
51
- }
52
- // Import password as PBKDF2 base key
53
- const baseKey = await crypto.subtle.importKey('raw', new TextEncoder().encode(password), 'PBKDF2', false, ['deriveBits']);
54
- // Derive 256 bits (32 bytes) for AES-256
55
- const derivedBits = new Uint8Array(await crypto.subtle.deriveBits({
56
- name: 'PBKDF2',
57
- hash: 'SHA-256',
58
- salt: toArrayBuffer(salt),
59
- iterations: PBKDF2_ITERATIONS,
60
- }, baseKey, 256));
61
- // Import derived key as AES-GCM key
62
- const aesKey = await crypto.subtle.importKey('raw', toArrayBuffer(derivedBits), { name: 'AES-GCM' }, false, ['encrypt', 'decrypt']);
63
- return (0, shared_1.ok)(aesKey);
64
- }
65
- catch {
66
- return (0, shared_1.err)('PBKDF2_FAILED');
67
- }
68
- }
69
- /**
70
- * Serialize an AgentIdentity to a plaintext backup payload.
71
- * (The payload is then encrypted before storage.)
72
- */
73
- async function serializeIdentity(identity) {
74
- try {
75
- // Export Ed25519 and X25519 private keys as PKCS8
76
- const ed25519PkResult = await (0, identity_js_1.exportPKCS8)(identity.privateKey);
77
- if (!ed25519PkResult.ok)
78
- return (0, shared_1.err)('EXPORT_FAILED');
79
- const x25519PkResult = await (0, identity_js_1.exportX25519PKCS8)(identity.x25519PrivateKey);
80
- if (!x25519PkResult.ok)
81
- return (0, shared_1.err)('EXPORT_FAILED');
82
- // Collect ML-KEM and ML-DSA keys if present
83
- const mlKemSecretKey = (0, identity_js_1.exportMlKemSecretKey)(identity);
84
- const mlKemPublicKey = (0, identity_js_1.exportMlKemPublicKey)(identity);
85
- const mlDsaSecretKey = (0, identity_js_1.exportMlDsaSecretKey)(identity);
86
- const mlDsaPublicKey = (0, identity_js_1.exportMlDsaPublicKey)(identity);
87
- // Serialize rotated keys
88
- const rotatedKeys = identity.rotatedKeys
89
- ? await Promise.all(identity.rotatedKeys.map(async (rotated) => {
90
- const x25519Pk = await (0, identity_js_1.exportX25519PKCS8)(rotated.x25519PrivateKey);
91
- if (!x25519Pk.ok)
92
- throw new Error('Failed to export rotated X25519 key');
93
- return {
94
- rotatedAt: rotated.rotatedAt,
95
- x25519Pkcs8: (0, crypto_utils_js_1.toBase64)(x25519Pk.value),
96
- ...(rotated.mlKemSecretKey ? { mlKemSecretKey: (0, crypto_utils_js_1.toBase64)(rotated.mlKemSecretKey) } : {}),
97
- };
98
- }))
99
- : undefined;
100
- return (0, shared_1.ok)({
101
- did: identity.did,
102
- rawPublicKey: (0, crypto_utils_js_1.toBase64)(identity.rawPublicKey),
103
- ed25519Pkcs8: (0, crypto_utils_js_1.toBase64)(ed25519PkResult.value),
104
- x25519Pkcs8: (0, crypto_utils_js_1.toBase64)(x25519PkResult.value),
105
- ...(mlKemSecretKey ? { mlKemSecretKey: (0, crypto_utils_js_1.toBase64)(mlKemSecretKey) } : {}),
106
- ...(mlKemPublicKey ? { mlKemPublicKey: (0, crypto_utils_js_1.toBase64)(mlKemPublicKey) } : {}),
107
- ...(mlDsaSecretKey ? { mlDsaSecretKey: (0, crypto_utils_js_1.toBase64)(mlDsaSecretKey) } : {}),
108
- ...(mlDsaPublicKey ? { mlDsaPublicKey: (0, crypto_utils_js_1.toBase64)(mlDsaPublicKey) } : {}),
109
- ...(rotatedKeys ? { rotatedKeys } : {}),
110
- exportedAt: Date.now(),
111
- });
112
- }
113
- catch {
114
- return (0, shared_1.err)('EXPORT_FAILED');
115
- }
116
- }
117
- /* ── Export: Encrypt Identity to Backup ── */
118
- /**
119
- * Export an identity as an encrypted backup blob.
120
- *
121
- * Encrypts the complete identity (Ed25519, X25519, ML-KEM, ML-DSA keys,
122
- * rotated keys) with a password using PBKDF2 + AES-256-GCM.
123
- *
124
- * The backup can be stored safely in cloud storage, version control, or
125
- * transmitted over untrusted channels. Only the password holder can decrypt.
126
- *
127
- * Security:
128
- * - PBKDF2-SHA256 with 310,000 iterations (≈100ms on modern hardware)
129
- * - AES-256-GCM for authenticated encryption
130
- * - Random salt + IV for each backup (no two backups are identical)
131
- * - 16-byte GCM tag prevents tampering
132
- *
133
- * @param identity - Agent identity to backup.
134
- * @param password - User password (plaintext). Will be PBKDF2 derived.
135
- * @returns Encrypted backup blob or error.
136
- *
137
- * @example
138
- * ```typescript
139
- * import { generateIdentity } from '@private.me/xbind';
140
- * import { exportBackup } from '@private.me/xbind';
141
- *
142
- * const identity = await generateIdentity();
143
- * if (!identity.ok) throw identity.error;
144
- *
145
- * const backup = await exportBackup(identity.value, 'user-password');
146
- * if (!backup.ok) throw backup.error;
147
- *
148
- * // Store backup securely
149
- * const json = JSON.stringify(backup.value);
150
- * localStorage.setItem('backup', json);
151
- * ```
152
- */
153
- async function exportBackup(identity, password) {
154
- try {
155
- // Serialize identity to plaintext payload
156
- const payloadResult = await serializeIdentity(identity);
157
- if (!payloadResult.ok)
158
- return payloadResult;
159
- // Generate random salt and IV
160
- const salt = crypto.getRandomValues(new Uint8Array(SALT_LENGTH));
161
- const iv = crypto.getRandomValues(new Uint8Array(IV_LENGTH));
162
- // Derive AES key from password
163
- const keyResult = await deriveKey(password, salt);
164
- if (!keyResult.ok)
165
- return keyResult;
166
- // Encrypt payload as JSON
167
- const payloadJson = JSON.stringify(payloadResult.value);
168
- const plaintext = new TextEncoder().encode(payloadJson);
169
- // Encrypt with AES-256-GCM
170
- const encryptResult = await crypto.subtle.encrypt({ name: 'AES-GCM', iv: toArrayBuffer(iv) }, keyResult.value, plaintext);
171
- const ciphertext = new Uint8Array(encryptResult);
172
- // GCM includes authentication tag in the ciphertext.
173
- // Split: ciphertext is everything except last 16 bytes, tag is last 16 bytes.
174
- // (Web Crypto API appends the tag to the ciphertext)
175
- if (ciphertext.length < 16) {
176
- return (0, shared_1.err)('ENCRYPTION_FAILED');
177
- }
178
- const ctLen = ciphertext.length - 16;
179
- const ct = ciphertext.slice(0, ctLen);
180
- const tag = ciphertext.slice(ctLen);
181
- return (0, shared_1.ok)({
182
- version: 1,
183
- salt: (0, crypto_utils_js_1.toBase64)(salt),
184
- iv: (0, crypto_utils_js_1.toBase64)(iv),
185
- ciphertext: (0, crypto_utils_js_1.toBase64)(ct),
186
- tag: (0, crypto_utils_js_1.toBase64)(tag),
187
- });
188
- }
189
- catch {
190
- return (0, shared_1.err)('ENCRYPTION_FAILED');
191
- }
192
- }
193
- /* ── Import: Decrypt Backup to Identity ── */
194
- /**
195
- * Restore an identity from an encrypted backup blob.
196
- *
197
- * Decrypts the backup using PBKDF2-derived AES key. Verifies authenticity
198
- * with GCM tag before returning plaintext keys.
199
- *
200
- * @param backup - Encrypted backup blob.
201
- * @param password - User password (plaintext). Will be PBKDF2 derived.
202
- * @returns Restored AgentIdentity or error.
203
- *
204
- * @example
205
- * ```typescript
206
- * import { importBackup } from '@private.me/xbind';
207
- *
208
- * const json = localStorage.getItem('backup');
209
- * const backup = JSON.parse(json);
210
- *
211
- * const identity = await importBackup(backup, 'user-password');
212
- * if (!identity.ok) {
213
- * if (identity.error === 'INVALID_PASSWORD') {
214
- * console.error('Wrong password!');
215
- * } else {
216
- * throw identity.error;
217
- * }
218
- * }
219
- *
220
- * // Now use restored identity
221
- * const agent = new Agent(identity.value);
222
- * ```
223
- */
224
- async function importBackup(backup, password) {
225
- try {
226
- // Validate version
227
- if (backup.version !== 1) {
228
- return (0, shared_1.err)('INVALID_BACKUP');
229
- }
230
- // Decode base64 fields
231
- let salt;
232
- let iv;
233
- let ciphertext;
234
- let tag;
235
- try {
236
- salt = (0, crypto_utils_js_1.fromBase64)(backup.salt);
237
- iv = (0, crypto_utils_js_1.fromBase64)(backup.iv);
238
- ciphertext = (0, crypto_utils_js_1.fromBase64)(backup.ciphertext);
239
- tag = (0, crypto_utils_js_1.fromBase64)(backup.tag);
240
- }
241
- catch {
242
- return (0, shared_1.err)('INVALID_BACKUP');
243
- }
244
- // Validate lengths
245
- if (salt.length !== SALT_LENGTH || iv.length !== IV_LENGTH || tag.length !== 16) {
246
- return (0, shared_1.err)('INVALID_BACKUP');
247
- }
248
- // Derive AES key from password
249
- const keyResult = await deriveKey(password, salt);
250
- if (!keyResult.ok)
251
- return keyResult;
252
- // Reconstruct full GCM input (ciphertext + tag)
253
- const gcmInput = new Uint8Array(ciphertext.length + tag.length);
254
- gcmInput.set(ciphertext);
255
- gcmInput.set(tag, ciphertext.length);
256
- // Decrypt with AES-256-GCM
257
- let plaintext;
258
- try {
259
- plaintext = await crypto.subtle.decrypt({ name: 'AES-GCM', iv: toArrayBuffer(iv) }, keyResult.value, toArrayBuffer(gcmInput));
260
- }
261
- catch (decryptErr) {
262
- // GCM authentication failure (wrong password or tampered backup)
263
- console.warn('[xBind] GCM verification failed:', decryptErr);
264
- return (0, shared_1.err)('INVALID_PASSWORD');
265
- }
266
- // Parse JSON payload
267
- let payload;
268
- try {
269
- const jsonStr = new TextDecoder().decode(plaintext);
270
- payload = JSON.parse(jsonStr);
271
- }
272
- catch {
273
- return (0, shared_1.err)('INVALID_BACKUP');
274
- }
275
- // Validate payload structure
276
- if (!payload.did || !payload.ed25519Pkcs8 || !payload.x25519Pkcs8) {
277
- return (0, shared_1.err)('INVALID_BACKUP');
278
- }
279
- // Decode base64 keys
280
- let ed25519Pkcs8;
281
- let x25519Pkcs8;
282
- let mlKemSecretKey;
283
- let mlKemPublicKey;
284
- let mlDsaSecretKey;
285
- let mlDsaPublicKey;
286
- try {
287
- ed25519Pkcs8 = (0, crypto_utils_js_1.fromBase64)(payload.ed25519Pkcs8);
288
- x25519Pkcs8 = (0, crypto_utils_js_1.fromBase64)(payload.x25519Pkcs8);
289
- if (payload.mlKemSecretKey)
290
- mlKemSecretKey = (0, crypto_utils_js_1.fromBase64)(payload.mlKemSecretKey);
291
- if (payload.mlKemPublicKey)
292
- mlKemPublicKey = (0, crypto_utils_js_1.fromBase64)(payload.mlKemPublicKey);
293
- if (payload.mlDsaSecretKey)
294
- mlDsaSecretKey = (0, crypto_utils_js_1.fromBase64)(payload.mlDsaSecretKey);
295
- if (payload.mlDsaPublicKey)
296
- mlDsaPublicKey = (0, crypto_utils_js_1.fromBase64)(payload.mlDsaPublicKey);
297
- }
298
- catch {
299
- return (0, shared_1.err)('INVALID_BACKUP');
300
- }
301
- // Import identity from decoded keys
302
- const identity = await (0, identity_js_1.importIdentity)(ed25519Pkcs8, x25519Pkcs8, mlKemSecretKey, mlKemPublicKey, mlDsaSecretKey, mlDsaPublicKey);
303
- if (!identity.ok)
304
- return (0, shared_1.err)('IMPORT_FAILED');
305
- // Restore rotated keys if present
306
- if (payload.rotatedKeys && payload.rotatedKeys.length > 0) {
307
- const restored = identity.value;
308
- const rotatedKeys = await Promise.all(payload.rotatedKeys.map(async (rk) => {
309
- const x25519Pk = (0, crypto_utils_js_1.fromBase64)(rk.x25519Pkcs8);
310
- const x25519PrivateKey = await crypto.subtle.importKey('pkcs8', toArrayBuffer(x25519Pk), { name: 'X25519' }, true, ['deriveBits']);
311
- const mlKemSecretKeyRk = rk.mlKemSecretKey ? (0, crypto_utils_js_1.fromBase64)(rk.mlKemSecretKey) : undefined;
312
- return {
313
- rotatedAt: rk.rotatedAt,
314
- x25519PrivateKey,
315
- ...(mlKemSecretKeyRk ? { mlKemSecretKey: mlKemSecretKeyRk } : {}),
316
- };
317
- }));
318
- // Return identity with restored rotated keys
319
- return (0, shared_1.ok)({
320
- ...restored,
321
- rotatedKeys: rotatedKeys,
322
- });
323
- }
324
- return identity;
325
- }
326
- catch (importErr) {
327
- console.warn('[xBind] Import backup failed:', importErr);
328
- return (0, shared_1.err)('DECRYPTION_FAILED');
329
- }
330
- }
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.exportBackup=exportBackup,exports.importBackup=importBackup;const shared_1=require("../_deps/shared/index.js"),crypto_utils_js_1=require("./crypto-utils.js"),identity_js_1=require("./identity.js"),PBKDF2_ITERATIONS=31e4,SALT_LENGTH=16,IV_LENGTH=12;function toArrayBuffer(e){const t=new ArrayBuffer(e.byteLength);return new Uint8Array(t).set(e),t}async function deriveKey(e,t){try{if(t.length!==SALT_LENGTH)return(0,shared_1.err)("INVALID_BACKUP");const r=await crypto.subtle.importKey("raw",(new TextEncoder).encode(e),"PBKDF2",!1,["deriveBits"]),s=new Uint8Array(await crypto.subtle.deriveBits({name:"PBKDF2",hash:"SHA-256",salt:toArrayBuffer(t),iterations:31e4},r,256)),a=await crypto.subtle.importKey("raw",toArrayBuffer(s),{name:"AES-GCM"},!1,["encrypt","decrypt"]);return(0,shared_1.ok)(a)}catch{return(0,shared_1.err)("PBKDF2_FAILED")}}async function serializeIdentity(e){try{const t=await(0,identity_js_1.exportPKCS8)(e.privateKey);if(!t.ok)return(0,shared_1.err)("EXPORT_FAILED");const r=await(0,identity_js_1.exportX25519PKCS8)(e.x25519PrivateKey);if(!r.ok)return(0,shared_1.err)("EXPORT_FAILED");const s=(0,identity_js_1.exportMlKemSecretKey)(e),a=(0,identity_js_1.exportMlKemPublicKey)(e),o=(0,identity_js_1.exportMlDsaSecretKey)(e),i=(0,identity_js_1.exportMlDsaPublicKey)(e),_=e.rotatedKeys?await Promise.all(e.rotatedKeys.map(async e=>{const t=await(0,identity_js_1.exportX25519PKCS8)(e.x25519PrivateKey);if(!t.ok)throw new Error("Failed to export rotated X25519 key");return{rotatedAt:e.rotatedAt,x25519Pkcs8:(0,crypto_utils_js_1.toBase64)(t.value),...e.mlKemSecretKey?{mlKemSecretKey:(0,crypto_utils_js_1.toBase64)(e.mlKemSecretKey)}:{}}})):void 0;return(0,shared_1.ok)({did:e.did,rawPublicKey:(0,crypto_utils_js_1.toBase64)(e.rawPublicKey),ed25519Pkcs8:(0,crypto_utils_js_1.toBase64)(t.value),x25519Pkcs8:(0,crypto_utils_js_1.toBase64)(r.value),...s?{mlKemSecretKey:(0,crypto_utils_js_1.toBase64)(s)}:{},...a?{mlKemPublicKey:(0,crypto_utils_js_1.toBase64)(a)}:{},...o?{mlDsaSecretKey:(0,crypto_utils_js_1.toBase64)(o)}:{},...i?{mlDsaPublicKey:(0,crypto_utils_js_1.toBase64)(i)}:{},..._?{rotatedKeys:_}:{},exportedAt:Date.now()})}catch{return(0,shared_1.err)("EXPORT_FAILED")}}async function exportBackup(e,t){try{const r=await serializeIdentity(e);if(!r.ok)return r;const s=crypto.getRandomValues(new Uint8Array(SALT_LENGTH)),a=crypto.getRandomValues(new Uint8Array(IV_LENGTH)),o=await deriveKey(t,s);if(!o.ok)return o;const i=JSON.stringify(r.value),_=(new TextEncoder).encode(i),c=await crypto.subtle.encrypt({name:"AES-GCM",iv:toArrayBuffer(a)},o.value,_),y=new Uint8Array(c);if(y.length<16)return(0,shared_1.err)("ENCRYPTION_FAILED");const n=y.length-16,u=y.slice(0,n),l=y.slice(n);return(0,shared_1.ok)({version:1,salt:(0,crypto_utils_js_1.toBase64)(s),iv:(0,crypto_utils_js_1.toBase64)(a),ciphertext:(0,crypto_utils_js_1.toBase64)(u),tag:(0,crypto_utils_js_1.toBase64)(l)})}catch{return(0,shared_1.err)("ENCRYPTION_FAILED")}}async function importBackup(e,t){try{if(1!==e.version)return(0,shared_1.err)("INVALID_BACKUP");let r,s,a,o;try{r=(0,crypto_utils_js_1.fromBase64)(e.salt),s=(0,crypto_utils_js_1.fromBase64)(e.iv),a=(0,crypto_utils_js_1.fromBase64)(e.ciphertext),o=(0,crypto_utils_js_1.fromBase64)(e.tag)}catch{return(0,shared_1.err)("INVALID_BACKUP")}if(r.length!==SALT_LENGTH||s.length!==IV_LENGTH||16!==o.length)return(0,shared_1.err)("INVALID_BACKUP");const i=await deriveKey(t,r);if(!i.ok)return i;const _=new Uint8Array(a.length+o.length);let c,y,n,u,l,d,p,K;_.set(a),_.set(o,a.length);try{c=await crypto.subtle.decrypt({name:"AES-GCM",iv:toArrayBuffer(s)},i.value,toArrayBuffer(_))}catch{return(0,shared_1.err)("INVALID_PASSWORD")}try{const e=(new TextDecoder).decode(c);y=JSON.parse(e)}catch{return(0,shared_1.err)("INVALID_BACKUP")}if(!y.did||!y.ed25519Pkcs8||!y.x25519Pkcs8)return(0,shared_1.err)("INVALID_BACKUP");try{n=(0,crypto_utils_js_1.fromBase64)(y.ed25519Pkcs8),u=(0,crypto_utils_js_1.fromBase64)(y.x25519Pkcs8),y.mlKemSecretKey&&(l=(0,crypto_utils_js_1.fromBase64)(y.mlKemSecretKey)),y.mlKemPublicKey&&(d=(0,crypto_utils_js_1.fromBase64)(y.mlKemPublicKey)),y.mlDsaSecretKey&&(p=(0,crypto_utils_js_1.fromBase64)(y.mlDsaSecretKey)),y.mlDsaPublicKey&&(K=(0,crypto_utils_js_1.fromBase64)(y.mlDsaPublicKey))}catch{return(0,shared_1.err)("INVALID_BACKUP")}const m=await(0,identity_js_1.importIdentity)(n,u,l,d,p,K);if(!m.ok)return(0,shared_1.err)("IMPORT_FAILED");if(y.rotatedKeys&&y.rotatedKeys.length>0){const e=m.value,t=await Promise.all(y.rotatedKeys.map(async e=>{const t=(0,crypto_utils_js_1.fromBase64)(e.x25519Pkcs8),r=await crypto.subtle.importKey("pkcs8",toArrayBuffer(t),{name:"X25519"},!0,["deriveBits"]),s=e.mlKemSecretKey?(0,crypto_utils_js_1.fromBase64)(e.mlKemSecretKey):void 0;return{rotatedAt:e.rotatedAt,x25519PrivateKey:r,...s?{mlKemSecretKey:s}:{}}}));return(0,shared_1.ok)({...e,rotatedKeys:t})}return m}catch{return(0,shared_1.err)("DECRYPTION_FAILED")}}