@metamask-previews/profile-sync-controller 28.3.0-preview-ec4680201 → 28.3.0-preview-40d5fb1e2

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 (159) hide show
  1. package/dist/controllers/authentication/AuthenticationController-method-action-types.cjs.map +1 -1
  2. package/dist/controllers/authentication/AuthenticationController-method-action-types.d.cts.map +1 -1
  3. package/dist/controllers/authentication/AuthenticationController-method-action-types.d.mts.map +1 -1
  4. package/dist/controllers/authentication/AuthenticationController-method-action-types.mjs.map +1 -1
  5. package/dist/controllers/authentication/AuthenticationController.cjs +9 -9
  6. package/dist/controllers/authentication/AuthenticationController.cjs.map +1 -1
  7. package/dist/controllers/authentication/AuthenticationController.d.cts.map +1 -1
  8. package/dist/controllers/authentication/AuthenticationController.d.mts.map +1 -1
  9. package/dist/controllers/authentication/AuthenticationController.mjs.map +1 -1
  10. package/dist/controllers/authentication/index.cjs +3 -3
  11. package/dist/controllers/authentication/index.cjs.map +1 -1
  12. package/dist/controllers/authentication/index.d.cts.map +1 -1
  13. package/dist/controllers/authentication/index.d.mts.map +1 -1
  14. package/dist/controllers/authentication/index.mjs.map +1 -1
  15. package/dist/controllers/authentication/mocks/index.cjs.map +1 -1
  16. package/dist/controllers/authentication/mocks/index.d.cts.map +1 -1
  17. package/dist/controllers/authentication/mocks/index.d.mts.map +1 -1
  18. package/dist/controllers/authentication/mocks/index.mjs.map +1 -1
  19. package/dist/controllers/authentication/mocks/mockResponses.cjs +12 -12
  20. package/dist/controllers/authentication/mocks/mockResponses.cjs.map +1 -1
  21. package/dist/controllers/authentication/mocks/mockResponses.mjs.map +1 -1
  22. package/dist/controllers/index.cjs.map +1 -1
  23. package/dist/controllers/index.d.cts.map +1 -1
  24. package/dist/controllers/index.d.mts.map +1 -1
  25. package/dist/controllers/index.mjs.map +1 -1
  26. package/dist/controllers/user-storage/UserStorageController-method-action-types.cjs.map +1 -1
  27. package/dist/controllers/user-storage/UserStorageController-method-action-types.d.cts.map +1 -1
  28. package/dist/controllers/user-storage/UserStorageController-method-action-types.d.mts.map +1 -1
  29. package/dist/controllers/user-storage/UserStorageController-method-action-types.mjs.map +1 -1
  30. package/dist/controllers/user-storage/UserStorageController.cjs +15 -15
  31. package/dist/controllers/user-storage/UserStorageController.cjs.map +1 -1
  32. package/dist/controllers/user-storage/UserStorageController.d.cts.map +1 -1
  33. package/dist/controllers/user-storage/UserStorageController.d.mts.map +1 -1
  34. package/dist/controllers/user-storage/UserStorageController.mjs.map +1 -1
  35. package/dist/controllers/user-storage/contact-syncing/controller-integration.cjs +23 -23
  36. package/dist/controllers/user-storage/contact-syncing/controller-integration.cjs.map +1 -1
  37. package/dist/controllers/user-storage/contact-syncing/controller-integration.d.cts.map +1 -1
  38. package/dist/controllers/user-storage/contact-syncing/controller-integration.d.mts.map +1 -1
  39. package/dist/controllers/user-storage/contact-syncing/controller-integration.mjs.map +1 -1
  40. package/dist/controllers/user-storage/contact-syncing/setup-subscriptions.cjs +9 -9
  41. package/dist/controllers/user-storage/contact-syncing/setup-subscriptions.cjs.map +1 -1
  42. package/dist/controllers/user-storage/contact-syncing/setup-subscriptions.d.cts.map +1 -1
  43. package/dist/controllers/user-storage/contact-syncing/setup-subscriptions.d.mts.map +1 -1
  44. package/dist/controllers/user-storage/contact-syncing/setup-subscriptions.mjs.map +1 -1
  45. package/dist/controllers/user-storage/contact-syncing/sync-utils.cjs.map +1 -1
  46. package/dist/controllers/user-storage/contact-syncing/sync-utils.d.cts.map +1 -1
  47. package/dist/controllers/user-storage/contact-syncing/sync-utils.d.mts.map +1 -1
  48. package/dist/controllers/user-storage/contact-syncing/sync-utils.mjs.map +1 -1
  49. package/dist/controllers/user-storage/contact-syncing/types.cjs.map +1 -1
  50. package/dist/controllers/user-storage/contact-syncing/types.d.cts.map +1 -1
  51. package/dist/controllers/user-storage/contact-syncing/types.d.mts.map +1 -1
  52. package/dist/controllers/user-storage/contact-syncing/types.mjs.map +1 -1
  53. package/dist/controllers/user-storage/contact-syncing/utils.cjs +2 -2
  54. package/dist/controllers/user-storage/contact-syncing/utils.cjs.map +1 -1
  55. package/dist/controllers/user-storage/contact-syncing/utils.d.cts.map +1 -1
  56. package/dist/controllers/user-storage/contact-syncing/utils.d.mts.map +1 -1
  57. package/dist/controllers/user-storage/contact-syncing/utils.mjs.map +1 -1
  58. package/dist/controllers/user-storage/index.cjs +3 -3
  59. package/dist/controllers/user-storage/index.cjs.map +1 -1
  60. package/dist/controllers/user-storage/index.d.cts.map +1 -1
  61. package/dist/controllers/user-storage/index.d.mts.map +1 -1
  62. package/dist/controllers/user-storage/index.mjs.map +1 -1
  63. package/dist/controllers/user-storage/mocks/index.cjs.map +1 -1
  64. package/dist/controllers/user-storage/mocks/index.d.cts.map +1 -1
  65. package/dist/controllers/user-storage/mocks/index.d.mts.map +1 -1
  66. package/dist/controllers/user-storage/mocks/index.mjs.map +1 -1
  67. package/dist/controllers/user-storage/mocks/mockResponses.cjs +15 -15
  68. package/dist/controllers/user-storage/mocks/mockResponses.cjs.map +1 -1
  69. package/dist/controllers/user-storage/mocks/mockResponses.d.cts.map +1 -1
  70. package/dist/controllers/user-storage/mocks/mockResponses.d.mts.map +1 -1
  71. package/dist/controllers/user-storage/mocks/mockResponses.mjs.map +1 -1
  72. package/dist/controllers/user-storage/mocks/mockStorage.cjs +3 -3
  73. package/dist/controllers/user-storage/mocks/mockStorage.cjs.map +1 -1
  74. package/dist/controllers/user-storage/mocks/mockStorage.d.cts.map +1 -1
  75. package/dist/controllers/user-storage/mocks/mockStorage.d.mts.map +1 -1
  76. package/dist/controllers/user-storage/mocks/mockStorage.mjs.map +1 -1
  77. package/dist/controllers/user-storage/types.cjs.map +1 -1
  78. package/dist/controllers/user-storage/types.d.cts.map +1 -1
  79. package/dist/controllers/user-storage/types.d.mts.map +1 -1
  80. package/dist/controllers/user-storage/types.mjs.map +1 -1
  81. package/dist/index.cjs.map +1 -1
  82. package/dist/index.d.cts.map +1 -1
  83. package/dist/index.d.mts.map +1 -1
  84. package/dist/index.mjs.map +1 -1
  85. package/dist/sdk/authentication-jwt-bearer/flow-siwe.cjs +11 -11
  86. package/dist/sdk/authentication-jwt-bearer/flow-siwe.cjs.map +1 -1
  87. package/dist/sdk/authentication-jwt-bearer/flow-siwe.d.cts.map +1 -1
  88. package/dist/sdk/authentication-jwt-bearer/flow-siwe.d.mts.map +1 -1
  89. package/dist/sdk/authentication-jwt-bearer/flow-siwe.mjs.map +1 -1
  90. package/dist/sdk/authentication-jwt-bearer/flow-srp.cjs +22 -22
  91. package/dist/sdk/authentication-jwt-bearer/flow-srp.cjs.map +1 -1
  92. package/dist/sdk/authentication-jwt-bearer/flow-srp.d.cts.map +1 -1
  93. package/dist/sdk/authentication-jwt-bearer/flow-srp.d.mts.map +1 -1
  94. package/dist/sdk/authentication-jwt-bearer/flow-srp.mjs.map +1 -1
  95. package/dist/sdk/authentication-jwt-bearer/services.cjs +37 -37
  96. package/dist/sdk/authentication-jwt-bearer/services.cjs.map +1 -1
  97. package/dist/sdk/authentication-jwt-bearer/services.d.cts.map +1 -1
  98. package/dist/sdk/authentication-jwt-bearer/services.d.mts.map +1 -1
  99. package/dist/sdk/authentication-jwt-bearer/services.mjs.map +1 -1
  100. package/dist/sdk/authentication-jwt-bearer/types.cjs.map +1 -1
  101. package/dist/sdk/authentication-jwt-bearer/types.d.cts.map +1 -1
  102. package/dist/sdk/authentication-jwt-bearer/types.d.mts.map +1 -1
  103. package/dist/sdk/authentication-jwt-bearer/types.mjs.map +1 -1
  104. package/dist/sdk/authentication-jwt-bearer/utils/identifier.cjs +2 -2
  105. package/dist/sdk/authentication-jwt-bearer/utils/identifier.cjs.map +1 -1
  106. package/dist/sdk/authentication-jwt-bearer/utils/identifier.d.cts.map +1 -1
  107. package/dist/sdk/authentication-jwt-bearer/utils/identifier.d.mts.map +1 -1
  108. package/dist/sdk/authentication-jwt-bearer/utils/identifier.mjs.map +1 -1
  109. package/dist/sdk/authentication.cjs +21 -21
  110. package/dist/sdk/authentication.cjs.map +1 -1
  111. package/dist/sdk/authentication.d.cts.map +1 -1
  112. package/dist/sdk/authentication.d.mts.map +1 -1
  113. package/dist/sdk/authentication.mjs.map +1 -1
  114. package/dist/sdk/errors.cjs +3 -3
  115. package/dist/sdk/errors.cjs.map +1 -1
  116. package/dist/sdk/errors.mjs.map +1 -1
  117. package/dist/sdk/index.cjs.map +1 -1
  118. package/dist/sdk/index.d.cts.map +1 -1
  119. package/dist/sdk/index.d.mts.map +1 -1
  120. package/dist/sdk/index.mjs.map +1 -1
  121. package/dist/sdk/mocks/auth.cjs +12 -12
  122. package/dist/sdk/mocks/auth.cjs.map +1 -1
  123. package/dist/sdk/mocks/auth.d.cts.map +1 -1
  124. package/dist/sdk/mocks/auth.d.mts.map +1 -1
  125. package/dist/sdk/mocks/auth.mjs.map +1 -1
  126. package/dist/sdk/mocks/userstorage.cjs +8 -8
  127. package/dist/sdk/mocks/userstorage.cjs.map +1 -1
  128. package/dist/sdk/mocks/userstorage.mjs.map +1 -1
  129. package/dist/sdk/user-storage.cjs +32 -32
  130. package/dist/sdk/user-storage.cjs.map +1 -1
  131. package/dist/sdk/user-storage.d.cts.map +1 -1
  132. package/dist/sdk/user-storage.d.mts.map +1 -1
  133. package/dist/sdk/user-storage.mjs +1 -1
  134. package/dist/sdk/user-storage.mjs.map +1 -1
  135. package/dist/sdk/utils/validate-login-response.cjs.map +1 -1
  136. package/dist/sdk/utils/validate-login-response.d.cts.map +1 -1
  137. package/dist/sdk/utils/validate-login-response.d.mts.map +1 -1
  138. package/dist/sdk/utils/validate-login-response.mjs.map +1 -1
  139. package/dist/shared/encryption/cache.cjs +6 -6
  140. package/dist/shared/encryption/cache.cjs.map +1 -1
  141. package/dist/shared/encryption/cache.mjs.map +1 -1
  142. package/dist/shared/encryption/encryption.cjs +26 -26
  143. package/dist/shared/encryption/encryption.cjs.map +1 -1
  144. package/dist/shared/encryption/encryption.d.cts.map +1 -1
  145. package/dist/shared/encryption/encryption.d.mts.map +1 -1
  146. package/dist/shared/encryption/encryption.mjs.map +1 -1
  147. package/dist/shared/encryption/index.cjs +3 -3
  148. package/dist/shared/encryption/index.cjs.map +1 -1
  149. package/dist/shared/encryption/index.d.cts.map +1 -1
  150. package/dist/shared/encryption/index.d.mts.map +1 -1
  151. package/dist/shared/encryption/index.mjs.map +1 -1
  152. package/dist/shared/storage-schema.cjs +2 -2
  153. package/dist/shared/storage-schema.cjs.map +1 -1
  154. package/dist/shared/storage-schema.mjs.map +1 -1
  155. package/dist/shared/types/services.cjs.map +1 -1
  156. package/dist/shared/types/services.d.cts.map +1 -1
  157. package/dist/shared/types/services.d.mts.map +1 -1
  158. package/dist/shared/types/services.mjs.map +1 -1
  159. package/package.json +7 -7
