@metamask/profile-sync-controller 2.0.0 → 3.1.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.
Files changed (140) hide show
  1. package/CHANGELOG.md +45 -1
  2. package/dist/controllers/authentication/AuthenticationController.cjs +0 -1
  3. package/dist/controllers/authentication/AuthenticationController.cjs.map +1 -1
  4. package/dist/controllers/authentication/AuthenticationController.d.cts.map +1 -1
  5. package/dist/controllers/authentication/AuthenticationController.d.mts.map +1 -1
  6. package/dist/controllers/authentication/AuthenticationController.mjs +0 -1
  7. package/dist/controllers/authentication/AuthenticationController.mjs.map +1 -1
  8. package/dist/controllers/user-storage/UserStorageController.cjs +55 -22
  9. package/dist/controllers/user-storage/UserStorageController.cjs.map +1 -1
  10. package/dist/controllers/user-storage/UserStorageController.d.cts +32 -15
  11. package/dist/controllers/user-storage/UserStorageController.d.cts.map +1 -1
  12. package/dist/controllers/user-storage/UserStorageController.d.mts +32 -15
  13. package/dist/controllers/user-storage/UserStorageController.d.mts.map +1 -1
  14. package/dist/controllers/user-storage/UserStorageController.mjs +56 -23
  15. package/dist/controllers/user-storage/UserStorageController.mjs.map +1 -1
  16. package/dist/controllers/user-storage/__fixtures__/mockMessenger.cjs +171 -0
  17. package/dist/controllers/user-storage/__fixtures__/mockMessenger.cjs.map +1 -0
  18. package/dist/controllers/user-storage/__fixtures__/mockMessenger.d.cts +102 -0
  19. package/dist/controllers/user-storage/__fixtures__/mockMessenger.d.cts.map +1 -0
  20. package/dist/controllers/user-storage/__fixtures__/mockMessenger.d.mts +102 -0
  21. package/dist/controllers/user-storage/__fixtures__/mockMessenger.d.mts.map +1 -0
  22. package/dist/controllers/user-storage/__fixtures__/mockMessenger.mjs +166 -0
  23. package/dist/controllers/user-storage/__fixtures__/mockMessenger.mjs.map +1 -0
  24. package/dist/controllers/user-storage/__fixtures__/mockResponses.cjs +7 -6
  25. package/dist/controllers/user-storage/__fixtures__/mockResponses.cjs.map +1 -1
  26. package/dist/controllers/user-storage/__fixtures__/mockResponses.d.cts.map +1 -1
  27. package/dist/controllers/user-storage/__fixtures__/mockResponses.d.mts.map +1 -1
  28. package/dist/controllers/user-storage/__fixtures__/mockResponses.mjs +7 -6
  29. package/dist/controllers/user-storage/__fixtures__/mockResponses.mjs.map +1 -1
  30. package/dist/controllers/user-storage/network-syncing/__fixtures__/mockNetwork.cjs +20 -2
  31. package/dist/controllers/user-storage/network-syncing/__fixtures__/mockNetwork.cjs.map +1 -1
  32. package/dist/controllers/user-storage/network-syncing/__fixtures__/mockNetwork.d.cts +8 -1
  33. package/dist/controllers/user-storage/network-syncing/__fixtures__/mockNetwork.d.cts.map +1 -1
  34. package/dist/controllers/user-storage/network-syncing/__fixtures__/mockNetwork.d.mts +8 -1
  35. package/dist/controllers/user-storage/network-syncing/__fixtures__/mockNetwork.d.mts.map +1 -1
  36. package/dist/controllers/user-storage/network-syncing/__fixtures__/mockNetwork.mjs +17 -1
  37. package/dist/controllers/user-storage/network-syncing/__fixtures__/mockNetwork.mjs.map +1 -1
  38. package/dist/controllers/user-storage/network-syncing/add-network-utils.cjs +35 -0
  39. package/dist/controllers/user-storage/network-syncing/add-network-utils.cjs.map +1 -0
  40. package/dist/controllers/user-storage/network-syncing/add-network-utils.d.cts +21 -0
  41. package/dist/controllers/user-storage/network-syncing/add-network-utils.d.cts.map +1 -0
  42. package/dist/controllers/user-storage/network-syncing/add-network-utils.d.mts +21 -0
  43. package/dist/controllers/user-storage/network-syncing/add-network-utils.d.mts.map +1 -0
  44. package/dist/controllers/user-storage/network-syncing/add-network-utils.mjs +30 -0
  45. package/dist/controllers/user-storage/network-syncing/add-network-utils.mjs.map +1 -0
  46. package/dist/controllers/user-storage/network-syncing/controller-integration.cjs +157 -29
  47. package/dist/controllers/user-storage/network-syncing/controller-integration.cjs.map +1 -1
  48. package/dist/controllers/user-storage/network-syncing/controller-integration.d.cts +45 -3
  49. package/dist/controllers/user-storage/network-syncing/controller-integration.d.cts.map +1 -1
  50. package/dist/controllers/user-storage/network-syncing/controller-integration.d.mts +45 -3
  51. package/dist/controllers/user-storage/network-syncing/controller-integration.d.mts.map +1 -1
  52. package/dist/controllers/user-storage/network-syncing/controller-integration.mjs +154 -28
  53. package/dist/controllers/user-storage/network-syncing/controller-integration.mjs.map +1 -1
  54. package/dist/controllers/user-storage/network-syncing/services.cjs +9 -4
  55. package/dist/controllers/user-storage/network-syncing/services.cjs.map +1 -1
  56. package/dist/controllers/user-storage/network-syncing/services.d.cts.map +1 -1
  57. package/dist/controllers/user-storage/network-syncing/services.d.mts.map +1 -1
  58. package/dist/controllers/user-storage/network-syncing/services.mjs +10 -5
  59. package/dist/controllers/user-storage/network-syncing/services.mjs.map +1 -1
  60. package/dist/controllers/user-storage/network-syncing/sync-all.cjs +10 -28
  61. package/dist/controllers/user-storage/network-syncing/sync-all.cjs.map +1 -1
  62. package/dist/controllers/user-storage/network-syncing/sync-all.d.cts +5 -8
  63. package/dist/controllers/user-storage/network-syncing/sync-all.d.cts.map +1 -1
  64. package/dist/controllers/user-storage/network-syncing/sync-all.d.mts +5 -8
  65. package/dist/controllers/user-storage/network-syncing/sync-all.d.mts.map +1 -1
  66. package/dist/controllers/user-storage/network-syncing/sync-all.mjs +9 -26
  67. package/dist/controllers/user-storage/network-syncing/sync-all.mjs.map +1 -1
  68. package/dist/controllers/user-storage/network-syncing/sync-mutations.cjs +1 -1
  69. package/dist/controllers/user-storage/network-syncing/sync-mutations.cjs.map +1 -1
  70. package/dist/controllers/user-storage/network-syncing/sync-mutations.d.cts +1 -1
  71. package/dist/controllers/user-storage/network-syncing/sync-mutations.d.cts.map +1 -1
  72. package/dist/controllers/user-storage/network-syncing/sync-mutations.d.mts +1 -1
  73. package/dist/controllers/user-storage/network-syncing/sync-mutations.d.mts.map +1 -1
  74. package/dist/controllers/user-storage/network-syncing/sync-mutations.mjs +1 -1
  75. package/dist/controllers/user-storage/network-syncing/sync-mutations.mjs.map +1 -1
  76. package/dist/controllers/user-storage/network-syncing/types.cjs.map +1 -1
  77. package/dist/controllers/user-storage/network-syncing/types.d.cts +1 -4
  78. package/dist/controllers/user-storage/network-syncing/types.d.cts.map +1 -1
  79. package/dist/controllers/user-storage/network-syncing/types.d.mts +1 -4
  80. package/dist/controllers/user-storage/network-syncing/types.d.mts.map +1 -1
  81. package/dist/controllers/user-storage/network-syncing/types.mjs.map +1 -1
  82. package/dist/controllers/user-storage/network-syncing/update-network-utils.cjs +126 -0
  83. package/dist/controllers/user-storage/network-syncing/update-network-utils.cjs.map +1 -0
  84. package/dist/controllers/user-storage/network-syncing/update-network-utils.d.cts +56 -0
  85. package/dist/controllers/user-storage/network-syncing/update-network-utils.d.cts.map +1 -0
  86. package/dist/controllers/user-storage/network-syncing/update-network-utils.d.mts +56 -0
  87. package/dist/controllers/user-storage/network-syncing/update-network-utils.d.mts.map +1 -0
  88. package/dist/controllers/user-storage/network-syncing/update-network-utils.mjs +119 -0
  89. package/dist/controllers/user-storage/network-syncing/update-network-utils.mjs.map +1 -0
  90. package/dist/controllers/user-storage/services.cjs +49 -1
  91. package/dist/controllers/user-storage/services.cjs.map +1 -1
  92. package/dist/controllers/user-storage/services.d.cts +8 -0
  93. package/dist/controllers/user-storage/services.d.cts.map +1 -1
  94. package/dist/controllers/user-storage/services.d.mts +8 -0
  95. package/dist/controllers/user-storage/services.d.mts.map +1 -1
  96. package/dist/controllers/user-storage/services.mjs +47 -0
  97. package/dist/controllers/user-storage/services.mjs.map +1 -1
  98. package/dist/sdk/__fixtures__/mock-userstorage.cjs +29 -6
  99. package/dist/sdk/__fixtures__/mock-userstorage.cjs.map +1 -1
  100. package/dist/sdk/__fixtures__/mock-userstorage.d.cts +4 -6
  101. package/dist/sdk/__fixtures__/mock-userstorage.d.cts.map +1 -1
  102. package/dist/sdk/__fixtures__/mock-userstorage.d.mts +4 -6
  103. package/dist/sdk/__fixtures__/mock-userstorage.d.mts.map +1 -1
  104. package/dist/sdk/__fixtures__/mock-userstorage.mjs +6 -6
  105. package/dist/sdk/__fixtures__/mock-userstorage.mjs.map +1 -1
  106. package/dist/sdk/authentication-jwt-bearer/flow-siwe.mjs +1 -2
  107. package/dist/sdk/authentication-jwt-bearer/flow-siwe.mjs.map +1 -1
  108. package/dist/sdk/user-storage.cjs +62 -9
  109. package/dist/sdk/user-storage.cjs.map +1 -1
  110. package/dist/sdk/user-storage.d.cts +5 -1
  111. package/dist/sdk/user-storage.d.cts.map +1 -1
  112. package/dist/sdk/user-storage.d.mts +5 -1
  113. package/dist/sdk/user-storage.d.mts.map +1 -1
  114. package/dist/sdk/user-storage.mjs +62 -9
  115. package/dist/sdk/user-storage.mjs.map +1 -1
  116. package/dist/shared/encryption/cache.cjs +12 -14
  117. package/dist/shared/encryption/cache.cjs.map +1 -1
  118. package/dist/shared/encryption/cache.d.cts +4 -3
  119. package/dist/shared/encryption/cache.d.cts.map +1 -1
  120. package/dist/shared/encryption/cache.d.mts +4 -3
  121. package/dist/shared/encryption/cache.d.mts.map +1 -1
  122. package/dist/shared/encryption/cache.mjs +11 -13
  123. package/dist/shared/encryption/cache.mjs.map +1 -1
  124. package/dist/shared/encryption/constants.cjs +18 -0
  125. package/dist/shared/encryption/constants.cjs.map +1 -0
  126. package/dist/shared/encryption/constants.d.cts +8 -0
  127. package/dist/shared/encryption/constants.d.cts.map +1 -0
  128. package/dist/shared/encryption/constants.d.mts +8 -0
  129. package/dist/shared/encryption/constants.d.mts.map +1 -0
  130. package/dist/shared/encryption/constants.mjs +15 -0
  131. package/dist/shared/encryption/constants.mjs.map +1 -0
  132. package/dist/shared/encryption/encryption.cjs +49 -25
  133. package/dist/shared/encryption/encryption.cjs.map +1 -1
  134. package/dist/shared/encryption/encryption.d.cts +2 -0
  135. package/dist/shared/encryption/encryption.d.cts.map +1 -1
  136. package/dist/shared/encryption/encryption.d.mts +2 -0
  137. package/dist/shared/encryption/encryption.d.mts.map +1 -1
  138. package/dist/shared/encryption/encryption.mjs +38 -14
  139. package/dist/shared/encryption/encryption.mjs.map +1 -1
  140. package/package.json +11 -6
