@embarkai/ui-kit 0.3.3 → 0.3.5
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/iframe/index.html +1 -1
- package/dist/iframe/main.js +76 -47
- package/dist/iframe/main.js.map +1 -1
- package/dist/index.cjs +451 -275
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +413 -238
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +2 -2
package/dist/iframe/index.html
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
<meta http-equiv="X-Content-Type-Options" content="nosniff" />
|
|
16
16
|
<meta http-equiv="Referrer-Policy" content="strict-origin-when-cross-origin" />
|
|
17
17
|
|
|
18
|
-
<title>EmbarkAI Secure Wallet - iframe version 0.3.
|
|
18
|
+
<title>EmbarkAI Secure Wallet - iframe version 0.3.5</title>
|
|
19
19
|
|
|
20
20
|
<!-- Styles will be injected by build process -->
|
|
21
21
|
<style>
|
package/dist/iframe/main.js
CHANGED
|
@@ -165,8 +165,19 @@ async function encryptKeyshare(data, password, encryptionMethod, credentialId) {
|
|
|
165
165
|
credentialId: encryptionMethod === "passkey" ? credentialId : void 0
|
|
166
166
|
};
|
|
167
167
|
}
|
|
168
|
+
function serializeAadWithKeyOrder(aad, keyOrder) {
|
|
169
|
+
const ordered = {};
|
|
170
|
+
for (const key of keyOrder) {
|
|
171
|
+
if (key in aad) ordered[key] = aad[key];
|
|
172
|
+
}
|
|
173
|
+
return new TextEncoder().encode(JSON.stringify(ordered));
|
|
174
|
+
}
|
|
168
175
|
function serializeAad(aad) {
|
|
169
|
-
|
|
176
|
+
const sorted = Object.keys(aad).sort().reduce((obj, key) => {
|
|
177
|
+
obj[key] = aad[key];
|
|
178
|
+
return obj;
|
|
179
|
+
}, {});
|
|
180
|
+
return new TextEncoder().encode(JSON.stringify(sorted));
|
|
170
181
|
}
|
|
171
182
|
async function envelopeEncryptKeyshare(data, userId) {
|
|
172
183
|
const { kek: kekBytes, credentialId } = await deriveKEKFromPasskey(userId);
|
|
@@ -241,39 +252,47 @@ async function envelopeDecryptKeyshare(envelope, userId) {
|
|
|
241
252
|
console.log("[iframe][envelopeDecryptKeyshare] Importing KEK as crypto key...");
|
|
242
253
|
const kek = await crypto.subtle.importKey("raw", kekBytes, "AES-GCM", false, ["decrypt"]);
|
|
243
254
|
const useAad = envelope.aad?.version >= 2;
|
|
244
|
-
const aadBytes = useAad ? serializeAad(envelope.aad) : void 0;
|
|
245
255
|
console.log("[iframe][envelopeDecryptKeyshare] Decrypting wrapped DEK...");
|
|
246
256
|
const wrappedDekWithIv = base64ToBytes(envelope.wrapped_dek);
|
|
247
257
|
console.log("[iframe][envelopeDecryptKeyshare] Wrapped DEK with IV length:", wrappedDekWithIv.length);
|
|
248
258
|
const wrapIv = wrappedDekWithIv.slice(0, 12);
|
|
249
259
|
const wrappedDekData = wrappedDekWithIv.slice(12);
|
|
250
260
|
console.log("[iframe][envelopeDecryptKeyshare] Wrap IV length:", wrapIv.length, "Wrapped DEK data length:", wrappedDekData.length);
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
261
|
+
const aadCandidates = useAad ? [serializeAad(envelope.aad), serializeAadWithKeyOrder(envelope.aad, LEGACY_V2_KEY_ORDER)] : [void 0];
|
|
262
|
+
let lastError;
|
|
263
|
+
for (const aadBytes of aadCandidates) {
|
|
264
|
+
try {
|
|
265
|
+
const dekBytes = await crypto.subtle.decrypt({ name: "AES-GCM", iv: wrapIv, ...aadBytes && { additionalData: aadBytes } }, kek, wrappedDekData);
|
|
266
|
+
console.log("[iframe][envelopeDecryptKeyshare] DEK decrypted successfully, length:", dekBytes.byteLength);
|
|
267
|
+
console.log("[iframe][envelopeDecryptKeyshare] Importing DEK as crypto key...");
|
|
268
|
+
const dekCryptoKey = await crypto.subtle.importKey("raw", dekBytes, "AES-GCM", false, ["decrypt"]);
|
|
269
|
+
console.log("[iframe][envelopeDecryptKeyshare] Decrypting main data...");
|
|
270
|
+
const ciphertextWithIv = base64ToBytes(envelope.ciphertext_share);
|
|
271
|
+
console.log("[iframe][envelopeDecryptKeyshare] Ciphertext with IV length:", ciphertextWithIv.length);
|
|
272
|
+
const dataIv = ciphertextWithIv.slice(0, 12);
|
|
273
|
+
const encryptedData = ciphertextWithIv.slice(12);
|
|
274
|
+
console.log("[iframe][envelopeDecryptKeyshare] Data IV length:", dataIv.length, "Encrypted data length:", encryptedData.length);
|
|
275
|
+
const decryptedData = await crypto.subtle.decrypt({ name: "AES-GCM", iv: dataIv, ...aadBytes && { additionalData: aadBytes } }, dekCryptoKey, encryptedData);
|
|
276
|
+
console.log("[iframe][envelopeDecryptKeyshare] Main data decrypted successfully, length:", decryptedData.byteLength);
|
|
277
|
+
console.log("[iframe][envelopeDecryptKeyshare] Parsing JSON...");
|
|
278
|
+
const plaintext = new TextDecoder().decode(decryptedData);
|
|
279
|
+
const result = JSON.parse(plaintext);
|
|
280
|
+
console.log("[iframe][envelopeDecryptKeyshare] Decryption completed successfully");
|
|
281
|
+
return result;
|
|
282
|
+
} catch (error) {
|
|
283
|
+
lastError = error;
|
|
284
|
+
if (error instanceof Error && error.name === "OperationError" && aadCandidates.indexOf(aadBytes) < aadCandidates.length - 1) {
|
|
285
|
+
console.log("[iframe][envelopeDecryptKeyshare] AAD mismatch, trying fallback key order...");
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
274
288
|
}
|
|
275
|
-
throw new Error("Failed to decrypt keyshare: " + (error instanceof Error ? error.message : String(error)));
|
|
276
289
|
}
|
|
290
|
+
console.error("[iframe][envelopeDecryptKeyshare] Decryption failed:", lastError);
|
|
291
|
+
if (lastError instanceof Error && lastError.name === "OperationError") {
|
|
292
|
+
const credentialHint = envelope.credentialId ? `The backup requires a specific passkey (ID: ${envelope.credentialId.slice(-8)}...)` : "The backup was encrypted with a different passkey than the one you selected";
|
|
293
|
+
throw new Error(`Passkey mismatch: ${credentialHint}. If you have multiple passkeys, please try again and select the correct passkey that was used when creating this backup.`);
|
|
294
|
+
}
|
|
295
|
+
throw new Error("Failed to decrypt keyshare: " + (lastError instanceof Error ? lastError.message : String(lastError)));
|
|
277
296
|
}
|
|
278
297
|
async function envelopeDecryptKeyshareWithPassword(envelope, password) {
|
|
279
298
|
console.log("[iframe][envelopeDecryptKeyshareWithPassword] Starting password-based decryption");
|
|
@@ -282,29 +301,37 @@ async function envelopeDecryptKeyshareWithPassword(envelope, password) {
|
|
|
282
301
|
const wrapIv = wrappedDekWithSaltAndIv.slice(16, 28);
|
|
283
302
|
const wrappedDekData = wrappedDekWithSaltAndIv.slice(28);
|
|
284
303
|
const useAad = envelope.aad?.version >= 2;
|
|
285
|
-
const aadBytes = useAad ? serializeAad(envelope.aad) : void 0;
|
|
286
304
|
console.log("[iframe][envelopeDecryptKeyshareWithPassword] Salt length:", salt.length, "Wrap IV length:", wrapIv.length, "Wrapped DEK data length:", wrappedDekData.length);
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
+
const aadCandidates = useAad ? [serializeAad(envelope.aad), serializeAadWithKeyOrder(envelope.aad, LEGACY_V2_KEY_ORDER)] : [void 0];
|
|
306
|
+
let lastError;
|
|
307
|
+
for (const aadBytes of aadCandidates) {
|
|
308
|
+
try {
|
|
309
|
+
const kekKey = await deriveKeyFromPassword(password, salt);
|
|
310
|
+
const dekBytes = await crypto.subtle.decrypt({ name: "AES-GCM", iv: wrapIv, ...aadBytes && { additionalData: aadBytes } }, kekKey, wrappedDekData);
|
|
311
|
+
console.log("[iframe][envelopeDecryptKeyshareWithPassword] DEK decrypted successfully, length:", dekBytes.byteLength);
|
|
312
|
+
const dekCryptoKey = await crypto.subtle.importKey("raw", dekBytes, "AES-GCM", false, ["decrypt"]);
|
|
313
|
+
const ciphertextWithIv = base64ToBytes(envelope.ciphertext_share);
|
|
314
|
+
const dataIv = ciphertextWithIv.slice(0, 12);
|
|
315
|
+
const encryptedData = ciphertextWithIv.slice(12);
|
|
316
|
+
const decryptedData = await crypto.subtle.decrypt({ name: "AES-GCM", iv: dataIv, ...aadBytes && { additionalData: aadBytes } }, dekCryptoKey, encryptedData);
|
|
317
|
+
console.log("[iframe][envelopeDecryptKeyshareWithPassword] Main data decrypted successfully");
|
|
318
|
+
const plaintext = new TextDecoder().decode(decryptedData);
|
|
319
|
+
const result = JSON.parse(plaintext);
|
|
320
|
+
console.log("[iframe][envelopeDecryptKeyshareWithPassword] Decryption completed successfully");
|
|
321
|
+
return result;
|
|
322
|
+
} catch (error) {
|
|
323
|
+
lastError = error;
|
|
324
|
+
if (error instanceof Error && error.name === "OperationError" && aadCandidates.indexOf(aadBytes) < aadCandidates.length - 1) {
|
|
325
|
+
console.log("[iframe][envelopeDecryptKeyshareWithPassword] AAD mismatch, trying fallback key order...");
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
305
328
|
}
|
|
306
|
-
throw new Error("Failed to decrypt keyshare with password: " + (error instanceof Error ? error.message : String(error)));
|
|
307
329
|
}
|
|
330
|
+
console.error("[iframe][envelopeDecryptKeyshareWithPassword] Decryption failed:", lastError);
|
|
331
|
+
if (lastError instanceof Error && lastError.name === "OperationError") {
|
|
332
|
+
throw new Error("Incorrect password: Unable to decrypt the backup with the provided password.");
|
|
333
|
+
}
|
|
334
|
+
throw new Error("Failed to decrypt keyshare with password: " + (lastError instanceof Error ? lastError.message : String(lastError)));
|
|
308
335
|
}
|
|
309
336
|
async function decryptKeyshare(encryptedBackup, password) {
|
|
310
337
|
console.log("[iframe][decryptKeyshare] Starting file backup decryption");
|
|
@@ -379,8 +406,10 @@ async function decryptKeyshare(encryptedBackup, password) {
|
|
|
379
406
|
throw new Error(`Failed to decrypt backup: ${message}`);
|
|
380
407
|
}
|
|
381
408
|
}
|
|
409
|
+
var LEGACY_V2_KEY_ORDER;
|
|
382
410
|
var init_crypto_utils = __esm({
|
|
383
411
|
"src/iframe/lib/backup/crypto-utils.ts"() {
|
|
412
|
+
LEGACY_V2_KEY_ORDER = ["userId", "version", "deviceId"];
|
|
384
413
|
}
|
|
385
414
|
});
|
|
386
415
|
|
|
@@ -4410,7 +4439,7 @@ var SigningManager = class extends TokenRefreshApiClient {
|
|
|
4410
4439
|
};
|
|
4411
4440
|
|
|
4412
4441
|
// src/iframe/main.ts
|
|
4413
|
-
var IFRAME_VERSION = "0.3.
|
|
4442
|
+
var IFRAME_VERSION = "0.3.5";
|
|
4414
4443
|
var IframeWallet = class {
|
|
4415
4444
|
constructor() {
|
|
4416
4445
|
console.log("=".repeat(60));
|