@@ -1 +1 @@
1
- {"version":3,"file":"user-storage.mjs","sourceRoot":"","sources":["../../src/sdk/user-storage.ts"],"names":[],"mappings":"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","sourcesContent":["import { SHARED_SALT } from '../shared/encryption/constants.js';\nimport encryption, { createSHA256Hash } from '../shared/encryption/index.js';\nimport type { Env } from '../shared/env.js';\nimport { getEnvUrls } from '../shared/env.js';\nimport type {\n UserStorageGenericFeatureKey,\n UserStorageGenericFeatureName,\n UserStorageGenericPathWithFeatureAndKey,\n UserStorageGenericPathWithFeatureOnly,\n} from '../shared/storage-schema.js';\nimport { createEntryPath } from '../shared/storage-schema.js';\nimport type { NativeScrypt } from '../shared/types/encryption.js';\nimport type { IBaseAuth } from './authentication-jwt-bearer/types.js';\nimport { NotFoundError, UserStorageError } from './errors.js';\n\nexport const STORAGE_URL = (env: Env, encryptedPath: string) =>\n `${getEnvUrls(env).userStorageApiUrl}/api/v1/userstorage/${encryptedPath}`;\n\nexport type UserStorageConfig = {\n env: Env;\n auth: Pick<IBaseAuth, 'getAccessToken' | 'getUserProfile' | 'signMessage'>;\n};\n\nexport type StorageOptions = {\n getStorageKey: (\n message: `metamask:${string}`,\n entropySourceId?: string,\n ) => Promise<string | null>;\n setStorageKey: (\n message: `metamask:${string}`,\n val: string,\n entropySourceId?: string,\n ) => Promise<void>;\n};\n\nexport type UserStorageOptions = {\n storage?: StorageOptions;\n};\n\nexport type GetUserStorageAllFeatureEntriesResponse = {\n HashedKey: string;\n\n Data: string;\n}[];\n\nexport type UserStorageMethodOptions = {\n nativeScryptCrypto?: NativeScrypt;\n entropySourceId?: string;\n /**\n * When true, skip the `x-profile-id` header on feature-scoped requests,\n * letting the server default to the JWT `sub` (canonical profile ID).\n * Useful during canonical storage migration (ADR 0005) to read/verify\n * data stored under the canonical key.\n */\n useCanonicalScope?: boolean;\n};\n\ntype ErrorMessage = {\n message: string;\n error: string;\n};\n\nexport class UserStorage {\n protected config: UserStorageConfig;\n\n public options: UserStorageOptions;\n\n protected env: Env;\n\n constructor(config: UserStorageConfig, options: UserStorageOptions) {\n this.env = config.env;\n this.config = config;\n this.options = options;\n }\n\n async setItem(\n path: UserStorageGenericPathWithFeatureAndKey,\n value: string,\n options?: UserStorageMethodOptions,\n ): Promise<void> {\n await this.#upsertUserStorage(path, value, options);\n }\n\n async batchSetItems(\n path: UserStorageGenericFeatureName,\n values: [UserStorageGenericFeatureKey, string][],\n options?: UserStorageMethodOptions,\n ) {\n await this.#batchUpsertUserStorage(path, values, options);\n }\n\n async getItem(\n path: UserStorageGenericPathWithFeatureAndKey,\n options?: UserStorageMethodOptions,\n ): Promise<string | null> {\n return this.#getUserStorage(path, options);\n }\n\n async getAllFeatureItems(\n path: UserStorageGenericFeatureName,\n options?: UserStorageMethodOptions,\n ): Promise<string[] | null> {\n return this.#getUserStorageAllFeatureEntries(path, options);\n }\n\n async deleteItem(\n path: UserStorageGenericPathWithFeatureAndKey,\n options?: UserStorageMethodOptions,\n ): Promise<void> {\n return this.#deleteUserStorage(path, options);\n }\n\n async deleteAllFeatureItems(\n path: UserStorageGenericFeatureName,\n options?: UserStorageMethodOptions,\n ): Promise<void> {\n return this.#deleteUserStorageAllFeatureEntries(path, options);\n }\n\n async batchDeleteItems(\n path: UserStorageGenericFeatureName,\n values: UserStorageGenericFeatureKey[],\n options?: UserStorageMethodOptions,\n ) {\n return this.#batchDeleteUserStorage(path, values, options);\n }\n\n async getStorageKey(entropySourceId?: string): Promise<string> {\n const userProfile = await this.config.auth.getUserProfile(entropySourceId);\n const message = `metamask:${userProfile.profileId}` as const;\n\n const storageKey = await this.options.storage?.getStorageKey(\n message,\n entropySourceId,\n );\n if (storageKey) {\n return storageKey;\n }\n\n const storageKeySignature = await this.config.auth.signMessage(\n message,\n entropySourceId,\n );\n const hashedStorageKeySignature = createSHA256Hash(storageKeySignature);\n await this.options.storage?.setStorageKey(\n message,\n hashedStorageKeySignature,\n entropySourceId,\n );\n return hashedStorageKeySignature;\n }\n\n async #upsertUserStorage(\n path: UserStorageGenericPathWithFeatureAndKey,\n data: string,\n options?: UserStorageMethodOptions,\n ): Promise<void> {\n const entropySourceId = options?.entropySourceId;\n try {\n const headers = await this.#getAuthorizationHeader(entropySourceId);\n const profileScopeHeader = await this.#getProfileScopeHeader(\n entropySourceId,\n options?.useCanonicalScope,\n );\n const storageKey = await this.getStorageKey(entropySourceId);\n const encryptedData = await encryption.encryptString(\n data,\n storageKey,\n options?.nativeScryptCrypto,\n );\n const encryptedPath = createEntryPath(path, storageKey);\n\n const url = new URL(STORAGE_URL(this.env, encryptedPath));\n\n const response = await fetch(url.toString(), {\n method: 'PUT',\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n ...profileScopeHeader,\n },\n body: JSON.stringify({ data: encryptedData }),\n });\n\n if (!response.ok) {\n const responseBody: ErrorMessage = await response.json().catch(() => ({\n message: 'unknown',\n error: 'unknown',\n }));\n throw new Error(\n `HTTP error message: ${responseBody.message}, error: ${responseBody.error}`,\n );\n }\n } catch (e) {\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n throw new UserStorageError(\n `failed to upsert user storage for path '${path}'. ${errorMessage}`,\n );\n }\n }\n\n async #batchUpsertUserStorage(\n path: UserStorageGenericPathWithFeatureOnly,\n data: [string, string][],\n options?: UserStorageMethodOptions,\n ): Promise<void> {\n const entropySourceId = options?.entropySourceId;\n try {\n if (!data.length) {\n return;\n }\n\n const headers = await this.#getAuthorizationHeader(entropySourceId);\n const profileScopeHeader = await this.#getProfileScopeHeader(\n entropySourceId,\n options?.useCanonicalScope,\n );\n const storageKey = await this.getStorageKey(entropySourceId);\n\n const encryptedData = await Promise.all(\n data.map(async (d) => {\n return [\n this.#createEntryKey(d[0], storageKey),\n await encryption.encryptString(\n d[1],\n storageKey,\n options?.nativeScryptCrypto,\n ),\n ];\n }),\n );\n\n const url = new URL(STORAGE_URL(this.env, path));\n\n const response = await fetch(url.toString(), {\n method: 'PUT',\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n ...profileScopeHeader,\n },\n body: JSON.stringify({ data: Object.fromEntries(encryptedData) }),\n });\n\n if (!response.ok) {\n const responseBody: ErrorMessage = await response.json().catch(() => ({\n message: 'unknown',\n error: 'unknown',\n }));\n throw new Error(\n `HTTP error message: ${responseBody.message}, error: ${responseBody.error}`,\n );\n }\n } catch (e) {\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n throw new UserStorageError(\n `failed to batch upsert user storage for path '${path}'. ${errorMessage}`,\n );\n }\n }\n\n async #batchUpsertUserStorageWithAlreadyHashedAndEncryptedEntries(\n path: UserStorageGenericPathWithFeatureOnly,\n encryptedData: [string, string][],\n entropySourceId?: string,\n useCanonicalScope?: boolean,\n ): Promise<void> {\n try {\n const headers = await this.#getAuthorizationHeader(entropySourceId);\n const profileScopeHeader = await this.#getProfileScopeHeader(\n entropySourceId,\n useCanonicalScope,\n );\n\n const url = new URL(STORAGE_URL(this.env, path));\n\n const response = await fetch(url.toString(), {\n method: 'PUT',\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n ...profileScopeHeader,\n },\n body: JSON.stringify({ data: Object.fromEntries(encryptedData) }),\n });\n\n // istanbul ignore next\n if (!response.ok) {\n const responseBody: ErrorMessage = await response.json().catch(() => ({\n message: 'unknown',\n error: 'unknown',\n }));\n throw new Error(\n `HTTP error message: ${responseBody.message}, error: ${responseBody.error}`,\n );\n }\n } catch (e) {\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n // istanbul ignore next\n throw new UserStorageError(\n `failed to batch upsert user storage for path '${path}'. ${errorMessage}`,\n );\n }\n }\n\n async #getUserStorage(\n path: UserStorageGenericPathWithFeatureAndKey,\n options?: UserStorageMethodOptions,\n ): Promise<string | null> {\n const entropySourceId = options?.entropySourceId;\n try {\n const headers = await this.#getAuthorizationHeader(entropySourceId);\n const storageKey = await this.getStorageKey(entropySourceId);\n const encryptedPath = createEntryPath(path, storageKey);\n\n const url = new URL(STORAGE_URL(this.env, encryptedPath));\n\n const response = await fetch(url.toString(), {\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n });\n\n if (response.status === 404) {\n return null;\n }\n\n if (!response.ok) {\n const responseBody = (await response.json()) as ErrorMessage;\n throw new Error(\n `HTTP error message: ${responseBody.message}, error: ${responseBody.error}`,\n );\n }\n\n const userStorage = await response.json();\n const encryptedData = userStorage?.Data ?? null;\n\n if (!encryptedData) {\n return null;\n }\n\n const decryptedData = await encryption.decryptString(\n encryptedData,\n storageKey,\n options?.nativeScryptCrypto,\n );\n\n // Re-encrypt the entry if it was encrypted with a random salt\n const salt = encryption.getSalt(encryptedData);\n if (salt.toString() !== SHARED_SALT.toString()) {\n await this.#upsertUserStorage(path, decryptedData, options);\n }\n\n return decryptedData;\n } catch (e) {\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n\n throw new UserStorageError(\n `failed to get user storage for path '${path}'. ${errorMessage}`,\n );\n }\n }\n\n async #getUserStorageAllFeatureEntries(\n path: UserStorageGenericPathWithFeatureOnly,\n options?: UserStorageMethodOptions,\n ): Promise<string[] | null> {\n const entropySourceId = options?.entropySourceId;\n try {\n const headers = await this.#getAuthorizationHeader(entropySourceId);\n const profileScopeHeader = await this.#getProfileScopeHeader(\n entropySourceId,\n options?.useCanonicalScope,\n );\n const storageKey = await this.getStorageKey(entropySourceId);\n\n const url = new URL(STORAGE_URL(this.env, path));\n\n const response = await fetch(url.toString(), {\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n ...profileScopeHeader,\n },\n });\n\n if (response.status === 404) {\n return null;\n }\n\n if (!response.ok) {\n const responseBody = (await response.json()) as ErrorMessage;\n throw new Error(\n `HTTP error message: ${responseBody.message}, error: ${responseBody.error}`,\n );\n }\n\n const userStorage: GetUserStorageAllFeatureEntriesResponse | null =\n await response.json();\n\n if (!Array.isArray(userStorage)) {\n return null;\n }\n\n const decryptedData: string[] = [];\n const reEncryptedEntries: [string, string][] = [];\n\n for (const entry of userStorage) {\n if (!entry.Data) {\n continue;\n }\n\n try {\n const data = await encryption.decryptString(\n entry.Data,\n storageKey,\n options?.nativeScryptCrypto,\n );\n decryptedData.push(data);\n\n // Re-encrypt the entry was encrypted with a random salt\n const salt = encryption.getSalt(entry.Data);\n if (salt.toString() !== SHARED_SALT.toString()) {\n reEncryptedEntries.push([\n entry.HashedKey,\n await encryption.encryptString(\n data,\n storageKey,\n options?.nativeScryptCrypto,\n ),\n ]);\n }\n } catch {\n // do nothing\n }\n }\n\n // Re-upload the re-encrypted entries\n if (reEncryptedEntries.length) {\n await this.#batchUpsertUserStorageWithAlreadyHashedAndEncryptedEntries(\n path,\n reEncryptedEntries,\n entropySourceId,\n options?.useCanonicalScope,\n );\n }\n\n return decryptedData;\n } catch (e) {\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n\n throw new UserStorageError(\n `failed to get user storage for path '${path}'. ${errorMessage}`,\n );\n }\n }\n\n async #deleteUserStorage(\n path: UserStorageGenericPathWithFeatureAndKey,\n options?: UserStorageMethodOptions,\n ): Promise<void> {\n const entropySourceId = options?.entropySourceId;\n try {\n const headers = await this.#getAuthorizationHeader(entropySourceId);\n const storageKey = await this.getStorageKey(entropySourceId);\n const encryptedPath = createEntryPath(path, storageKey);\n\n const url = new URL(STORAGE_URL(this.env, encryptedPath));\n\n const response = await fetch(url.toString(), {\n method: 'DELETE',\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n });\n\n if (response.status === 404) {\n throw new NotFoundError(\n `feature/key set not found for path '${path}'.`,\n );\n }\n\n if (!response.ok) {\n const responseBody = (await response.json()) as ErrorMessage;\n throw new Error(\n `HTTP error message: ${responseBody.message}, error: ${responseBody.error}`,\n );\n }\n } catch (e) {\n if (e instanceof NotFoundError) {\n throw e;\n }\n\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n\n throw new UserStorageError(\n `failed to delete user storage for path '${path}'. ${errorMessage}`,\n );\n }\n }\n\n async #deleteUserStorageAllFeatureEntries(\n path: UserStorageGenericPathWithFeatureOnly,\n options?: UserStorageMethodOptions,\n ): Promise<void> {\n try {\n const entropySourceId = options?.entropySourceId;\n const headers = await this.#getAuthorizationHeader(entropySourceId);\n const profileScopeHeader = await this.#getProfileScopeHeader(\n entropySourceId,\n options?.useCanonicalScope,\n );\n\n const url = new URL(STORAGE_URL(this.env, path));\n\n const response = await fetch(url.toString(), {\n method: 'DELETE',\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n ...profileScopeHeader,\n },\n });\n\n if (response.status === 404) {\n throw new NotFoundError(`feature not found for path '${path}'.`);\n }\n\n if (!response.ok) {\n const responseBody = (await response.json()) as ErrorMessage;\n throw new Error(\n `HTTP error message: ${responseBody.message}, error: ${responseBody.error}`,\n );\n }\n } catch (e) {\n if (e instanceof NotFoundError) {\n throw e;\n }\n\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n\n throw new UserStorageError(\n `failed to delete user storage for path '${path}'. ${errorMessage}`,\n );\n }\n }\n\n async #batchDeleteUserStorage(\n path: UserStorageGenericPathWithFeatureOnly,\n keysToDelete: string[],\n options?: UserStorageMethodOptions,\n ): Promise<void> {\n try {\n if (!keysToDelete.length) {\n return;\n }\n\n const entropySourceId = options?.entropySourceId;\n const headers = await this.#getAuthorizationHeader(entropySourceId);\n const storageKey = await this.getStorageKey(entropySourceId);\n\n const rawEntryKeys = keysToDelete.map((d) =>\n this.#createEntryKey(d, storageKey),\n );\n\n const url = new URL(STORAGE_URL(this.env, path));\n\n const response = await fetch(url.toString(), {\n method: 'PUT',\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n\n body: JSON.stringify({ batch_delete: rawEntryKeys }),\n });\n\n if (!response.ok) {\n const responseBody: ErrorMessage = await response.json().catch(() => ({\n message: 'unknown',\n error: 'unknown',\n }));\n throw new Error(\n `HTTP error message: ${responseBody.message}, error: ${responseBody.error}`,\n );\n }\n } catch (e) {\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n throw new UserStorageError(\n `failed to batch delete user storage for path '${path}'. ${errorMessage}`,\n );\n }\n }\n\n #createEntryKey(key: string, storageKey: string): string {\n return createSHA256Hash(key + storageKey);\n }\n\n async #getAuthorizationHeader(\n entropySourceId?: string,\n ): Promise<{ Authorization: string }> {\n const accessToken = await this.config.auth.getAccessToken(entropySourceId);\n return { Authorization: `Bearer ${accessToken}` };\n }\n\n async #getProfileScopeHeader(\n entropySourceId?: string,\n useCanonicalScope?: boolean,\n ): Promise<Record<string, string>> {\n if (useCanonicalScope) {\n return {};\n }\n const profile = await this.config.auth.getUserProfile(entropySourceId);\n if (profile.profileId !== profile.canonicalProfileId) {\n // After SRP pairing the JWT `sub` is the canonical profile id, but\n // user storage data is still keyed by the original per-SRP profileId.\n // The `x-profile-id` header tells the backend to scope reads/writes to\n // that alias partition until ADR 0005 migrates storage keys to canonical.\n return { 'x-profile-id': profile.profileId };\n }\n return {};\n }\n}\n"]}
1
+ {"version":3,"file":"user-storage.mjs","sourceRoot":"","sources":["../../src/sdk/user-storage.ts"],"names":[],"mappings":"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","sourcesContent":["import encryption, { createSHA256Hash } from '../shared/encryption';\nimport { SHARED_SALT } from '../shared/encryption/constants';\nimport type { Env } from '../shared/env';\nimport { getEnvUrls } from '../shared/env';\nimport type {\n UserStorageGenericFeatureKey,\n UserStorageGenericFeatureName,\n UserStorageGenericPathWithFeatureAndKey,\n UserStorageGenericPathWithFeatureOnly,\n} from '../shared/storage-schema';\nimport { createEntryPath } from '../shared/storage-schema';\nimport type { NativeScrypt } from '../shared/types/encryption';\nimport type { IBaseAuth } from './authentication-jwt-bearer/types';\nimport { NotFoundError, UserStorageError } from './errors';\n\nexport const STORAGE_URL = (env: Env, encryptedPath: string) =>\n `${getEnvUrls(env).userStorageApiUrl}/api/v1/userstorage/${encryptedPath}`;\n\nexport type UserStorageConfig = {\n env: Env;\n auth: Pick<IBaseAuth, 'getAccessToken' | 'getUserProfile' | 'signMessage'>;\n};\n\nexport type StorageOptions = {\n getStorageKey: (\n message: `metamask:${string}`,\n entropySourceId?: string,\n ) => Promise<string | null>;\n setStorageKey: (\n message: `metamask:${string}`,\n val: string,\n entropySourceId?: string,\n ) => Promise<void>;\n};\n\nexport type UserStorageOptions = {\n storage?: StorageOptions;\n};\n\nexport type GetUserStorageAllFeatureEntriesResponse = {\n HashedKey: string;\n\n Data: string;\n}[];\n\nexport type UserStorageMethodOptions = {\n nativeScryptCrypto?: NativeScrypt;\n entropySourceId?: string;\n /**\n * When true, skip the `x-profile-id` header on feature-scoped requests,\n * letting the server default to the JWT `sub` (canonical profile ID).\n * Useful during canonical storage migration (ADR 0005) to read/verify\n * data stored under the canonical key.\n */\n useCanonicalScope?: boolean;\n};\n\ntype ErrorMessage = {\n message: string;\n error: string;\n};\n\nexport class UserStorage {\n protected config: UserStorageConfig;\n\n public options: UserStorageOptions;\n\n protected env: Env;\n\n constructor(config: UserStorageConfig, options: UserStorageOptions) {\n this.env = config.env;\n this.config = config;\n this.options = options;\n }\n\n async setItem(\n path: UserStorageGenericPathWithFeatureAndKey,\n value: string,\n options?: UserStorageMethodOptions,\n ): Promise<void> {\n await this.#upsertUserStorage(path, value, options);\n }\n\n async batchSetItems(\n path: UserStorageGenericFeatureName,\n values: [UserStorageGenericFeatureKey, string][],\n options?: UserStorageMethodOptions,\n ) {\n await this.#batchUpsertUserStorage(path, values, options);\n }\n\n async getItem(\n path: UserStorageGenericPathWithFeatureAndKey,\n options?: UserStorageMethodOptions,\n ): Promise<string | null> {\n return this.#getUserStorage(path, options);\n }\n\n async getAllFeatureItems(\n path: UserStorageGenericFeatureName,\n options?: UserStorageMethodOptions,\n ): Promise<string[] | null> {\n return this.#getUserStorageAllFeatureEntries(path, options);\n }\n\n async deleteItem(\n path: UserStorageGenericPathWithFeatureAndKey,\n options?: UserStorageMethodOptions,\n ): Promise<void> {\n return this.#deleteUserStorage(path, options);\n }\n\n async deleteAllFeatureItems(\n path: UserStorageGenericFeatureName,\n options?: UserStorageMethodOptions,\n ): Promise<void> {\n return this.#deleteUserStorageAllFeatureEntries(path, options);\n }\n\n async batchDeleteItems(\n path: UserStorageGenericFeatureName,\n values: UserStorageGenericFeatureKey[],\n options?: UserStorageMethodOptions,\n ) {\n return this.#batchDeleteUserStorage(path, values, options);\n }\n\n async getStorageKey(entropySourceId?: string): Promise<string> {\n const userProfile = await this.config.auth.getUserProfile(entropySourceId);\n const message = `metamask:${userProfile.profileId}` as const;\n\n const storageKey = await this.options.storage?.getStorageKey(\n message,\n entropySourceId,\n );\n if (storageKey) {\n return storageKey;\n }\n\n const storageKeySignature = await this.config.auth.signMessage(\n message,\n entropySourceId,\n );\n const hashedStorageKeySignature = createSHA256Hash(storageKeySignature);\n await this.options.storage?.setStorageKey(\n message,\n hashedStorageKeySignature,\n entropySourceId,\n );\n return hashedStorageKeySignature;\n }\n\n async #upsertUserStorage(\n path: UserStorageGenericPathWithFeatureAndKey,\n data: string,\n options?: UserStorageMethodOptions,\n ): Promise<void> {\n const entropySourceId = options?.entropySourceId;\n try {\n const headers = await this.#getAuthorizationHeader(entropySourceId);\n const profileScopeHeader = await this.#getProfileScopeHeader(\n entropySourceId,\n options?.useCanonicalScope,\n );\n const storageKey = await this.getStorageKey(entropySourceId);\n const encryptedData = await encryption.encryptString(\n data,\n storageKey,\n options?.nativeScryptCrypto,\n );\n const encryptedPath = createEntryPath(path, storageKey);\n\n const url = new URL(STORAGE_URL(this.env, encryptedPath));\n\n const response = await fetch(url.toString(), {\n method: 'PUT',\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n ...profileScopeHeader,\n },\n body: JSON.stringify({ data: encryptedData }),\n });\n\n if (!response.ok) {\n const responseBody: ErrorMessage = await response.json().catch(() => ({\n message: 'unknown',\n error: 'unknown',\n }));\n throw new Error(\n `HTTP error message: ${responseBody.message}, error: ${responseBody.error}`,\n );\n }\n } catch (e) {\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n throw new UserStorageError(\n `failed to upsert user storage for path '${path}'. ${errorMessage}`,\n );\n }\n }\n\n async #batchUpsertUserStorage(\n path: UserStorageGenericPathWithFeatureOnly,\n data: [string, string][],\n options?: UserStorageMethodOptions,\n ): Promise<void> {\n const entropySourceId = options?.entropySourceId;\n try {\n if (!data.length) {\n return;\n }\n\n const headers = await this.#getAuthorizationHeader(entropySourceId);\n const profileScopeHeader = await this.#getProfileScopeHeader(\n entropySourceId,\n options?.useCanonicalScope,\n );\n const storageKey = await this.getStorageKey(entropySourceId);\n\n const encryptedData = await Promise.all(\n data.map(async (d) => {\n return [\n this.#createEntryKey(d[0], storageKey),\n await encryption.encryptString(\n d[1],\n storageKey,\n options?.nativeScryptCrypto,\n ),\n ];\n }),\n );\n\n const url = new URL(STORAGE_URL(this.env, path));\n\n const response = await fetch(url.toString(), {\n method: 'PUT',\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n ...profileScopeHeader,\n },\n body: JSON.stringify({ data: Object.fromEntries(encryptedData) }),\n });\n\n if (!response.ok) {\n const responseBody: ErrorMessage = await response.json().catch(() => ({\n message: 'unknown',\n error: 'unknown',\n }));\n throw new Error(\n `HTTP error message: ${responseBody.message}, error: ${responseBody.error}`,\n );\n }\n } catch (e) {\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n throw new UserStorageError(\n `failed to batch upsert user storage for path '${path}'. ${errorMessage}`,\n );\n }\n }\n\n async #batchUpsertUserStorageWithAlreadyHashedAndEncryptedEntries(\n path: UserStorageGenericPathWithFeatureOnly,\n encryptedData: [string, string][],\n entropySourceId?: string,\n useCanonicalScope?: boolean,\n ): Promise<void> {\n try {\n const headers = await this.#getAuthorizationHeader(entropySourceId);\n const profileScopeHeader = await this.#getProfileScopeHeader(\n entropySourceId,\n useCanonicalScope,\n );\n\n const url = new URL(STORAGE_URL(this.env, path));\n\n const response = await fetch(url.toString(), {\n method: 'PUT',\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n ...profileScopeHeader,\n },\n body: JSON.stringify({ data: Object.fromEntries(encryptedData) }),\n });\n\n // istanbul ignore next\n if (!response.ok) {\n const responseBody: ErrorMessage = await response.json().catch(() => ({\n message: 'unknown',\n error: 'unknown',\n }));\n throw new Error(\n `HTTP error message: ${responseBody.message}, error: ${responseBody.error}`,\n );\n }\n } catch (e) {\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n // istanbul ignore next\n throw new UserStorageError(\n `failed to batch upsert user storage for path '${path}'. ${errorMessage}`,\n );\n }\n }\n\n async #getUserStorage(\n path: UserStorageGenericPathWithFeatureAndKey,\n options?: UserStorageMethodOptions,\n ): Promise<string | null> {\n const entropySourceId = options?.entropySourceId;\n try {\n const headers = await this.#getAuthorizationHeader(entropySourceId);\n const storageKey = await this.getStorageKey(entropySourceId);\n const encryptedPath = createEntryPath(path, storageKey);\n\n const url = new URL(STORAGE_URL(this.env, encryptedPath));\n\n const response = await fetch(url.toString(), {\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n });\n\n if (response.status === 404) {\n return null;\n }\n\n if (!response.ok) {\n const responseBody = (await response.json()) as ErrorMessage;\n throw new Error(\n `HTTP error message: ${responseBody.message}, error: ${responseBody.error}`,\n );\n }\n\n const userStorage = await response.json();\n const encryptedData = userStorage?.Data ?? null;\n\n if (!encryptedData) {\n return null;\n }\n\n const decryptedData = await encryption.decryptString(\n encryptedData,\n storageKey,\n options?.nativeScryptCrypto,\n );\n\n // Re-encrypt the entry if it was encrypted with a random salt\n const salt = encryption.getSalt(encryptedData);\n if (salt.toString() !== SHARED_SALT.toString()) {\n await this.#upsertUserStorage(path, decryptedData, options);\n }\n\n return decryptedData;\n } catch (e) {\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n\n throw new UserStorageError(\n `failed to get user storage for path '${path}'. ${errorMessage}`,\n );\n }\n }\n\n async #getUserStorageAllFeatureEntries(\n path: UserStorageGenericPathWithFeatureOnly,\n options?: UserStorageMethodOptions,\n ): Promise<string[] | null> {\n const entropySourceId = options?.entropySourceId;\n try {\n const headers = await this.#getAuthorizationHeader(entropySourceId);\n const profileScopeHeader = await this.#getProfileScopeHeader(\n entropySourceId,\n options?.useCanonicalScope,\n );\n const storageKey = await this.getStorageKey(entropySourceId);\n\n const url = new URL(STORAGE_URL(this.env, path));\n\n const response = await fetch(url.toString(), {\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n ...profileScopeHeader,\n },\n });\n\n if (response.status === 404) {\n return null;\n }\n\n if (!response.ok) {\n const responseBody = (await response.json()) as ErrorMessage;\n throw new Error(\n `HTTP error message: ${responseBody.message}, error: ${responseBody.error}`,\n );\n }\n\n const userStorage: GetUserStorageAllFeatureEntriesResponse | null =\n await response.json();\n\n if (!Array.isArray(userStorage)) {\n return null;\n }\n\n const decryptedData: string[] = [];\n const reEncryptedEntries: [string, string][] = [];\n\n for (const entry of userStorage) {\n if (!entry.Data) {\n continue;\n }\n\n try {\n const data = await encryption.decryptString(\n entry.Data,\n storageKey,\n options?.nativeScryptCrypto,\n );\n decryptedData.push(data);\n\n // Re-encrypt the entry was encrypted with a random salt\n const salt = encryption.getSalt(entry.Data);\n if (salt.toString() !== SHARED_SALT.toString()) {\n reEncryptedEntries.push([\n entry.HashedKey,\n await encryption.encryptString(\n data,\n storageKey,\n options?.nativeScryptCrypto,\n ),\n ]);\n }\n } catch {\n // do nothing\n }\n }\n\n // Re-upload the re-encrypted entries\n if (reEncryptedEntries.length) {\n await this.#batchUpsertUserStorageWithAlreadyHashedAndEncryptedEntries(\n path,\n reEncryptedEntries,\n entropySourceId,\n options?.useCanonicalScope,\n );\n }\n\n return decryptedData;\n } catch (e) {\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n\n throw new UserStorageError(\n `failed to get user storage for path '${path}'. ${errorMessage}`,\n );\n }\n }\n\n async #deleteUserStorage(\n path: UserStorageGenericPathWithFeatureAndKey,\n options?: UserStorageMethodOptions,\n ): Promise<void> {\n const entropySourceId = options?.entropySourceId;\n try {\n const headers = await this.#getAuthorizationHeader(entropySourceId);\n const storageKey = await this.getStorageKey(entropySourceId);\n const encryptedPath = createEntryPath(path, storageKey);\n\n const url = new URL(STORAGE_URL(this.env, encryptedPath));\n\n const response = await fetch(url.toString(), {\n method: 'DELETE',\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n });\n\n if (response.status === 404) {\n throw new NotFoundError(\n `feature/key set not found for path '${path}'.`,\n );\n }\n\n if (!response.ok) {\n const responseBody = (await response.json()) as ErrorMessage;\n throw new Error(\n `HTTP error message: ${responseBody.message}, error: ${responseBody.error}`,\n );\n }\n } catch (e) {\n if (e instanceof NotFoundError) {\n throw e;\n }\n\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n\n throw new UserStorageError(\n `failed to delete user storage for path '${path}'. ${errorMessage}`,\n );\n }\n }\n\n async #deleteUserStorageAllFeatureEntries(\n path: UserStorageGenericPathWithFeatureOnly,\n options?: UserStorageMethodOptions,\n ): Promise<void> {\n try {\n const entropySourceId = options?.entropySourceId;\n const headers = await this.#getAuthorizationHeader(entropySourceId);\n const profileScopeHeader = await this.#getProfileScopeHeader(\n entropySourceId,\n options?.useCanonicalScope,\n );\n\n const url = new URL(STORAGE_URL(this.env, path));\n\n const response = await fetch(url.toString(), {\n method: 'DELETE',\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n ...profileScopeHeader,\n },\n });\n\n if (response.status === 404) {\n throw new NotFoundError(`feature not found for path '${path}'.`);\n }\n\n if (!response.ok) {\n const responseBody = (await response.json()) as ErrorMessage;\n throw new Error(\n `HTTP error message: ${responseBody.message}, error: ${responseBody.error}`,\n );\n }\n } catch (e) {\n if (e instanceof NotFoundError) {\n throw e;\n }\n\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n\n throw new UserStorageError(\n `failed to delete user storage for path '${path}'. ${errorMessage}`,\n );\n }\n }\n\n async #batchDeleteUserStorage(\n path: UserStorageGenericPathWithFeatureOnly,\n keysToDelete: string[],\n options?: UserStorageMethodOptions,\n ): Promise<void> {\n try {\n if (!keysToDelete.length) {\n return;\n }\n\n const entropySourceId = options?.entropySourceId;\n const headers = await this.#getAuthorizationHeader(entropySourceId);\n const storageKey = await this.getStorageKey(entropySourceId);\n\n const rawEntryKeys = keysToDelete.map((d) =>\n this.#createEntryKey(d, storageKey),\n );\n\n const url = new URL(STORAGE_URL(this.env, path));\n\n const response = await fetch(url.toString(), {\n method: 'PUT',\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n\n body: JSON.stringify({ batch_delete: rawEntryKeys }),\n });\n\n if (!response.ok) {\n const responseBody: ErrorMessage = await response.json().catch(() => ({\n message: 'unknown',\n error: 'unknown',\n }));\n throw new Error(\n `HTTP error message: ${responseBody.message}, error: ${responseBody.error}`,\n );\n }\n } catch (e) {\n /* istanbul ignore next */\n const errorMessage =\n e instanceof Error ? e.message : JSON.stringify(e ?? '');\n throw new UserStorageError(\n `failed to batch delete user storage for path '${path}'. ${errorMessage}`,\n );\n }\n }\n\n #createEntryKey(key: string, storageKey: string): string {\n return createSHA256Hash(key + storageKey);\n }\n\n async #getAuthorizationHeader(\n entropySourceId?: string,\n ): Promise<{ Authorization: string }> {\n const accessToken = await this.config.auth.getAccessToken(entropySourceId);\n return { Authorization: `Bearer ${accessToken}` };\n }\n\n async #getProfileScopeHeader(\n entropySourceId?: string,\n useCanonicalScope?: boolean,\n ): Promise<Record<string, string>> {\n if (useCanonicalScope) {\n return {};\n }\n const profile = await this.config.auth.getUserProfile(entropySourceId);\n if (profile.profileId !== profile.canonicalProfileId) {\n // After SRP pairing the JWT `sub` is the canonical profile id, but\n // user storage data is still keyed by the original per-SRP profileId.\n // The `x-profile-id` header tells the backend to scope reads/writes to\n // that alias partition until ADR 0005 migrates storage keys to canonical.\n return { 'x-profile-id': profile.profileId };\n }\n return {};\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"validate-login-response.cjs","sourceRoot":"","sources":["../../../src/sdk/utils/validate-login-response.ts"],"names":[],"mappings":";;;AAEA;;;;;;;;;;GAUG;AACH,SAAgB,qBAAqB,CAAC,KAAc;IAClD,MAAM,YAAY,GAAG,KAAsB,CAAC;IAE5C,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC,YAAY,EAAE,KAAK,IAAI,CAAC,YAAY,EAAE,OAAO,EAAE,CAAC;QACnD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,YAAY,CAAC,YAAY,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC;QACjD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAhBD,sDAgBC;AAED;;;;;GAKG;AACH,SAAS,YAAY,CAAC,KAAa;IACjC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAChE,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;QACzC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC","sourcesContent":["import type { LoginResponse } from '../authentication.js';\n\n/**\n * Validates that the input is a well-formed, non-expired LoginResponse.\n *\n * Checks structural shape (token + profile objects exist) and verifies\n * the JWT access token's `exp` claim is still in the future. This acts\n * as a hard guard against stale cached tokens regardless of client-side\n * TTL tracking (obtainedAt / expiresIn), which can be corrupted.\n *\n * @param input - unknown/untyped input\n * @returns boolean if input is a valid, non-expired LoginResponse\n */\nexport function validateLoginResponse(input: unknown): input is LoginResponse {\n const assumedInput = input as LoginResponse;\n\n if (!assumedInput) {\n return false;\n }\n\n if (!assumedInput?.token || !assumedInput?.profile) {\n return false;\n }\n\n if (isJwtExpired(assumedInput.token.accessToken)) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Checks whether a JWT has expired by decoding its `exp` claim.\n *\n * @param token - A JWT string.\n * @returns true if the token is expired or cannot be decoded; false if still valid.\n */\nfunction isJwtExpired(token: string): boolean {\n try {\n const parts = token.split('.');\n if (parts.length !== 3) {\n return true;\n }\n const base64 = parts[1].replace(/-/gu, '+').replace(/_/gu, '/');\n const { exp } = JSON.parse(atob(base64));\n return !Number.isInteger(exp) || exp * 1000 <= Date.now();\n } catch {\n return true;\n }\n}\n"]}
1
+ {"version":3,"file":"validate-login-response.cjs","sourceRoot":"","sources":["../../../src/sdk/utils/validate-login-response.ts"],"names":[],"mappings":";;;AAEA;;;;;;;;;;GAUG;AACH,SAAgB,qBAAqB,CAAC,KAAc;IAClD,MAAM,YAAY,GAAG,KAAsB,CAAC;IAE5C,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC,YAAY,EAAE,KAAK,IAAI,CAAC,YAAY,EAAE,OAAO,EAAE,CAAC;QACnD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,YAAY,CAAC,YAAY,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC;QACjD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAhBD,sDAgBC;AAED;;;;;GAKG;AACH,SAAS,YAAY,CAAC,KAAa;IACjC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAChE,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;QACzC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC","sourcesContent":["import type { LoginResponse } from '../authentication';\n\n/**\n * Validates that the input is a well-formed, non-expired LoginResponse.\n *\n * Checks structural shape (token + profile objects exist) and verifies\n * the JWT access token's `exp` claim is still in the future. This acts\n * as a hard guard against stale cached tokens regardless of client-side\n * TTL tracking (obtainedAt / expiresIn), which can be corrupted.\n *\n * @param input - unknown/untyped input\n * @returns boolean if input is a valid, non-expired LoginResponse\n */\nexport function validateLoginResponse(input: unknown): input is LoginResponse {\n const assumedInput = input as LoginResponse;\n\n if (!assumedInput) {\n return false;\n }\n\n if (!assumedInput?.token || !assumedInput?.profile) {\n return false;\n }\n\n if (isJwtExpired(assumedInput.token.accessToken)) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Checks whether a JWT has expired by decoding its `exp` claim.\n *\n * @param token - A JWT string.\n * @returns true if the token is expired or cannot be decoded; false if still valid.\n */\nfunction isJwtExpired(token: string): boolean {\n try {\n const parts = token.split('.');\n if (parts.length !== 3) {\n return true;\n }\n const base64 = parts[1].replace(/-/gu, '+').replace(/_/gu, '/');\n const { exp } = JSON.parse(atob(base64));\n return !Number.isInteger(exp) || exp * 1000 <= Date.now();\n } catch {\n return true;\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"validate-login-response.d.cts","sourceRoot":"","sources":["../../../src/sdk/utils/validate-login-response.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,8BAA6B;AAE1D;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,aAAa,CAgB5E"}
1
+ {"version":3,"file":"validate-login-response.d.cts","sourceRoot":"","sources":["../../../src/sdk/utils/validate-login-response.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,8BAA0B;AAEvD;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,aAAa,CAgB5E"}
@@ -1 +1 @@
1
- {"version":3,"file":"validate-login-response.d.mts","sourceRoot":"","sources":["../../../src/sdk/utils/validate-login-response.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,8BAA6B;AAE1D;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,aAAa,CAgB5E"}
1
+ {"version":3,"file":"validate-login-response.d.mts","sourceRoot":"","sources":["../../../src/sdk/utils/validate-login-response.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,8BAA0B;AAEvD;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,aAAa,CAgB5E"}
@@ -1 +1 @@
1
- {"version":3,"file":"validate-login-response.mjs","sourceRoot":"","sources":["../../../src/sdk/utils/validate-login-response.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAc;IAClD,MAAM,YAAY,GAAG,KAAsB,CAAC;IAE5C,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC,YAAY,EAAE,KAAK,IAAI,CAAC,YAAY,EAAE,OAAO,EAAE,CAAC;QACnD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,YAAY,CAAC,YAAY,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC;QACjD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,SAAS,YAAY,CAAC,KAAa;IACjC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAChE,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;QACzC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC","sourcesContent":["import type { LoginResponse } from '../authentication.js';\n\n/**\n * Validates that the input is a well-formed, non-expired LoginResponse.\n *\n * Checks structural shape (token + profile objects exist) and verifies\n * the JWT access token's `exp` claim is still in the future. This acts\n * as a hard guard against stale cached tokens regardless of client-side\n * TTL tracking (obtainedAt / expiresIn), which can be corrupted.\n *\n * @param input - unknown/untyped input\n * @returns boolean if input is a valid, non-expired LoginResponse\n */\nexport function validateLoginResponse(input: unknown): input is LoginResponse {\n const assumedInput = input as LoginResponse;\n\n if (!assumedInput) {\n return false;\n }\n\n if (!assumedInput?.token || !assumedInput?.profile) {\n return false;\n }\n\n if (isJwtExpired(assumedInput.token.accessToken)) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Checks whether a JWT has expired by decoding its `exp` claim.\n *\n * @param token - A JWT string.\n * @returns true if the token is expired or cannot be decoded; false if still valid.\n */\nfunction isJwtExpired(token: string): boolean {\n try {\n const parts = token.split('.');\n if (parts.length !== 3) {\n return true;\n }\n const base64 = parts[1].replace(/-/gu, '+').replace(/_/gu, '/');\n const { exp } = JSON.parse(atob(base64));\n return !Number.isInteger(exp) || exp * 1000 <= Date.now();\n } catch {\n return true;\n }\n}\n"]}
1
+ {"version":3,"file":"validate-login-response.mjs","sourceRoot":"","sources":["../../../src/sdk/utils/validate-login-response.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAc;IAClD,MAAM,YAAY,GAAG,KAAsB,CAAC;IAE5C,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC,YAAY,EAAE,KAAK,IAAI,CAAC,YAAY,EAAE,OAAO,EAAE,CAAC;QACnD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,YAAY,CAAC,YAAY,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC;QACjD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,SAAS,YAAY,CAAC,KAAa;IACjC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAChE,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;QACzC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC","sourcesContent":["import type { LoginResponse } from '../authentication';\n\n/**\n * Validates that the input is a well-formed, non-expired LoginResponse.\n *\n * Checks structural shape (token + profile objects exist) and verifies\n * the JWT access token's `exp` claim is still in the future. This acts\n * as a hard guard against stale cached tokens regardless of client-side\n * TTL tracking (obtainedAt / expiresIn), which can be corrupted.\n *\n * @param input - unknown/untyped input\n * @returns boolean if input is a valid, non-expired LoginResponse\n */\nexport function validateLoginResponse(input: unknown): input is LoginResponse {\n const assumedInput = input as LoginResponse;\n\n if (!assumedInput) {\n return false;\n }\n\n if (!assumedInput?.token || !assumedInput?.profile) {\n return false;\n }\n\n if (isJwtExpired(assumedInput.token.accessToken)) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Checks whether a JWT has expired by decoding its `exp` claim.\n *\n * @param token - A JWT string.\n * @returns true if the token is expired or cannot be decoded; false if still valid.\n */\nfunction isJwtExpired(token: string): boolean {\n try {\n const parts = token.split('.');\n if (parts.length !== 3) {\n return true;\n }\n const base64 = parts[1].replace(/-/gu, '+').replace(/_/gu, '/');\n const { exp } = JSON.parse(atob(base64));\n return !Number.isInteger(exp) || exp * 1000 <= Date.now();\n } catch {\n return true;\n }\n}\n"]}
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.setCachedKey = exports.getCachedKeyGeneratedWithSharedSalt = exports.getCachedKeyBySalt = void 0;
4
- const constants_js_1 = require("./constants.cjs");
5
- const utils_js_1 = require("./utils.cjs");
4
+ const constants_1 = require("./constants.cjs");
5
+ const utils_1 = require("./utils.cjs");
6
6
  const MAX_PASSWORD_CACHES = 100;
7
7
  const MAX_SALT_CACHES = 100;
8
8
  let inMemCachedKDF = {};
@@ -19,7 +19,7 @@ const getPasswordCache = (hashedPassword) => {
19
19
  */
20
20
  function getCachedKeyBySalt(hashedPassword, salt) {
21
21
  const cache = getPasswordCache(hashedPassword);
22
- const base64Salt = (0, utils_js_1.byteArrayToBase64)(salt);
22
+ const base64Salt = (0, utils_1.byteArrayToBase64)(salt);
23
23
  const cachedKey = cache.get(base64Salt);
24
24
  if (!cachedKey) {
25
25
  return undefined;
@@ -40,13 +40,13 @@ exports.getCachedKeyBySalt = getCachedKeyBySalt;
40
40
  */
41
41
  function getCachedKeyGeneratedWithSharedSalt(hashedPassword) {
42
42
  const cache = getPasswordCache(hashedPassword);
43
- const base64Salt = (0, utils_js_1.byteArrayToBase64)(constants_js_1.SHARED_SALT);
43
+ const base64Salt = (0, utils_1.byteArrayToBase64)(constants_1.SHARED_SALT);
44
44
  const cachedKey = cache.get(base64Salt);
45
45
  if (!cachedKey) {
46
46
  return undefined;
47
47
  }
48
48
  return {
49
- salt: constants_js_1.SHARED_SALT,
49
+ salt: constants_1.SHARED_SALT,
50
50
  base64Salt,
51
51
  key: cachedKey,
52
52
  };
@@ -66,7 +66,7 @@ function setCachedKey(hashedPassword, salt, key) {
66
66
  inMemCachedKDF = {};
67
67
  }
68
68
  const cache = getPasswordCache(hashedPassword);
69
- const base64Salt = (0, utils_js_1.byteArrayToBase64)(salt);
69
+ const base64Salt = (0, utils_1.byteArrayToBase64)(salt);
70
70
  // Max salt caches
71
71
  if (cache.size > MAX_SALT_CACHES) {
72
72
  cache.clear();
@@ -1 +1 @@
1
- {"version":3,"file":"cache.cjs","sourceRoot":"","sources":["../../../src/shared/encryption/cache.ts"],"names":[],"mappings":";;;AAAA,kDAA6C;AAC7C,0CAA+C;AAQ/C,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAChC,MAAM,eAAe,GAAG,GAAG,CAAC;AAQ5B,IAAI,cAAc,GAAyB,EAAE,CAAC;AAC9C,MAAM,gBAAgB,GAAG,CAAC,cAAsB,EAAE,EAAE;IAClD,cAAc,CAAC,cAAc,MAA7B,cAAc,CAAC,cAAc,IAAM,IAAI,GAAG,EAAE,EAAC;IAC7C,OAAO,cAAc,CAAC,cAAc,CAAC,CAAC;AACxC,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,SAAgB,kBAAkB,CAChC,cAAsB,EACtB,IAAgB;IAEhB,MAAM,KAAK,GAAG,gBAAgB,CAAC,cAAc,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,IAAA,4BAAiB,EAAC,IAAI,CAAC,CAAC;IAC3C,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACxC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO;QACL,IAAI;QACJ,UAAU;QACV,GAAG,EAAE,SAAS;KACf,CAAC;AACJ,CAAC;AAhBD,gDAgBC;AAED;;;;;;GAMG;AACH,SAAgB,mCAAmC,CACjD,cAAsB;IAEtB,MAAM,KAAK,GAAG,gBAAgB,CAAC,cAAc,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,IAAA,4BAAiB,EAAC,0BAAW,CAAC,CAAC;IAClD,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAExC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO;QACL,IAAI,EAAE,0BAAW;QACjB,UAAU;QACV,GAAG,EAAE,SAAS;KACf,CAAC;AACJ,CAAC;AAhBD,kFAgBC;AAED;;;;;;;GAOG;AACH,SAAgB,YAAY,CAC1B,cAAsB,EACtB,IAAgB,EAChB,GAAe;IAEf,sBAAsB;IACtB,IAAI,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,MAAM,GAAG,mBAAmB,EAAE,CAAC;QAC7D,cAAc,GAAG,EAAE,CAAC;IACtB,CAAC;IAED,MAAM,KAAK,GAAG,gBAAgB,CAAC,cAAc,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,IAAA,4BAAiB,EAAC,IAAI,CAAC,CAAC;IAE3C,kBAAkB;IAClB,IAAI,KAAK,CAAC,IAAI,GAAG,eAAe,EAAE,CAAC;QACjC,KAAK,CAAC,KAAK,EAAE,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;AAC7B,CAAC;AAnBD,oCAmBC","sourcesContent":["import { SHARED_SALT } from './constants.js';\nimport { byteArrayToBase64 } from './utils.js';\n\ntype CachedEntry = {\n salt: Uint8Array;\n base64Salt: string;\n key: Uint8Array;\n};\n\nconst MAX_PASSWORD_CACHES = 100;\nconst MAX_SALT_CACHES = 100;\n\n/**\n * In-Memory Caching derived keys based from a given salt and password.\n */\ntype PasswordMemCachedKDF = {\n [hashedPassword: string]: Map<string, Uint8Array>;\n};\nlet inMemCachedKDF: PasswordMemCachedKDF = {};\nconst getPasswordCache = (hashedPassword: string) => {\n inMemCachedKDF[hashedPassword] ??= new Map();\n return inMemCachedKDF[hashedPassword];\n};\n\n/**\n * Returns a given cached derived key from a hashed password and salt\n *\n * @param hashedPassword - hashed password for cache lookup\n * @param salt - provide salt to receive cached key\n * @returns cached key\n */\nexport function getCachedKeyBySalt(\n hashedPassword: string,\n salt: Uint8Array,\n): CachedEntry | undefined {\n const cache = getPasswordCache(hashedPassword);\n const base64Salt = byteArrayToBase64(salt);\n const cachedKey = cache.get(base64Salt);\n if (!cachedKey) {\n return undefined;\n }\n\n return {\n salt,\n base64Salt,\n key: cachedKey,\n };\n}\n\n/**\n * Gets the cached key that was generated without a salt, if it exists.\n * This is unique per hashed password.\n *\n * @param hashedPassword - hashed password for cache lookup\n * @returns the cached key\n */\nexport function getCachedKeyGeneratedWithSharedSalt(\n hashedPassword: string,\n): CachedEntry | undefined {\n const cache = getPasswordCache(hashedPassword);\n const base64Salt = byteArrayToBase64(SHARED_SALT);\n const cachedKey = cache.get(base64Salt);\n\n if (!cachedKey) {\n return undefined;\n }\n\n return {\n salt: SHARED_SALT,\n base64Salt,\n key: cachedKey,\n };\n}\n\n/**\n * Sets a key to the in memory cache.\n * We have set an arbitrary size of 10 cached keys per hashed password.\n *\n * @param hashedPassword - hashed password for cache lookup\n * @param salt - salt to set new derived key\n * @param key - derived key we are setting\n */\nexport function setCachedKey(\n hashedPassword: string,\n salt: Uint8Array,\n key: Uint8Array,\n): void {\n // Max password caches\n if (Object.keys(inMemCachedKDF).length > MAX_PASSWORD_CACHES) {\n inMemCachedKDF = {};\n }\n\n const cache = getPasswordCache(hashedPassword);\n const base64Salt = byteArrayToBase64(salt);\n\n // Max salt caches\n if (cache.size > MAX_SALT_CACHES) {\n cache.clear();\n }\n\n cache.set(base64Salt, key);\n}\n"]}
1
+ {"version":3,"file":"cache.cjs","sourceRoot":"","sources":["../../../src/shared/encryption/cache.ts"],"names":[],"mappings":";;;AAAA,+CAA0C;AAC1C,uCAA4C;AAQ5C,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAChC,MAAM,eAAe,GAAG,GAAG,CAAC;AAQ5B,IAAI,cAAc,GAAyB,EAAE,CAAC;AAC9C,MAAM,gBAAgB,GAAG,CAAC,cAAsB,EAAE,EAAE;IAClD,cAAc,CAAC,cAAc,MAA7B,cAAc,CAAC,cAAc,IAAM,IAAI,GAAG,EAAE,EAAC;IAC7C,OAAO,cAAc,CAAC,cAAc,CAAC,CAAC;AACxC,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,SAAgB,kBAAkB,CAChC,cAAsB,EACtB,IAAgB;IAEhB,MAAM,KAAK,GAAG,gBAAgB,CAAC,cAAc,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,IAAA,yBAAiB,EAAC,IAAI,CAAC,CAAC;IAC3C,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACxC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO;QACL,IAAI;QACJ,UAAU;QACV,GAAG,EAAE,SAAS;KACf,CAAC;AACJ,CAAC;AAhBD,gDAgBC;AAED;;;;;;GAMG;AACH,SAAgB,mCAAmC,CACjD,cAAsB;IAEtB,MAAM,KAAK,GAAG,gBAAgB,CAAC,cAAc,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,IAAA,yBAAiB,EAAC,uBAAW,CAAC,CAAC;IAClD,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAExC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO;QACL,IAAI,EAAE,uBAAW;QACjB,UAAU;QACV,GAAG,EAAE,SAAS;KACf,CAAC;AACJ,CAAC;AAhBD,kFAgBC;AAED;;;;;;;GAOG;AACH,SAAgB,YAAY,CAC1B,cAAsB,EACtB,IAAgB,EAChB,GAAe;IAEf,sBAAsB;IACtB,IAAI,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,MAAM,GAAG,mBAAmB,EAAE,CAAC;QAC7D,cAAc,GAAG,EAAE,CAAC;IACtB,CAAC;IAED,MAAM,KAAK,GAAG,gBAAgB,CAAC,cAAc,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,IAAA,yBAAiB,EAAC,IAAI,CAAC,CAAC;IAE3C,kBAAkB;IAClB,IAAI,KAAK,CAAC,IAAI,GAAG,eAAe,EAAE,CAAC;QACjC,KAAK,CAAC,KAAK,EAAE,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;AAC7B,CAAC;AAnBD,oCAmBC","sourcesContent":["import { SHARED_SALT } from './constants';\nimport { byteArrayToBase64 } from './utils';\n\ntype CachedEntry = {\n salt: Uint8Array;\n base64Salt: string;\n key: Uint8Array;\n};\n\nconst MAX_PASSWORD_CACHES = 100;\nconst MAX_SALT_CACHES = 100;\n\n/**\n * In-Memory Caching derived keys based from a given salt and password.\n */\ntype PasswordMemCachedKDF = {\n [hashedPassword: string]: Map<string, Uint8Array>;\n};\nlet inMemCachedKDF: PasswordMemCachedKDF = {};\nconst getPasswordCache = (hashedPassword: string) => {\n inMemCachedKDF[hashedPassword] ??= new Map();\n return inMemCachedKDF[hashedPassword];\n};\n\n/**\n * Returns a given cached derived key from a hashed password and salt\n *\n * @param hashedPassword - hashed password for cache lookup\n * @param salt - provide salt to receive cached key\n * @returns cached key\n */\nexport function getCachedKeyBySalt(\n hashedPassword: string,\n salt: Uint8Array,\n): CachedEntry | undefined {\n const cache = getPasswordCache(hashedPassword);\n const base64Salt = byteArrayToBase64(salt);\n const cachedKey = cache.get(base64Salt);\n if (!cachedKey) {\n return undefined;\n }\n\n return {\n salt,\n base64Salt,\n key: cachedKey,\n };\n}\n\n/**\n * Gets the cached key that was generated without a salt, if it exists.\n * This is unique per hashed password.\n *\n * @param hashedPassword - hashed password for cache lookup\n * @returns the cached key\n */\nexport function getCachedKeyGeneratedWithSharedSalt(\n hashedPassword: string,\n): CachedEntry | undefined {\n const cache = getPasswordCache(hashedPassword);\n const base64Salt = byteArrayToBase64(SHARED_SALT);\n const cachedKey = cache.get(base64Salt);\n\n if (!cachedKey) {\n return undefined;\n }\n\n return {\n salt: SHARED_SALT,\n base64Salt,\n key: cachedKey,\n };\n}\n\n/**\n * Sets a key to the in memory cache.\n * We have set an arbitrary size of 10 cached keys per hashed password.\n *\n * @param hashedPassword - hashed password for cache lookup\n * @param salt - salt to set new derived key\n * @param key - derived key we are setting\n */\nexport function setCachedKey(\n hashedPassword: string,\n salt: Uint8Array,\n key: Uint8Array,\n): void {\n // Max password caches\n if (Object.keys(inMemCachedKDF).length > MAX_PASSWORD_CACHES) {\n inMemCachedKDF = {};\n }\n\n const cache = getPasswordCache(hashedPassword);\n const base64Salt = byteArrayToBase64(salt);\n\n // Max salt caches\n if (cache.size > MAX_SALT_CACHES) {\n cache.clear();\n }\n\n cache.set(base64Salt, key);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"cache.mjs","sourceRoot":"","sources":["../../../src/shared/encryption/cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,wBAAuB;AAC7C,OAAO,EAAE,iBAAiB,EAAE,oBAAmB;AAQ/C,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAChC,MAAM,eAAe,GAAG,GAAG,CAAC;AAQ5B,IAAI,cAAc,GAAyB,EAAE,CAAC;AAC9C,MAAM,gBAAgB,GAAG,CAAC,cAAsB,EAAE,EAAE;IAClD,cAAc,CAAC,cAAc,MAA7B,cAAc,CAAC,cAAc,IAAM,IAAI,GAAG,EAAE,EAAC;IAC7C,OAAO,cAAc,CAAC,cAAc,CAAC,CAAC;AACxC,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAChC,cAAsB,EACtB,IAAgB;IAEhB,MAAM,KAAK,GAAG,gBAAgB,CAAC,cAAc,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAC3C,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACxC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO;QACL,IAAI;QACJ,UAAU;QACV,GAAG,EAAE,SAAS;KACf,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,mCAAmC,CACjD,cAAsB;IAEtB,MAAM,KAAK,GAAG,gBAAgB,CAAC,cAAc,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAClD,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAExC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO;QACL,IAAI,EAAE,WAAW;QACjB,UAAU;QACV,GAAG,EAAE,SAAS;KACf,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAC1B,cAAsB,EACtB,IAAgB,EAChB,GAAe;IAEf,sBAAsB;IACtB,IAAI,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,MAAM,GAAG,mBAAmB,EAAE,CAAC;QAC7D,cAAc,GAAG,EAAE,CAAC;IACtB,CAAC;IAED,MAAM,KAAK,GAAG,gBAAgB,CAAC,cAAc,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAE3C,kBAAkB;IAClB,IAAI,KAAK,CAAC,IAAI,GAAG,eAAe,EAAE,CAAC;QACjC,KAAK,CAAC,KAAK,EAAE,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;AAC7B,CAAC","sourcesContent":["import { SHARED_SALT } from './constants.js';\nimport { byteArrayToBase64 } from './utils.js';\n\ntype CachedEntry = {\n salt: Uint8Array;\n base64Salt: string;\n key: Uint8Array;\n};\n\nconst MAX_PASSWORD_CACHES = 100;\nconst MAX_SALT_CACHES = 100;\n\n/**\n * In-Memory Caching derived keys based from a given salt and password.\n */\ntype PasswordMemCachedKDF = {\n [hashedPassword: string]: Map<string, Uint8Array>;\n};\nlet inMemCachedKDF: PasswordMemCachedKDF = {};\nconst getPasswordCache = (hashedPassword: string) => {\n inMemCachedKDF[hashedPassword] ??= new Map();\n return inMemCachedKDF[hashedPassword];\n};\n\n/**\n * Returns a given cached derived key from a hashed password and salt\n *\n * @param hashedPassword - hashed password for cache lookup\n * @param salt - provide salt to receive cached key\n * @returns cached key\n */\nexport function getCachedKeyBySalt(\n hashedPassword: string,\n salt: Uint8Array,\n): CachedEntry | undefined {\n const cache = getPasswordCache(hashedPassword);\n const base64Salt = byteArrayToBase64(salt);\n const cachedKey = cache.get(base64Salt);\n if (!cachedKey) {\n return undefined;\n }\n\n return {\n salt,\n base64Salt,\n key: cachedKey,\n };\n}\n\n/**\n * Gets the cached key that was generated without a salt, if it exists.\n * This is unique per hashed password.\n *\n * @param hashedPassword - hashed password for cache lookup\n * @returns the cached key\n */\nexport function getCachedKeyGeneratedWithSharedSalt(\n hashedPassword: string,\n): CachedEntry | undefined {\n const cache = getPasswordCache(hashedPassword);\n const base64Salt = byteArrayToBase64(SHARED_SALT);\n const cachedKey = cache.get(base64Salt);\n\n if (!cachedKey) {\n return undefined;\n }\n\n return {\n salt: SHARED_SALT,\n base64Salt,\n key: cachedKey,\n };\n}\n\n/**\n * Sets a key to the in memory cache.\n * We have set an arbitrary size of 10 cached keys per hashed password.\n *\n * @param hashedPassword - hashed password for cache lookup\n * @param salt - salt to set new derived key\n * @param key - derived key we are setting\n */\nexport function setCachedKey(\n hashedPassword: string,\n salt: Uint8Array,\n key: Uint8Array,\n): void {\n // Max password caches\n if (Object.keys(inMemCachedKDF).length > MAX_PASSWORD_CACHES) {\n inMemCachedKDF = {};\n }\n\n const cache = getPasswordCache(hashedPassword);\n const base64Salt = byteArrayToBase64(salt);\n\n // Max salt caches\n if (cache.size > MAX_SALT_CACHES) {\n cache.clear();\n }\n\n cache.set(base64Salt, key);\n}\n"]}
1
+ {"version":3,"file":"cache.mjs","sourceRoot":"","sources":["../../../src/shared/encryption/cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,wBAAoB;AAC1C,OAAO,EAAE,iBAAiB,EAAE,oBAAgB;AAQ5C,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAChC,MAAM,eAAe,GAAG,GAAG,CAAC;AAQ5B,IAAI,cAAc,GAAyB,EAAE,CAAC;AAC9C,MAAM,gBAAgB,GAAG,CAAC,cAAsB,EAAE,EAAE;IAClD,cAAc,CAAC,cAAc,MAA7B,cAAc,CAAC,cAAc,IAAM,IAAI,GAAG,EAAE,EAAC;IAC7C,OAAO,cAAc,CAAC,cAAc,CAAC,CAAC;AACxC,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAChC,cAAsB,EACtB,IAAgB;IAEhB,MAAM,KAAK,GAAG,gBAAgB,CAAC,cAAc,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAC3C,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACxC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO;QACL,IAAI;QACJ,UAAU;QACV,GAAG,EAAE,SAAS;KACf,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,mCAAmC,CACjD,cAAsB;IAEtB,MAAM,KAAK,GAAG,gBAAgB,CAAC,cAAc,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAClD,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAExC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO;QACL,IAAI,EAAE,WAAW;QACjB,UAAU;QACV,GAAG,EAAE,SAAS;KACf,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAC1B,cAAsB,EACtB,IAAgB,EAChB,GAAe;IAEf,sBAAsB;IACtB,IAAI,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,MAAM,GAAG,mBAAmB,EAAE,CAAC;QAC7D,cAAc,GAAG,EAAE,CAAC;IACtB,CAAC;IAED,MAAM,KAAK,GAAG,gBAAgB,CAAC,cAAc,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAE3C,kBAAkB;IAClB,IAAI,KAAK,CAAC,IAAI,GAAG,eAAe,EAAE,CAAC;QACjC,KAAK,CAAC,KAAK,EAAE,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;AAC7B,CAAC","sourcesContent":["import { SHARED_SALT } from './constants';\nimport { byteArrayToBase64 } from './utils';\n\ntype CachedEntry = {\n salt: Uint8Array;\n base64Salt: string;\n key: Uint8Array;\n};\n\nconst MAX_PASSWORD_CACHES = 100;\nconst MAX_SALT_CACHES = 100;\n\n/**\n * In-Memory Caching derived keys based from a given salt and password.\n */\ntype PasswordMemCachedKDF = {\n [hashedPassword: string]: Map<string, Uint8Array>;\n};\nlet inMemCachedKDF: PasswordMemCachedKDF = {};\nconst getPasswordCache = (hashedPassword: string) => {\n inMemCachedKDF[hashedPassword] ??= new Map();\n return inMemCachedKDF[hashedPassword];\n};\n\n/**\n * Returns a given cached derived key from a hashed password and salt\n *\n * @param hashedPassword - hashed password for cache lookup\n * @param salt - provide salt to receive cached key\n * @returns cached key\n */\nexport function getCachedKeyBySalt(\n hashedPassword: string,\n salt: Uint8Array,\n): CachedEntry | undefined {\n const cache = getPasswordCache(hashedPassword);\n const base64Salt = byteArrayToBase64(salt);\n const cachedKey = cache.get(base64Salt);\n if (!cachedKey) {\n return undefined;\n }\n\n return {\n salt,\n base64Salt,\n key: cachedKey,\n };\n}\n\n/**\n * Gets the cached key that was generated without a salt, if it exists.\n * This is unique per hashed password.\n *\n * @param hashedPassword - hashed password for cache lookup\n * @returns the cached key\n */\nexport function getCachedKeyGeneratedWithSharedSalt(\n hashedPassword: string,\n): CachedEntry | undefined {\n const cache = getPasswordCache(hashedPassword);\n const base64Salt = byteArrayToBase64(SHARED_SALT);\n const cachedKey = cache.get(base64Salt);\n\n if (!cachedKey) {\n return undefined;\n }\n\n return {\n salt: SHARED_SALT,\n base64Salt,\n key: cachedKey,\n };\n}\n\n/**\n * Sets a key to the in memory cache.\n * We have set an arbitrary size of 10 cached keys per hashed password.\n *\n * @param hashedPassword - hashed password for cache lookup\n * @param salt - salt to set new derived key\n * @param key - derived key we are setting\n */\nexport function setCachedKey(\n hashedPassword: string,\n salt: Uint8Array,\n key: Uint8Array,\n): void {\n // Max password caches\n if (Object.keys(inMemCachedKDF).length > MAX_PASSWORD_CACHES) {\n inMemCachedKDF = {};\n }\n\n const cache = getPasswordCache(hashedPassword);\n const base64Salt = byteArrayToBase64(salt);\n\n // Max salt caches\n if (cache.size > MAX_SALT_CACHES) {\n cache.clear();\n }\n\n cache.set(base64Salt, key);\n}\n"]}
@@ -12,9 +12,9 @@ const webcrypto_1 = require("@noble/ciphers/webcrypto");
12
12
  const scrypt_1 = require("@noble/hashes/scrypt");
13
13
  const sha256_1 = require("@noble/hashes/sha256");
14
14
  const utils_1 = require("@noble/hashes/utils");
15
- const cache_js_1 = require("./cache.cjs");
16
- const constants_js_1 = require("./constants.cjs");
17
- const utils_js_1 = require("./utils.cjs");
15
+ const cache_1 = require("./cache.cjs");
16
+ const constants_1 = require("./constants.cjs");
17
+ const utils_2 = require("./utils.cjs");
18
18
  class EncryptorDecryptor {
19
19
  constructor() {
20
20
  _EncryptorDecryptor_instances.add(this);
@@ -52,7 +52,7 @@ class EncryptorDecryptor {
52
52
  if (encryptedData.t === 'scrypt') {
53
53
  const { d: base64CiphertextAndNonceAndSalt, saltLen } = encryptedData;
54
54
  // Decode the base64.
55
- const ciphertextAndNonceAndSalt = (0, utils_js_1.base64ToByteArray)(base64CiphertextAndNonceAndSalt);
55
+ const ciphertextAndNonceAndSalt = (0, utils_2.base64ToByteArray)(base64CiphertextAndNonceAndSalt);
56
56
  // Create buffers of salt and ciphertextAndNonce.
57
57
  const salt = ciphertextAndNonceAndSalt.slice(0, saltLen);
58
58
  return salt;
@@ -82,33 +82,33 @@ class EncryptorDecryptor {
82
82
  }
83
83
  _EncryptorDecryptor_kdfPromiseCache = new WeakMap(), _EncryptorDecryptor_instances = new WeakSet(), _EncryptorDecryptor_encryptStringV1 = async function _EncryptorDecryptor_encryptStringV1(plaintext, password, nativeScryptCrypto) {
84
84
  const { key, salt } = await __classPrivateFieldGet(this, _EncryptorDecryptor_instances, "m", _EncryptorDecryptor_getOrGenerateScryptKey).call(this, password, {
85
- N: constants_js_1.SCRYPT_N,
86
- r: constants_js_1.SCRYPT_r,
87
- p: constants_js_1.SCRYPT_p,
88
- dkLen: constants_js_1.ALGORITHM_KEY_SIZE,
85
+ N: constants_1.SCRYPT_N,
86
+ r: constants_1.SCRYPT_r,
87
+ p: constants_1.SCRYPT_p,
88
+ dkLen: constants_1.ALGORITHM_KEY_SIZE,
89
89
  }, undefined, nativeScryptCrypto);
90
90
  // Encrypt and prepend salt.
91
91
  const plaintextRaw = (0, utils_1.utf8ToBytes)(plaintext);
92
92
  const ciphertextAndNonceAndSalt = (0, utils_1.concatBytes)(salt, __classPrivateFieldGet(this, _EncryptorDecryptor_instances, "m", _EncryptorDecryptor_encrypt).call(this, plaintextRaw, key));
93
93
  // Convert to Base64
94
- const encryptedData = (0, utils_js_1.byteArrayToBase64)(ciphertextAndNonceAndSalt);
94
+ const encryptedData = (0, utils_2.byteArrayToBase64)(ciphertextAndNonceAndSalt);
95
95
  const encryptedPayload = {
96
96
  v: '1',
97
97
  t: 'scrypt',
98
98
  d: encryptedData,
99
99
  o: {
100
- N: constants_js_1.SCRYPT_N,
101
- r: constants_js_1.SCRYPT_r,
102
- p: constants_js_1.SCRYPT_p,
103
- dkLen: constants_js_1.ALGORITHM_KEY_SIZE,
100
+ N: constants_1.SCRYPT_N,
101
+ r: constants_1.SCRYPT_r,
102
+ p: constants_1.SCRYPT_p,
103
+ dkLen: constants_1.ALGORITHM_KEY_SIZE,
104
104
  },
105
- saltLen: constants_js_1.SCRYPT_SALT_SIZE,
105
+ saltLen: constants_1.SCRYPT_SALT_SIZE,
106
106
  };
107
107
  return JSON.stringify(encryptedPayload);
108
108
  }, _EncryptorDecryptor_decryptStringV1 = async function _EncryptorDecryptor_decryptStringV1(data, password, nativeScryptCrypto) {
109
109
  const { o, d: base64CiphertextAndNonceAndSalt, saltLen } = data;
110
110
  // Decode the base64.
111
- const ciphertextAndNonceAndSalt = (0, utils_js_1.base64ToByteArray)(base64CiphertextAndNonceAndSalt);
111
+ const ciphertextAndNonceAndSalt = (0, utils_2.base64ToByteArray)(base64CiphertextAndNonceAndSalt);
112
112
  // Create buffers of salt and ciphertextAndNonce.
113
113
  const salt = ciphertextAndNonceAndSalt.slice(0, saltLen);
114
114
  const ciphertextAndNonce = ciphertextAndNonceAndSalt.slice(saltLen, ciphertextAndNonceAndSalt.length);
@@ -120,24 +120,24 @@ _EncryptorDecryptor_kdfPromiseCache = new WeakMap(), _EncryptorDecryptor_instanc
120
120
  dkLen: o.dkLen,
121
121
  }, salt, nativeScryptCrypto);
122
122
  // Decrypt and return result.
123
- return (0, utils_js_1.bytesToUtf8)(__classPrivateFieldGet(this, _EncryptorDecryptor_instances, "m", _EncryptorDecryptor_decrypt).call(this, ciphertextAndNonce, key));
123
+ return (0, utils_2.bytesToUtf8)(__classPrivateFieldGet(this, _EncryptorDecryptor_instances, "m", _EncryptorDecryptor_decrypt).call(this, ciphertextAndNonce, key));
124
124
  }, _EncryptorDecryptor_encrypt = function _EncryptorDecryptor_encrypt(plaintext, key) {
125
- const nonce = (0, webcrypto_1.randomBytes)(constants_js_1.ALGORITHM_NONCE_SIZE);
125
+ const nonce = (0, webcrypto_1.randomBytes)(constants_1.ALGORITHM_NONCE_SIZE);
126
126
  // Encrypt and prepend nonce.
127
127
  const ciphertext = (0, aes_1.gcm)(key, nonce).encrypt(plaintext);
128
128
  return (0, utils_1.concatBytes)(nonce, ciphertext);
129
129
  }, _EncryptorDecryptor_decrypt = function _EncryptorDecryptor_decrypt(ciphertextAndNonce, key) {
130
130
  // Create buffers of nonce and ciphertext.
131
- const nonce = ciphertextAndNonce.slice(0, constants_js_1.ALGORITHM_NONCE_SIZE);
132
- const ciphertext = ciphertextAndNonce.slice(constants_js_1.ALGORITHM_NONCE_SIZE, ciphertextAndNonce.length);
131
+ const nonce = ciphertextAndNonce.slice(0, constants_1.ALGORITHM_NONCE_SIZE);
132
+ const ciphertext = ciphertextAndNonce.slice(constants_1.ALGORITHM_NONCE_SIZE, ciphertextAndNonce.length);
133
133
  // Decrypt and return result.
134
134
  return (0, aes_1.gcm)(key, nonce).decrypt(ciphertext);
135
135
  }, _EncryptorDecryptor_getOrGenerateScryptKey = async function _EncryptorDecryptor_getOrGenerateScryptKey(password, o, salt, nativeScryptCrypto) {
136
136
  const hashedPassword = createSHA256Hash(password);
137
137
  // Check if we already have the key cached
138
138
  const cachedKey = salt
139
- ? (0, cache_js_1.getCachedKeyBySalt)(hashedPassword, salt)
140
- : (0, cache_js_1.getCachedKeyGeneratedWithSharedSalt)(hashedPassword);
139
+ ? (0, cache_1.getCachedKeyBySalt)(hashedPassword, salt)
140
+ : (0, cache_1.getCachedKeyGeneratedWithSharedSalt)(hashedPassword);
141
141
  if (cachedKey) {
142
142
  return {
143
143
  key: cachedKey.key,
@@ -145,7 +145,7 @@ _EncryptorDecryptor_kdfPromiseCache = new WeakMap(), _EncryptorDecryptor_instanc
145
145
  };
146
146
  }
147
147
  // Create a unique cache key for this KDF operation
148
- const newSalt = salt ?? constants_js_1.SHARED_SALT;
148
+ const newSalt = salt ?? constants_1.SHARED_SALT;
149
149
  const cacheKey = __classPrivateFieldGet(this, _EncryptorDecryptor_instances, "m", _EncryptorDecryptor_createKdfCacheKey).call(this, hashedPassword, o, newSalt, nativeScryptCrypto);
150
150
  // Check if there's already an ongoing KDF operation with the same parameters
151
151
  const existingPromise = __classPrivateFieldGet(this, _EncryptorDecryptor_kdfPromiseCache, "f").get(cacheKey);
@@ -153,7 +153,7 @@ _EncryptorDecryptor_kdfPromiseCache = new WeakMap(), _EncryptorDecryptor_instanc
153
153
  return existingPromise;
154
154
  }
155
155
  // Limit cache size to prevent unbounded growth
156
- if (__classPrivateFieldGet(this, _EncryptorDecryptor_kdfPromiseCache, "f").size >= constants_js_1.MAX_KDF_PROMISE_CACHE_SIZE) {
156
+ if (__classPrivateFieldGet(this, _EncryptorDecryptor_kdfPromiseCache, "f").size >= constants_1.MAX_KDF_PROMISE_CACHE_SIZE) {
157
157
  // Remove the oldest entry (first inserted)
158
158
  const firstKey = __classPrivateFieldGet(this, _EncryptorDecryptor_kdfPromiseCache, "f").keys().next().value;
159
159
  if (firstKey) {
@@ -171,13 +171,13 @@ _EncryptorDecryptor_kdfPromiseCache = new WeakMap(), _EncryptorDecryptor_instanc
171
171
  });
172
172
  return kdfPromise;
173
173
  }, _EncryptorDecryptor_createKdfCacheKey = function _EncryptorDecryptor_createKdfCacheKey(hashedPassword, o, salt, nativeScryptCrypto) {
174
- const saltStr = (0, utils_js_1.byteArrayToBase64)(salt);
174
+ const saltStr = (0, utils_2.byteArrayToBase64)(salt);
175
175
  const hasNative = Boolean(nativeScryptCrypto);
176
176
  return `${hashedPassword}:${o.N}:${o.r}:${o.p}:${o.dkLen}:${saltStr}:${hasNative}`;
177
177
  }, _EncryptorDecryptor_performKdfOperation = async function _EncryptorDecryptor_performKdfOperation(password, o, salt, hashedPassword, nativeScryptCrypto) {
178
178
  let newKey;
179
179
  if (nativeScryptCrypto) {
180
- newKey = await nativeScryptCrypto((0, utils_js_1.stringToByteArray)(password), salt, o.N, o.r, o.p, o.dkLen);
180
+ newKey = await nativeScryptCrypto((0, utils_2.stringToByteArray)(password), salt, o.N, o.r, o.p, o.dkLen);
181
181
  }
182
182
  else {
183
183
  newKey = await (0, scrypt_1.scryptAsync)(password, salt, {
@@ -187,7 +187,7 @@ _EncryptorDecryptor_kdfPromiseCache = new WeakMap(), _EncryptorDecryptor_instanc
187
187
  dkLen: o.dkLen,
188
188
  });
189
189
  }
190
- (0, cache_js_1.setCachedKey)(hashedPassword, salt, newKey);
190
+ (0, cache_1.setCachedKey)(hashedPassword, salt, newKey);
191
191
  return {
192
192
  key: newKey,
193
193
  salt,
@@ -1 +1 @@
1
- {"version":3,"file":"encryption.cjs","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.js';\nimport {\n getCachedKeyBySalt,\n getCachedKeyGeneratedWithSharedSalt,\n setCachedKey,\n} from './cache.js';\nimport {\n ALGORITHM_KEY_SIZE,\n ALGORITHM_NONCE_SIZE,\n MAX_KDF_PROMISE_CACHE_SIZE,\n SCRYPT_N,\n SCRYPT_p,\n SCRYPT_r,\n SCRYPT_SALT_SIZE,\n SHARED_SALT,\n} from './constants.js';\nimport {\n base64ToByteArray,\n byteArrayToBase64,\n bytesToUtf8,\n stringToByteArray,\n} from './utils.js';\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 N: number;\n r: number;\n p: number;\n dkLen: number;\n };\n\n // Salt options\n saltLen: number;\n};\n\nclass EncryptorDecryptor {\n // Promise cache for ongoing KDF operations to prevent duplicate work\n readonly #kdfPromiseCache = new Map<\n string,\n Promise<{ key: Uint8Array; salt: Uint8Array }>\n >();\n\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\n // Check if we already have the key cached\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 // Create a unique cache key for this KDF operation\n const newSalt = salt ?? SHARED_SALT;\n const cacheKey = this.#createKdfCacheKey(\n hashedPassword,\n o,\n newSalt,\n nativeScryptCrypto,\n );\n\n // Check if there's already an ongoing KDF operation with the same parameters\n const existingPromise = this.#kdfPromiseCache.get(cacheKey);\n if (existingPromise) {\n return existingPromise;\n }\n\n // Limit cache size to prevent unbounded growth\n if (this.#kdfPromiseCache.size >= MAX_KDF_PROMISE_CACHE_SIZE) {\n // Remove the oldest entry (first inserted)\n const firstKey = this.#kdfPromiseCache.keys().next().value;\n if (firstKey) {\n this.#kdfPromiseCache.delete(firstKey);\n }\n }\n\n // Create and cache the promise for the KDF operation\n const kdfPromise = this.#performKdfOperation(\n password,\n o,\n newSalt,\n hashedPassword,\n nativeScryptCrypto,\n );\n\n // Cache the promise and set up cleanup\n this.#kdfPromiseCache.set(cacheKey, kdfPromise);\n\n // Clean up the cache after completion (both success and failure)\n // eslint-disable-next-line no-void\n void kdfPromise.finally(() => {\n this.#kdfPromiseCache.delete(cacheKey);\n });\n\n return kdfPromise;\n }\n\n #createKdfCacheKey(\n hashedPassword: string,\n o: EncryptedPayload['o'],\n salt: Uint8Array,\n nativeScryptCrypto?: NativeScrypt,\n ): string {\n const saltStr = byteArrayToBase64(salt);\n const hasNative = Boolean(nativeScryptCrypto);\n return `${hashedPassword}:${o.N}:${o.r}:${o.p}:${o.dkLen}:${saltStr}:${hasNative}`;\n }\n\n async #performKdfOperation(\n password: string,\n o: EncryptedPayload['o'],\n salt: Uint8Array,\n hashedPassword: string,\n nativeScryptCrypto?: NativeScrypt,\n ): Promise<{ key: Uint8Array; salt: Uint8Array }> {\n let newKey: Uint8Array;\n\n if (nativeScryptCrypto) {\n newKey = await nativeScryptCrypto(\n stringToByteArray(password),\n salt,\n o.N,\n o.r,\n o.p,\n o.dkLen,\n );\n } else {\n newKey = await scryptAsync(password, salt, {\n N: o.N,\n r: o.r,\n p: o.p,\n dkLen: o.dkLen,\n });\n }\n\n setCachedKey(hashedPassword, salt, newKey);\n\n return {\n key: newKey,\n salt,\n };\n }\n}\n\nconst encryption = new EncryptorDecryptor();\nexport default encryption;\n\n/**\n * Receive a SHA256 hash from a given string\n *\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.cjs","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 MAX_KDF_PROMISE_CACHE_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 N: number;\n r: number;\n p: number;\n dkLen: number;\n };\n\n // Salt options\n saltLen: number;\n};\n\nclass EncryptorDecryptor {\n // Promise cache for ongoing KDF operations to prevent duplicate work\n readonly #kdfPromiseCache = new Map<\n string,\n Promise<{ key: Uint8Array; salt: Uint8Array }>\n >();\n\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\n // Check if we already have the key cached\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 // Create a unique cache key for this KDF operation\n const newSalt = salt ?? SHARED_SALT;\n const cacheKey = this.#createKdfCacheKey(\n hashedPassword,\n o,\n newSalt,\n nativeScryptCrypto,\n );\n\n // Check if there's already an ongoing KDF operation with the same parameters\n const existingPromise = this.#kdfPromiseCache.get(cacheKey);\n if (existingPromise) {\n return existingPromise;\n }\n\n // Limit cache size to prevent unbounded growth\n if (this.#kdfPromiseCache.size >= MAX_KDF_PROMISE_CACHE_SIZE) {\n // Remove the oldest entry (first inserted)\n const firstKey = this.#kdfPromiseCache.keys().next().value;\n if (firstKey) {\n this.#kdfPromiseCache.delete(firstKey);\n }\n }\n\n // Create and cache the promise for the KDF operation\n const kdfPromise = this.#performKdfOperation(\n password,\n o,\n newSalt,\n hashedPassword,\n nativeScryptCrypto,\n );\n\n // Cache the promise and set up cleanup\n this.#kdfPromiseCache.set(cacheKey, kdfPromise);\n\n // Clean up the cache after completion (both success and failure)\n // eslint-disable-next-line no-void\n void kdfPromise.finally(() => {\n this.#kdfPromiseCache.delete(cacheKey);\n });\n\n return kdfPromise;\n }\n\n #createKdfCacheKey(\n hashedPassword: string,\n o: EncryptedPayload['o'],\n salt: Uint8Array,\n nativeScryptCrypto?: NativeScrypt,\n ): string {\n const saltStr = byteArrayToBase64(salt);\n const hasNative = Boolean(nativeScryptCrypto);\n return `${hashedPassword}:${o.N}:${o.r}:${o.p}:${o.dkLen}:${saltStr}:${hasNative}`;\n }\n\n async #performKdfOperation(\n password: string,\n o: EncryptedPayload['o'],\n salt: Uint8Array,\n hashedPassword: string,\n nativeScryptCrypto?: NativeScrypt,\n ): Promise<{ key: Uint8Array; salt: Uint8Array }> {\n let newKey: Uint8Array;\n\n if (nativeScryptCrypto) {\n newKey = await nativeScryptCrypto(\n stringToByteArray(password),\n salt,\n o.N,\n o.r,\n o.p,\n o.dkLen,\n );\n } else {\n newKey = await scryptAsync(password, salt, {\n N: o.N,\n r: o.r,\n p: o.p,\n dkLen: o.dkLen,\n });\n }\n\n setCachedKey(hashedPassword, salt, newKey);\n\n return {\n key: newKey,\n salt,\n };\n }\n}\n\nconst encryption = new EncryptorDecryptor();\nexport default encryption;\n\n/**\n * Receive a SHA256 hash from a given string\n *\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 +1 @@
1
- {"version":3,"file":"encryption.d.cts","sourceRoot":"","sources":["../../../src/shared/encryption/encryption.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,gCAA+B;AAuB3D,MAAM,MAAM,gBAAgB,GAAG;IAE7B,CAAC,EAAE,GAAG,CAAC;IAGP,CAAC,EAAE,QAAQ,CAAC;IAGZ,CAAC,EAAE,MAAM,CAAC;IAGV,CAAC,EAAE;QACD,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;;IAOhB,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;CAkJ3D;AAED,QAAA,MAAM,UAAU,oBAA2B,CAAC;AAC5C,eAAe,UAAU,CAAC;AAE1B;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGrD"}
1
+ {"version":3,"file":"encryption.d.cts","sourceRoot":"","sources":["../../../src/shared/encryption/encryption.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,gCAA4B;AAuBxD,MAAM,MAAM,gBAAgB,GAAG;IAE7B,CAAC,EAAE,GAAG,CAAC;IAGP,CAAC,EAAE,QAAQ,CAAC;IAGZ,CAAC,EAAE,MAAM,CAAC;IAGV,CAAC,EAAE;QACD,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;;IAOhB,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;CAkJ3D;AAED,QAAA,MAAM,UAAU,oBAA2B,CAAC;AAC5C,eAAe,UAAU,CAAC;AAE1B;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGrD"}
@@ -1 +1 @@
1
- {"version":3,"file":"encryption.d.mts","sourceRoot":"","sources":["../../../src/shared/encryption/encryption.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,gCAA+B;AAuB3D,MAAM,MAAM,gBAAgB,GAAG;IAE7B,CAAC,EAAE,GAAG,CAAC;IAGP,CAAC,EAAE,QAAQ,CAAC;IAGZ,CAAC,EAAE,MAAM,CAAC;IAGV,CAAC,EAAE;QACD,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;;IAOhB,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;CAkJ3D;AAED,QAAA,MAAM,UAAU,oBAA2B,CAAC;AAC5C,eAAe,UAAU,CAAC;AAE1B;;;;;GAKG;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;AAuBxD,MAAM,MAAM,gBAAgB,GAAG;IAE7B,CAAC,EAAE,GAAG,CAAC;IAGP,CAAC,EAAE,QAAQ,CAAC;IAGZ,CAAC,EAAE,MAAM,CAAC;IAGV,CAAC,EAAE;QACD,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;;IAOhB,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;CAkJ3D;AAED,QAAA,MAAM,UAAU,oBAA2B,CAAC;AAC5C,eAAe,UAAU,CAAC;AAE1B;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGrD"}