@@ -1 +1 @@
1
- {"version":3,"file":"encryption.d.mts","sourceRoot":"","sources":["../../../src/shared/encryption/encryption.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,gCAA4B;AASxD,MAAM,MAAM,gBAAgB,GAAG;IAE7B,CAAC,EAAE,GAAG,CAAC;IAGP,CAAC,EAAE,QAAQ,CAAC;IAGZ,CAAC,EAAE,MAAM,CAAC;IAGV,CAAC,EAAE;QAED,CAAC,EAAE,MAAM,CAAC;QACV,CAAC,EAAE,MAAM,CAAC;QACV,CAAC,EAAE,MAAM,CAAC;QACV,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IAGF,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAeF,cAAM,kBAAkB;;IAChB,aAAa,CACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,kBAAkB,CAAC,EAAE,YAAY,GAChC,OAAO,CAAC,MAAM,CAAC;IAaZ,aAAa,CACjB,gBAAgB,EAAE,MAAM,EACxB,QAAQ,EAAE,MAAM,EAChB,kBAAkB,CAAC,EAAE,YAAY,GAChC,OAAO,CAAC,MAAM,CAAC;CAuKnB;AAED,QAAA,MAAM,UAAU,oBAA2B,CAAC;AAC5C,eAAe,UAAU,CAAC;AAE1B;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGrD"}
1
+ {"version":3,"file":"encryption.d.mts","sourceRoot":"","sources":["../../../src/shared/encryption/encryption.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,gCAA4B;AAsBxD,MAAM,MAAM,gBAAgB,GAAG;IAE7B,CAAC,EAAE,GAAG,CAAC;IAGP,CAAC,EAAE,QAAQ,CAAC;IAGZ,CAAC,EAAE,MAAM,CAAC;IAGV,CAAC,EAAE;QAED,CAAC,EAAE,MAAM,CAAC;QACV,CAAC,EAAE,MAAM,CAAC;QACV,CAAC,EAAE,MAAM,CAAC;QACV,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IAGF,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,cAAM,kBAAkB;;IAChB,aAAa,CACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,kBAAkB,CAAC,EAAE,YAAY,GAChC,OAAO,CAAC,MAAM,CAAC;IAaZ,aAAa,CACjB,gBAAgB,EAAE,MAAM,EACxB,QAAQ,EAAE,MAAM,EAChB,kBAAkB,CAAC,EAAE,YAAY,GAChC,OAAO,CAAC,MAAM,CAAC;IAoGlB,OAAO,CAAC,gBAAgB,EAAE,MAAM;IA0BhC,8BAA8B,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO;CAmF3D;AAED,QAAA,MAAM,UAAU,oBAA2B,CAAC;AAC5C,eAAe,UAAU,CAAC;AAE1B;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGrD"}
@@ -9,19 +9,9 @@ import { randomBytes } from "@noble/ciphers/webcrypto";
9
9
  import { scryptAsync } from "@noble/hashes/scrypt";
10
10
  import { sha256 } from "@noble/hashes/sha256";
11
11
  import { utf8ToBytes, concatBytes, bytesToHex } from "@noble/hashes/utils";
12
- import { getAnyCachedKey, getCachedKeyBySalt, setCachedKey } from "./cache.mjs";
12
+ import { getCachedKeyBySalt, getCachedKeyGeneratedWithSharedSalt, setCachedKey } from "./cache.mjs";
13
+ import { ALGORITHM_KEY_SIZE, ALGORITHM_NONCE_SIZE, SCRYPT_N, SCRYPT_p, SCRYPT_r, SCRYPT_SALT_SIZE, SHARED_SALT } from "./constants.mjs";
13
14
  import { base64ToByteArray, byteArrayToBase64, bytesToUtf8, stringToByteArray } from "./utils.mjs";
14
- // Nonce/Key Sizes
15
- const ALGORITHM_NONCE_SIZE = 12; // 12 bytes
16
- const ALGORITHM_KEY_SIZE = 16; // 16 bytes
17
- // Scrypt settings
18
- // see: https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#scrypt
19
- const SCRYPT_SALT_SIZE = 16; // 16 bytes
20
- const SCRYPT_N = 2 ** 17; // CPU/memory cost parameter (must be a power of 2, > 1)
21
- // eslint-disable-next-line @typescript-eslint/naming-convention
22
- const SCRYPT_r = 8; // Block size parameter
23
- // eslint-disable-next-line @typescript-eslint/naming-convention
24
- const SCRYPT_p = 1; // Parallelization parameter
25
15
  class EncryptorDecryptor {
26
16
  constructor() {
27
17
  _EncryptorDecryptor_instances.add(this);
@@ -50,6 +40,40 @@ class EncryptorDecryptor {
50
40
  throw new Error(`Unable to decrypt string - ${errorMessage}`);
51
41
  }
52
42
  }
43
+ getSalt(encryptedDataStr) {
44
+ try {
45
+ const encryptedData = JSON.parse(encryptedDataStr);
46
+ if (encryptedData.v === '1') {
47
+ if (encryptedData.t === 'scrypt') {
48
+ const { d: base64CiphertextAndNonceAndSalt, saltLen } = encryptedData;
49
+ // Decode the base64.
50
+ const ciphertextAndNonceAndSalt = base64ToByteArray(base64CiphertextAndNonceAndSalt);
51
+ // Create buffers of salt and ciphertextAndNonce.
52
+ const salt = ciphertextAndNonceAndSalt.slice(0, saltLen);
53
+ return salt;
54
+ }
55
+ }
56
+ throw new Error(`Unsupported encrypted data payload - ${encryptedDataStr}`);
57
+ }
58
+ catch (e) {
59
+ const errorMessage = e instanceof Error ? e.message : JSON.stringify(e);
60
+ throw new Error(`Unable to get salt - ${errorMessage}`);
61
+ }
62
+ }
63
+ getIfEntriesHaveDifferentSalts(entries) {
64
+ const salts = entries
65
+ .map((e) => {
66
+ try {
67
+ return this.getSalt(e);
68
+ }
69
+ catch {
70
+ return undefined;
71
+ }
72
+ })
73
+ .filter((s) => s !== undefined);
74
+ const strSet = new Set(salts.map((arr) => arr.toString()));
75
+ return strSet.size === salts.length;
76
+ }
53
77
  }
54
78
  _EncryptorDecryptor_instances = new WeakSet(), _EncryptorDecryptor_encryptStringV1 = async function _EncryptorDecryptor_encryptStringV1(plaintext, password, nativeScryptCrypto) {
55
79
  const { key, salt } = await __classPrivateFieldGet(this, _EncryptorDecryptor_instances, "m", _EncryptorDecryptor_getOrGenerateScryptKey).call(this, password, {
@@ -107,14 +131,14 @@ _EncryptorDecryptor_instances = new WeakSet(), _EncryptorDecryptor_encryptString
107
131
  const hashedPassword = createSHA256Hash(password);
108
132
  const cachedKey = salt
109
133
  ? getCachedKeyBySalt(hashedPassword, salt)
110
- : getAnyCachedKey(hashedPassword);
134
+ : getCachedKeyGeneratedWithSharedSalt(hashedPassword);
111
135
  if (cachedKey) {
112
136
  return {
113
137
  key: cachedKey.key,
114
138
  salt: cachedKey.salt,
115
139
  };
116
140
  }
117
- const newSalt = salt ?? randomBytes(SCRYPT_SALT_SIZE);
141
+ const newSalt = salt ?? SHARED_SALT;
118
142
  let newKey;
119
143
  if (nativeScryptCrypto) {
120
144
  newKey = await nativeScryptCrypto(stringToByteArray(password), newSalt, o.N, o.r, o.p, o.dkLen);
@@ -1 +1 @@
1
- {"version":3,"file":"encryption.mjs","sourceRoot":"","sources":["../../../src/shared/encryption/encryption.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,GAAG,EAAE,2BAA2B;AACzC,OAAO,EAAE,WAAW,EAAE,iCAAiC;AACvD,OAAO,EAAE,WAAW,EAAE,6BAA6B;AACnD,OAAO,EAAE,MAAM,EAAE,6BAA6B;AAC9C,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,4BAA4B;AAG3E,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,YAAY,EAAE,oBAAgB;AAC5E,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,WAAW,EACX,iBAAiB,EAClB,oBAAgB;AAyBjB,kBAAkB;AAClB,MAAM,oBAAoB,GAAG,EAAE,CAAC,CAAC,WAAW;AAC5C,MAAM,kBAAkB,GAAG,EAAE,CAAC,CAAC,WAAW;AAE1C,kBAAkB;AAClB,+FAA+F;AAC/F,MAAM,gBAAgB,GAAG,EAAE,CAAC,CAAC,WAAW;AACxC,MAAM,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,wDAAwD;AAClF,gEAAgE;AAChE,MAAM,QAAQ,GAAG,CAAC,CAAC,CAAC,uBAAuB;AAC3C,gEAAgE;AAChE,MAAM,QAAQ,GAAG,CAAC,CAAC,CAAC,4BAA4B;AAEhD,MAAM,kBAAkB;IAAxB;;IA6LA,CAAC;IA5LC,KAAK,CAAC,aAAa,CACjB,SAAiB,EACjB,QAAgB,EAChB,kBAAiC;QAEjC,IAAI;YACF,OAAO,MAAM,uBAAA,IAAI,0EAAiB,MAArB,IAAI,EACf,SAAS,EACT,QAAQ,EACR,kBAAkB,CACnB,CAAC;SACH;QAAC,OAAO,CAAC,EAAE;YACV,MAAM,YAAY,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YACxE,MAAM,IAAI,KAAK,CAAC,8BAA8B,YAAY,EAAE,CAAC,CAAC;SAC/D;IACH,CAAC;IAED,KAAK,CAAC,aAAa,CACjB,gBAAwB,EACxB,QAAgB,EAChB,kBAAiC;QAEjC,IAAI;YACF,MAAM,aAAa,GAAqB,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;YACrE,IAAI,aAAa,CAAC,CAAC,KAAK,GAAG,EAAE;gBAC3B,IAAI,aAAa,CAAC,CAAC,KAAK,QAAQ,EAAE;oBAChC,OAAO,MAAM,uBAAA,IAAI,0EAAiB,MAArB,IAAI,EACf,aAAa,EACb,QAAQ,EACR,kBAAkB,CACnB,CAAC;iBACH;aACF;YACD,MAAM,IAAI,KAAK,CACb,wCAAwC,gBAAgB,EAAE,CAC3D,CAAC;SACH;QAAC,OAAO,CAAC,EAAE;YACV,MAAM,YAAY,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YACxE,MAAM,IAAI,KAAK,CAAC,8BAA8B,YAAY,EAAE,CAAC,CAAC;SAC/D;IACH,CAAC;CAoJF;qFAlJC,KAAK,8CACH,SAAiB,EACjB,QAAgB,EAChB,kBAAiC;IAEjC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,MAAM,uBAAA,IAAI,iFAAwB,MAA5B,IAAI,EAC9B,QAAQ,EACR;QACE,CAAC,EAAE,QAAQ;QACX,CAAC,EAAE,QAAQ;QACX,CAAC,EAAE,QAAQ;QACX,KAAK,EAAE,kBAAkB;KAC1B,EACD,SAAS,EACT,kBAAkB,CACnB,CAAC;IAEF,4BAA4B;IAC5B,MAAM,YAAY,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC;IAC5C,MAAM,yBAAyB,GAAG,WAAW,CAC3C,IAAI,EACJ,uBAAA,IAAI,kEAAS,MAAb,IAAI,EAAU,YAAY,EAAE,GAAG,CAAC,CACjC,CAAC;IAEF,oBAAoB;IACpB,MAAM,aAAa,GAAG,iBAAiB,CAAC,yBAAyB,CAAC,CAAC;IAEnE,MAAM,gBAAgB,GAAqB;QACzC,CAAC,EAAE,GAAG;QACN,CAAC,EAAE,QAAQ;QACX,CAAC,EAAE,aAAa;QAChB,CAAC,EAAE;YACD,CAAC,EAAE,QAAQ;YACX,CAAC,EAAE,QAAQ;YACX,CAAC,EAAE,QAAQ;YACX,KAAK,EAAE,kBAAkB;SAC1B;QACD,OAAO,EAAE,gBAAgB;KAC1B,CAAC;IAEF,OAAO,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;AAC1C,CAAC,wCAED,KAAK,8CACH,IAAsB,EACtB,QAAgB,EAChB,kBAAiC;IAEjC,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,+BAA+B,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAEhE,qBAAqB;IACrB,MAAM,yBAAyB,GAAG,iBAAiB,CACjD,+BAA+B,CAChC,CAAC;IAEF,iDAAiD;IACjD,MAAM,IAAI,GAAG,yBAAyB,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACzD,MAAM,kBAAkB,GAAG,yBAAyB,CAAC,KAAK,CACxD,OAAO,EACP,yBAAyB,CAAC,MAAM,CACjC,CAAC;IAEF,kBAAkB;IAClB,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,uBAAA,IAAI,iFAAwB,MAA5B,IAAI,EACxB,QAAQ,EACR;QACE,CAAC,EAAE,CAAC,CAAC,CAAC;QACN,CAAC,EAAE,CAAC,CAAC,CAAC;QACN,CAAC,EAAE,CAAC,CAAC,CAAC;QACN,KAAK,EAAE,CAAC,CAAC,KAAK;KACf,EACD,IAAI,EACJ,kBAAkB,CACnB,CAAC;IAEF,6BAA6B;IAC7B,OAAO,WAAW,CAAC,uBAAA,IAAI,kEAAS,MAAb,IAAI,EAAU,kBAAkB,EAAE,GAAG,CAAC,CAAC,CAAC;AAC7D,CAAC,qEAEQ,SAAqB,EAAE,GAAe;IAC7C,MAAM,KAAK,GAAG,WAAW,CAAC,oBAAoB,CAAC,CAAC;IAEhD,6BAA6B;IAC7B,MAAM,UAAU,GAAG,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEtD,OAAO,WAAW,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;AACxC,CAAC,qEAEQ,kBAA8B,EAAE,GAAe;IACtD,0CAA0C;IAC1C,MAAM,KAAK,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC,EAAE,oBAAoB,CAAC,CAAC;IAChE,MAAM,UAAU,GAAG,kBAAkB,CAAC,KAAK,CACzC,oBAAoB,EACpB,kBAAkB,CAAC,MAAM,CAC1B,CAAC;IAEF,6BAA6B;IAC7B,OAAO,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAC7C,CAAC,+CAED,KAAK,qDACH,QAAgB,EAChB,CAAwB,EACxB,IAAiB,EACjB,kBAAiC;IAEjC,MAAM,cAAc,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAClD,MAAM,SAAS,GAAG,IAAI;QACpB,CAAC,CAAC,kBAAkB,CAAC,cAAc,EAAE,IAAI,CAAC;QAC1C,CAAC,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC;IAEpC,IAAI,SAAS,EAAE;QACb,OAAO;YACL,GAAG,EAAE,SAAS,CAAC,GAAG;YAClB,IAAI,EAAE,SAAS,CAAC,IAAI;SACrB,CAAC;KACH;IAED,MAAM,OAAO,GAAG,IAAI,IAAI,WAAW,CAAC,gBAAgB,CAAC,CAAC;IAEtD,IAAI,MAAkB,CAAC;IAEvB,IAAI,kBAAkB,EAAE;QACtB,MAAM,GAAG,MAAM,kBAAkB,CAC/B,iBAAiB,CAAC,QAAQ,CAAC,EAC3B,OAAO,EACP,CAAC,CAAC,CAAC,EACH,CAAC,CAAC,CAAC,EACH,CAAC,CAAC,CAAC,EACH,CAAC,CAAC,KAAK,CACR,CAAC;KACH;SAAM;QACL,MAAM,GAAG,MAAM,WAAW,CAAC,QAAQ,EAAE,OAAO,EAAE;YAC5C,CAAC,EAAE,CAAC,CAAC,CAAC;YACN,CAAC,EAAE,CAAC,CAAC,CAAC;YACN,CAAC,EAAE,CAAC,CAAC,CAAC;YACN,KAAK,EAAE,CAAC,CAAC,KAAK;SACf,CAAC,CAAC;KACJ;IACD,YAAY,CAAC,cAAc,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAE9C,OAAO;QACL,GAAG,EAAE,MAAM;QACX,IAAI,EAAE,OAAO;KACd,CAAC;AACJ,CAAC;AAGH,MAAM,UAAU,GAAG,IAAI,kBAAkB,EAAE,CAAC;AAC5C,eAAe,UAAU,CAAC;AAE1B;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAChC,OAAO,UAAU,CAAC,UAAU,CAAC,CAAC;AAChC,CAAC","sourcesContent":["import { gcm } from '@noble/ciphers/aes';\nimport { randomBytes } from '@noble/ciphers/webcrypto';\nimport { scryptAsync } from '@noble/hashes/scrypt';\nimport { sha256 } from '@noble/hashes/sha256';\nimport { utf8ToBytes, concatBytes, bytesToHex } from '@noble/hashes/utils';\n\nimport type { NativeScrypt } from '../types/encryption';\nimport { getAnyCachedKey, getCachedKeyBySalt, setCachedKey } from './cache';\nimport {\n base64ToByteArray,\n byteArrayToBase64,\n bytesToUtf8,\n stringToByteArray,\n} from './utils';\n\nexport type EncryptedPayload = {\n // version\n v: '1';\n\n // key derivation function algorithm - scrypt\n t: 'scrypt';\n\n // data\n d: string;\n\n // encryption options - scrypt\n o: {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n N: number;\n r: number;\n p: number;\n dkLen: number;\n };\n\n // Salt options\n saltLen: number;\n};\n\n// Nonce/Key Sizes\nconst ALGORITHM_NONCE_SIZE = 12; // 12 bytes\nconst ALGORITHM_KEY_SIZE = 16; // 16 bytes\n\n// Scrypt settings\n// see: https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#scrypt\nconst SCRYPT_SALT_SIZE = 16; // 16 bytes\nconst SCRYPT_N = 2 ** 17; // CPU/memory cost parameter (must be a power of 2, > 1)\n// eslint-disable-next-line @typescript-eslint/naming-convention\nconst SCRYPT_r = 8; // Block size parameter\n// eslint-disable-next-line @typescript-eslint/naming-convention\nconst SCRYPT_p = 1; // Parallelization parameter\n\nclass EncryptorDecryptor {\n async encryptString(\n plaintext: string,\n password: string,\n nativeScryptCrypto?: NativeScrypt,\n ): Promise<string> {\n try {\n return await this.#encryptStringV1(\n plaintext,\n password,\n nativeScryptCrypto,\n );\n } catch (e) {\n const errorMessage = e instanceof Error ? e.message : JSON.stringify(e);\n throw new Error(`Unable to encrypt string - ${errorMessage}`);\n }\n }\n\n async decryptString(\n encryptedDataStr: string,\n password: string,\n nativeScryptCrypto?: NativeScrypt,\n ): Promise<string> {\n try {\n const encryptedData: EncryptedPayload = JSON.parse(encryptedDataStr);\n if (encryptedData.v === '1') {\n if (encryptedData.t === 'scrypt') {\n return await this.#decryptStringV1(\n encryptedData,\n password,\n nativeScryptCrypto,\n );\n }\n }\n throw new Error(\n `Unsupported encrypted data payload - ${encryptedDataStr}`,\n );\n } catch (e) {\n const errorMessage = e instanceof Error ? e.message : JSON.stringify(e);\n throw new Error(`Unable to decrypt string - ${errorMessage}`);\n }\n }\n\n async #encryptStringV1(\n plaintext: string,\n password: string,\n nativeScryptCrypto?: NativeScrypt,\n ): Promise<string> {\n const { key, salt } = await this.#getOrGenerateScryptKey(\n password,\n {\n N: SCRYPT_N,\n r: SCRYPT_r,\n p: SCRYPT_p,\n dkLen: ALGORITHM_KEY_SIZE,\n },\n undefined,\n nativeScryptCrypto,\n );\n\n // Encrypt and prepend salt.\n const plaintextRaw = utf8ToBytes(plaintext);\n const ciphertextAndNonceAndSalt = concatBytes(\n salt,\n this.#encrypt(plaintextRaw, key),\n );\n\n // Convert to Base64\n const encryptedData = byteArrayToBase64(ciphertextAndNonceAndSalt);\n\n const encryptedPayload: EncryptedPayload = {\n v: '1',\n t: 'scrypt',\n d: encryptedData,\n o: {\n N: SCRYPT_N,\n r: SCRYPT_r,\n p: SCRYPT_p,\n dkLen: ALGORITHM_KEY_SIZE,\n },\n saltLen: SCRYPT_SALT_SIZE,\n };\n\n return JSON.stringify(encryptedPayload);\n }\n\n async #decryptStringV1(\n data: EncryptedPayload,\n password: string,\n nativeScryptCrypto?: NativeScrypt,\n ): Promise<string> {\n const { o, d: base64CiphertextAndNonceAndSalt, saltLen } = data;\n\n // Decode the base64.\n const ciphertextAndNonceAndSalt = base64ToByteArray(\n base64CiphertextAndNonceAndSalt,\n );\n\n // Create buffers of salt and ciphertextAndNonce.\n const salt = ciphertextAndNonceAndSalt.slice(0, saltLen);\n const ciphertextAndNonce = ciphertextAndNonceAndSalt.slice(\n saltLen,\n ciphertextAndNonceAndSalt.length,\n );\n\n // Derive the key.\n const { key } = await this.#getOrGenerateScryptKey(\n password,\n {\n N: o.N,\n r: o.r,\n p: o.p,\n dkLen: o.dkLen,\n },\n salt,\n nativeScryptCrypto,\n );\n\n // Decrypt and return result.\n return bytesToUtf8(this.#decrypt(ciphertextAndNonce, key));\n }\n\n #encrypt(plaintext: Uint8Array, key: Uint8Array): Uint8Array {\n const nonce = randomBytes(ALGORITHM_NONCE_SIZE);\n\n // Encrypt and prepend nonce.\n const ciphertext = gcm(key, nonce).encrypt(plaintext);\n\n return concatBytes(nonce, ciphertext);\n }\n\n #decrypt(ciphertextAndNonce: Uint8Array, key: Uint8Array): Uint8Array {\n // Create buffers of nonce and ciphertext.\n const nonce = ciphertextAndNonce.slice(0, ALGORITHM_NONCE_SIZE);\n const ciphertext = ciphertextAndNonce.slice(\n ALGORITHM_NONCE_SIZE,\n ciphertextAndNonce.length,\n );\n\n // Decrypt and return result.\n return gcm(key, nonce).decrypt(ciphertext);\n }\n\n async #getOrGenerateScryptKey(\n password: string,\n o: EncryptedPayload['o'],\n salt?: Uint8Array,\n nativeScryptCrypto?: NativeScrypt,\n ) {\n const hashedPassword = createSHA256Hash(password);\n const cachedKey = salt\n ? getCachedKeyBySalt(hashedPassword, salt)\n : getAnyCachedKey(hashedPassword);\n\n if (cachedKey) {\n return {\n key: cachedKey.key,\n salt: cachedKey.salt,\n };\n }\n\n const newSalt = salt ?? randomBytes(SCRYPT_SALT_SIZE);\n\n let newKey: Uint8Array;\n\n if (nativeScryptCrypto) {\n newKey = await nativeScryptCrypto(\n stringToByteArray(password),\n newSalt,\n o.N,\n o.r,\n o.p,\n o.dkLen,\n );\n } else {\n newKey = await scryptAsync(password, newSalt, {\n N: o.N,\n r: o.r,\n p: o.p,\n dkLen: o.dkLen,\n });\n }\n setCachedKey(hashedPassword, newSalt, newKey);\n\n return {\n key: newKey,\n salt: newSalt,\n };\n }\n}\n\nconst encryption = new EncryptorDecryptor();\nexport default encryption;\n\n/**\n * Receive a SHA256 hash from a given string\n * @param data - input\n * @returns sha256 hash\n */\nexport function createSHA256Hash(data: string): string {\n const hashedData = sha256(data);\n return bytesToHex(hashedData);\n}\n"]}
1
+ {"version":3,"file":"encryption.mjs","sourceRoot":"","sources":["../../../src/shared/encryption/encryption.ts"],"names":[],"mappings":"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","sourcesContent":["import { gcm } from '@noble/ciphers/aes';\nimport { randomBytes } from '@noble/ciphers/webcrypto';\nimport { scryptAsync } from '@noble/hashes/scrypt';\nimport { sha256 } from '@noble/hashes/sha256';\nimport { utf8ToBytes, concatBytes, bytesToHex } from '@noble/hashes/utils';\n\nimport type { NativeScrypt } from '../types/encryption';\nimport {\n getCachedKeyBySalt,\n getCachedKeyGeneratedWithSharedSalt,\n setCachedKey,\n} from './cache';\nimport {\n ALGORITHM_KEY_SIZE,\n ALGORITHM_NONCE_SIZE,\n SCRYPT_N,\n SCRYPT_p,\n SCRYPT_r,\n SCRYPT_SALT_SIZE,\n SHARED_SALT,\n} from './constants';\nimport {\n base64ToByteArray,\n byteArrayToBase64,\n bytesToUtf8,\n stringToByteArray,\n} from './utils';\n\nexport type EncryptedPayload = {\n // version\n v: '1';\n\n // key derivation function algorithm - scrypt\n t: 'scrypt';\n\n // data\n d: string;\n\n // encryption options - scrypt\n o: {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n N: number;\n r: number;\n p: number;\n dkLen: number;\n };\n\n // Salt options\n saltLen: number;\n};\n\nclass EncryptorDecryptor {\n async encryptString(\n plaintext: string,\n password: string,\n nativeScryptCrypto?: NativeScrypt,\n ): Promise<string> {\n try {\n return await this.#encryptStringV1(\n plaintext,\n password,\n nativeScryptCrypto,\n );\n } catch (e) {\n const errorMessage = e instanceof Error ? e.message : JSON.stringify(e);\n throw new Error(`Unable to encrypt string - ${errorMessage}`);\n }\n }\n\n async decryptString(\n encryptedDataStr: string,\n password: string,\n nativeScryptCrypto?: NativeScrypt,\n ): Promise<string> {\n try {\n const encryptedData: EncryptedPayload = JSON.parse(encryptedDataStr);\n if (encryptedData.v === '1') {\n if (encryptedData.t === 'scrypt') {\n return await this.#decryptStringV1(\n encryptedData,\n password,\n nativeScryptCrypto,\n );\n }\n }\n throw new Error(\n `Unsupported encrypted data payload - ${encryptedDataStr}`,\n );\n } catch (e) {\n const errorMessage = e instanceof Error ? e.message : JSON.stringify(e);\n throw new Error(`Unable to decrypt string - ${errorMessage}`);\n }\n }\n\n async #encryptStringV1(\n plaintext: string,\n password: string,\n nativeScryptCrypto?: NativeScrypt,\n ): Promise<string> {\n const { key, salt } = await this.#getOrGenerateScryptKey(\n password,\n {\n N: SCRYPT_N,\n r: SCRYPT_r,\n p: SCRYPT_p,\n dkLen: ALGORITHM_KEY_SIZE,\n },\n undefined,\n nativeScryptCrypto,\n );\n\n // Encrypt and prepend salt.\n const plaintextRaw = utf8ToBytes(plaintext);\n const ciphertextAndNonceAndSalt = concatBytes(\n salt,\n this.#encrypt(plaintextRaw, key),\n );\n\n // Convert to Base64\n const encryptedData = byteArrayToBase64(ciphertextAndNonceAndSalt);\n\n const encryptedPayload: EncryptedPayload = {\n v: '1',\n t: 'scrypt',\n d: encryptedData,\n o: {\n N: SCRYPT_N,\n r: SCRYPT_r,\n p: SCRYPT_p,\n dkLen: ALGORITHM_KEY_SIZE,\n },\n saltLen: SCRYPT_SALT_SIZE,\n };\n\n return JSON.stringify(encryptedPayload);\n }\n\n async #decryptStringV1(\n data: EncryptedPayload,\n password: string,\n nativeScryptCrypto?: NativeScrypt,\n ): Promise<string> {\n const { o, d: base64CiphertextAndNonceAndSalt, saltLen } = data;\n\n // Decode the base64.\n const ciphertextAndNonceAndSalt = base64ToByteArray(\n base64CiphertextAndNonceAndSalt,\n );\n\n // Create buffers of salt and ciphertextAndNonce.\n const salt = ciphertextAndNonceAndSalt.slice(0, saltLen);\n const ciphertextAndNonce = ciphertextAndNonceAndSalt.slice(\n saltLen,\n ciphertextAndNonceAndSalt.length,\n );\n\n // Derive the key.\n const { key } = await this.#getOrGenerateScryptKey(\n password,\n {\n N: o.N,\n r: o.r,\n p: o.p,\n dkLen: o.dkLen,\n },\n salt,\n nativeScryptCrypto,\n );\n\n // Decrypt and return result.\n return bytesToUtf8(this.#decrypt(ciphertextAndNonce, key));\n }\n\n getSalt(encryptedDataStr: string) {\n try {\n const encryptedData: EncryptedPayload = JSON.parse(encryptedDataStr);\n if (encryptedData.v === '1') {\n if (encryptedData.t === 'scrypt') {\n const { d: base64CiphertextAndNonceAndSalt, saltLen } = encryptedData;\n\n // Decode the base64.\n const ciphertextAndNonceAndSalt = base64ToByteArray(\n base64CiphertextAndNonceAndSalt,\n );\n\n // Create buffers of salt and ciphertextAndNonce.\n const salt = ciphertextAndNonceAndSalt.slice(0, saltLen);\n return salt;\n }\n }\n throw new Error(\n `Unsupported encrypted data payload - ${encryptedDataStr}`,\n );\n } catch (e) {\n const errorMessage = e instanceof Error ? e.message : JSON.stringify(e);\n throw new Error(`Unable to get salt - ${errorMessage}`);\n }\n }\n\n getIfEntriesHaveDifferentSalts(entries: string[]): boolean {\n const salts = entries\n .map((e) => {\n try {\n return this.getSalt(e);\n } catch {\n return undefined;\n }\n })\n .filter((s): s is Uint8Array => s !== undefined);\n\n const strSet = new Set(salts.map((arr) => arr.toString()));\n return strSet.size === salts.length;\n }\n\n #encrypt(plaintext: Uint8Array, key: Uint8Array): Uint8Array {\n const nonce = randomBytes(ALGORITHM_NONCE_SIZE);\n\n // Encrypt and prepend nonce.\n const ciphertext = gcm(key, nonce).encrypt(plaintext);\n\n return concatBytes(nonce, ciphertext);\n }\n\n #decrypt(ciphertextAndNonce: Uint8Array, key: Uint8Array): Uint8Array {\n // Create buffers of nonce and ciphertext.\n const nonce = ciphertextAndNonce.slice(0, ALGORITHM_NONCE_SIZE);\n const ciphertext = ciphertextAndNonce.slice(\n ALGORITHM_NONCE_SIZE,\n ciphertextAndNonce.length,\n );\n\n // Decrypt and return result.\n return gcm(key, nonce).decrypt(ciphertext);\n }\n\n async #getOrGenerateScryptKey(\n password: string,\n o: EncryptedPayload['o'],\n salt?: Uint8Array,\n nativeScryptCrypto?: NativeScrypt,\n ) {\n const hashedPassword = createSHA256Hash(password);\n const cachedKey = salt\n ? getCachedKeyBySalt(hashedPassword, salt)\n : getCachedKeyGeneratedWithSharedSalt(hashedPassword);\n\n if (cachedKey) {\n return {\n key: cachedKey.key,\n salt: cachedKey.salt,\n };\n }\n\n const newSalt = salt ?? SHARED_SALT;\n\n let newKey: Uint8Array;\n\n if (nativeScryptCrypto) {\n newKey = await nativeScryptCrypto(\n stringToByteArray(password),\n newSalt,\n o.N,\n o.r,\n o.p,\n o.dkLen,\n );\n } else {\n newKey = await scryptAsync(password, newSalt, {\n N: o.N,\n r: o.r,\n p: o.p,\n dkLen: o.dkLen,\n });\n }\n\n setCachedKey(hashedPassword, newSalt, newKey);\n\n return {\n key: newKey,\n salt: newSalt,\n };\n }\n}\n\nconst encryption = new EncryptorDecryptor();\nexport default encryption;\n\n/**\n * Receive a SHA256 hash from a given string\n * @param data - input\n * @returns sha256 hash\n */\nexport function createSHA256Hash(data: string): string {\n const hashedData = sha256(data);\n return bytesToHex(hashedData);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask/profile-sync-controller",
3
- "version": "2.0.0",
3
+ "version": "3.1.0",
4
4
  "description": "The profile sync helps developers synchronize data across multiple clients and devices in a privacy-preserving way. All data saved in the user storage database is encrypted client-side to preserve privacy. The user storage provides a modular design, giving developers the flexibility to construct and manage their storage spaces in a way that best suits their needs",
5
5
  "keywords": [
6
6
  "MetaMask",
@@ -102,8 +102,8 @@
102
102
  "dependencies": {
103
103
  "@metamask/base-controller": "^7.0.2",
104
104
  "@metamask/keyring-api": "^10.1.0",
105
- "@metamask/keyring-controller": "^19.0.0",
106
- "@metamask/network-controller": "^22.0.2",
105
+ "@metamask/keyring-controller": "^19.0.1",
106
+ "@metamask/network-controller": "^22.1.1",
107
107
  "@metamask/snaps-sdk": "^6.7.0",
108
108
  "@metamask/snaps-utils": "^8.3.0",
109
109
  "@noble/ciphers": "^0.5.2",
@@ -114,8 +114,10 @@
114
114
  },
115
115
  "devDependencies": {
116
116
  "@lavamoat/allow-scripts": "^3.0.4",
117
- "@metamask/accounts-controller": "^20.0.0",
117
+ "@lavamoat/preinstall-always-fail": "^2.1.0",
118
+ "@metamask/accounts-controller": "^20.0.1",
118
119
  "@metamask/auto-changelog": "^3.4.4",
120
+ "@metamask/providers": "^18.1.1",
119
121
  "@metamask/snaps-controllers": "^9.10.0",
120
122
  "@types/jest": "^27.4.1",
121
123
  "deepmerge": "^4.2.2",
@@ -126,13 +128,16 @@
126
128
  "ts-jest": "^27.1.4",
127
129
  "typedoc": "^0.24.8",
128
130
  "typedoc-plugin-missing-exports": "^2.0.0",
129
- "typescript": "~5.2.2"
131
+ "typescript": "~5.2.2",
132
+ "webextension-polyfill": "^0.12.0"
130
133
  },
131
134
  "peerDependencies": {
132
135
  "@metamask/accounts-controller": "^20.0.0",
133
136
  "@metamask/keyring-controller": "^19.0.0",
134
137
  "@metamask/network-controller": "^22.0.0",
135
- "@metamask/snaps-controllers": "^9.10.0"
138
+ "@metamask/providers": "^18.1.0",
139
+ "@metamask/snaps-controllers": "^9.10.0",
140
+ "webextension-polyfill": "^0.10.0 || ^0.11.0 || ^0.12.0"
136
141
  },
137
142
  "engines": {
138
143
  "node": "^18.18 || >=20"