@embarkai/ui-kit 0.2.8 → 0.3.1

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.
@@ -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.2.8</title>
18
+ <title>EmbarkAI Secure Wallet - iframe version 0.3.1</title>
19
19
 
20
20
  <!-- Styles will be injected by build process -->
21
21
  <style>
@@ -165,18 +165,23 @@ async function encryptKeyshare(data, password, encryptionMethod, credentialId) {
165
165
  credentialId: encryptionMethod === "passkey" ? credentialId : void 0
166
166
  };
167
167
  }
168
+ function serializeAad(aad) {
169
+ return new TextEncoder().encode(JSON.stringify(aad));
170
+ }
168
171
  async function envelopeEncryptKeyshare(data, userId) {
169
172
  const { kek: kekBytes, credentialId } = await deriveKEKFromPasskey(userId);
170
173
  console.log("[envelopeEncryptKeyshare] Using credential ID for encryption:", credentialId);
174
+ const aad = { userId: data.userId, version: 2, deviceId: "embarkai-ui-kit" };
175
+ const aadBytes = serializeAad(aad);
171
176
  const dek = crypto.getRandomValues(new Uint8Array(32));
172
177
  const kek = await crypto.subtle.importKey("raw", kekBytes, "AES-GCM", false, ["encrypt"]);
173
178
  const plaintext = JSON.stringify(data);
174
179
  const plaintextBytes = new TextEncoder().encode(plaintext);
175
180
  const dekCryptoKey = await crypto.subtle.importKey("raw", dek, "AES-GCM", false, ["encrypt"]);
176
181
  const dataIv = crypto.getRandomValues(new Uint8Array(12));
177
- const encryptedData = await crypto.subtle.encrypt({ name: "AES-GCM", iv: dataIv }, dekCryptoKey, plaintextBytes);
182
+ const encryptedData = await crypto.subtle.encrypt({ name: "AES-GCM", iv: dataIv, additionalData: aadBytes }, dekCryptoKey, plaintextBytes);
178
183
  const wrapIv = crypto.getRandomValues(new Uint8Array(12));
179
- const wrappedDekData = await crypto.subtle.encrypt({ name: "AES-GCM", iv: wrapIv }, kek, dek);
184
+ const wrappedDekData = await crypto.subtle.encrypt({ name: "AES-GCM", iv: wrapIv, additionalData: aadBytes }, kek, dek);
180
185
  const ciphertextWithIv = new Uint8Array(dataIv.length + encryptedData.byteLength);
181
186
  ciphertextWithIv.set(dataIv, 0);
182
187
  ciphertextWithIv.set(new Uint8Array(encryptedData), dataIv.length);
@@ -188,7 +193,7 @@ async function envelopeEncryptKeyshare(data, userId) {
188
193
  wrapped_dek: bytesToBase64(wrappedDekWithIv),
189
194
  kdf: { prf: "webauthn-prf", hkdf: "hkdf-sha256", info: "client-share" },
190
195
  alg: { data: "aes-256-gcm", wrap: "aes-256-gcm" },
191
- aad: { userId: data.userId, version: 1, deviceId: "lumia-ui-kit" },
196
+ aad,
192
197
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
193
198
  expiresAt: null,
194
199
  encryptionMethod: "passkey",
@@ -197,6 +202,8 @@ async function envelopeEncryptKeyshare(data, userId) {
197
202
  }
198
203
  async function envelopeEncryptKeyshareWithPassword(data, password) {
199
204
  console.log("[envelopeEncryptKeyshareWithPassword] Encrypting with password");
205
+ const aad = { userId: data.userId, version: 2, deviceId: "embarkai-ui-kit" };
206
+ const aadBytes = serializeAad(aad);
200
207
  const dek = crypto.getRandomValues(new Uint8Array(32));
201
208
  const salt = crypto.getRandomValues(new Uint8Array(16));
202
209
  const kekKey = await deriveKeyFromPassword(password, salt);
@@ -204,9 +211,9 @@ async function envelopeEncryptKeyshareWithPassword(data, password) {
204
211
  const plaintextBytes = new TextEncoder().encode(plaintext);
205
212
  const dekCryptoKey = await crypto.subtle.importKey("raw", dek, "AES-GCM", false, ["encrypt"]);
206
213
  const dataIv = crypto.getRandomValues(new Uint8Array(12));
207
- const encryptedData = await crypto.subtle.encrypt({ name: "AES-GCM", iv: dataIv }, dekCryptoKey, plaintextBytes);
214
+ const encryptedData = await crypto.subtle.encrypt({ name: "AES-GCM", iv: dataIv, additionalData: aadBytes }, dekCryptoKey, plaintextBytes);
208
215
  const wrapIv = crypto.getRandomValues(new Uint8Array(12));
209
- const wrappedDekData = await crypto.subtle.encrypt({ name: "AES-GCM", iv: wrapIv }, kekKey, dek);
216
+ const wrappedDekData = await crypto.subtle.encrypt({ name: "AES-GCM", iv: wrapIv, additionalData: aadBytes }, kekKey, dek);
210
217
  const ciphertextWithIv = new Uint8Array(dataIv.length + encryptedData.byteLength);
211
218
  ciphertextWithIv.set(dataIv, 0);
212
219
  ciphertextWithIv.set(new Uint8Array(encryptedData), dataIv.length);
@@ -219,7 +226,7 @@ async function envelopeEncryptKeyshareWithPassword(data, password) {
219
226
  wrapped_dek: bytesToBase64(wrappedDekWithIv),
220
227
  kdf: { prf: "pbkdf2", hkdf: "hkdf-sha256", info: "client-share" },
221
228
  alg: { data: "aes-256-gcm", wrap: "aes-256-gcm" },
222
- aad: { userId: data.userId, version: 1, deviceId: "lumia-ui-kit" },
229
+ aad,
223
230
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
224
231
  expiresAt: null,
225
232
  encryptionMethod: "password"
@@ -233,6 +240,8 @@ async function envelopeDecryptKeyshare(envelope, userId) {
233
240
  console.log("[iframe][envelopeDecryptKeyshare] KEK bytes length:", kekBytes.byteLength);
234
241
  console.log("[iframe][envelopeDecryptKeyshare] Importing KEK as crypto key...");
235
242
  const kek = await crypto.subtle.importKey("raw", kekBytes, "AES-GCM", false, ["decrypt"]);
243
+ const useAad = envelope.aad?.version >= 2;
244
+ const aadBytes = useAad ? serializeAad(envelope.aad) : void 0;
236
245
  console.log("[iframe][envelopeDecryptKeyshare] Decrypting wrapped DEK...");
237
246
  const wrappedDekWithIv = base64ToBytes(envelope.wrapped_dek);
238
247
  console.log("[iframe][envelopeDecryptKeyshare] Wrapped DEK with IV length:", wrappedDekWithIv.length);
@@ -240,7 +249,7 @@ async function envelopeDecryptKeyshare(envelope, userId) {
240
249
  const wrappedDekData = wrappedDekWithIv.slice(12);
241
250
  console.log("[iframe][envelopeDecryptKeyshare] Wrap IV length:", wrapIv.length, "Wrapped DEK data length:", wrappedDekData.length);
242
251
  try {
243
- const dekBytes = await crypto.subtle.decrypt({ name: "AES-GCM", iv: wrapIv }, kek, wrappedDekData);
252
+ const dekBytes = await crypto.subtle.decrypt({ name: "AES-GCM", iv: wrapIv, ...aadBytes && { additionalData: aadBytes } }, kek, wrappedDekData);
244
253
  console.log("[iframe][envelopeDecryptKeyshare] DEK decrypted successfully, length:", dekBytes.byteLength);
245
254
  console.log("[iframe][envelopeDecryptKeyshare] Importing DEK as crypto key...");
246
255
  const dekCryptoKey = await crypto.subtle.importKey("raw", dekBytes, "AES-GCM", false, ["decrypt"]);
@@ -250,7 +259,7 @@ async function envelopeDecryptKeyshare(envelope, userId) {
250
259
  const dataIv = ciphertextWithIv.slice(0, 12);
251
260
  const encryptedData = ciphertextWithIv.slice(12);
252
261
  console.log("[iframe][envelopeDecryptKeyshare] Data IV length:", dataIv.length, "Encrypted data length:", encryptedData.length);
253
- const decryptedData = await crypto.subtle.decrypt({ name: "AES-GCM", iv: dataIv }, dekCryptoKey, encryptedData);
262
+ const decryptedData = await crypto.subtle.decrypt({ name: "AES-GCM", iv: dataIv, ...aadBytes && { additionalData: aadBytes } }, dekCryptoKey, encryptedData);
254
263
  console.log("[iframe][envelopeDecryptKeyshare] Main data decrypted successfully, length:", decryptedData.byteLength);
255
264
  console.log("[iframe][envelopeDecryptKeyshare] Parsing JSON...");
256
265
  const plaintext = new TextDecoder().decode(decryptedData);
@@ -272,16 +281,18 @@ async function envelopeDecryptKeyshareWithPassword(envelope, password) {
272
281
  const salt = wrappedDekWithSaltAndIv.slice(0, 16);
273
282
  const wrapIv = wrappedDekWithSaltAndIv.slice(16, 28);
274
283
  const wrappedDekData = wrappedDekWithSaltAndIv.slice(28);
284
+ const useAad = envelope.aad?.version >= 2;
285
+ const aadBytes = useAad ? serializeAad(envelope.aad) : void 0;
275
286
  console.log("[iframe][envelopeDecryptKeyshareWithPassword] Salt length:", salt.length, "Wrap IV length:", wrapIv.length, "Wrapped DEK data length:", wrappedDekData.length);
276
287
  try {
277
288
  const kekKey = await deriveKeyFromPassword(password, salt);
278
- const dekBytes = await crypto.subtle.decrypt({ name: "AES-GCM", iv: wrapIv }, kekKey, wrappedDekData);
289
+ const dekBytes = await crypto.subtle.decrypt({ name: "AES-GCM", iv: wrapIv, ...aadBytes && { additionalData: aadBytes } }, kekKey, wrappedDekData);
279
290
  console.log("[iframe][envelopeDecryptKeyshareWithPassword] DEK decrypted successfully, length:", dekBytes.byteLength);
280
291
  const dekCryptoKey = await crypto.subtle.importKey("raw", dekBytes, "AES-GCM", false, ["decrypt"]);
281
292
  const ciphertextWithIv = base64ToBytes(envelope.ciphertext_share);
282
293
  const dataIv = ciphertextWithIv.slice(0, 12);
283
294
  const encryptedData = ciphertextWithIv.slice(12);
284
- const decryptedData = await crypto.subtle.decrypt({ name: "AES-GCM", iv: dataIv }, dekCryptoKey, encryptedData);
295
+ const decryptedData = await crypto.subtle.decrypt({ name: "AES-GCM", iv: dataIv, ...aadBytes && { additionalData: aadBytes } }, dekCryptoKey, encryptedData);
285
296
  console.log("[iframe][envelopeDecryptKeyshareWithPassword] Main data decrypted successfully");
286
297
  const plaintext = new TextDecoder().decode(decryptedData);
287
298
  const result = JSON.parse(plaintext);
@@ -4399,7 +4410,7 @@ var SigningManager = class extends TokenRefreshApiClient {
4399
4410
  };
4400
4411
 
4401
4412
  // src/iframe/main.ts
4402
- var IFRAME_VERSION = "0.2.8";
4413
+ var IFRAME_VERSION = "0.3.1";
4403
4414
  var IframeWallet = class {
4404
4415
  constructor() {
4405
4416
  console.log("=".repeat(60));