From 7452189eec2d136603eda7a850e25e466f3e36d2 Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Wed, 30 Sep 2026 15:12:34 +0200 Subject: [PATCH 01/12] chore(profile-sync-controller): Replace JS AES implementation with cryptography package --- jest.config.packages.cjs | 3 ++ packages/profile-sync-controller/package.json | 2 +- .../src/shared/encryption/constants.ts | 2 -- .../src/shared/encryption/encryption.test.ts | 4 +-- .../src/shared/encryption/encryption.ts | 29 ++++++++----------- .../tsconfig.build.json | 3 ++ .../profile-sync-controller/tsconfig.json | 3 ++ .../tsconfig.lint.json | 5 +++- yarn.lock | 4 +-- 9 files changed, 30 insertions(+), 25 deletions(-) diff --git a/jest.config.packages.cjs b/jest.config.packages.cjs index a96314934e2..125c04f03dd 100644 --- a/jest.config.packages.cjs +++ b/jest.config.packages.cjs @@ -87,6 +87,9 @@ module.exports = { '/../json-rpc-engine/src/v2/index.ts', ], '^@metamask/utils/node$': ['/../utils/src/node.ts'], + '^@metamask/cryptography/(.+)$': [ + '/../cryptography/src/$1', + ], '^@metamask/(.+)$': [ '/../$1/src', // Some @metamask/* packages we are referencing aren't in this monorepo, diff --git a/packages/profile-sync-controller/package.json b/packages/profile-sync-controller/package.json index 15d40b690da..f024f8f379d 100644 --- a/packages/profile-sync-controller/package.json +++ b/packages/profile-sync-controller/package.json @@ -76,13 +76,13 @@ "@metamask/address-book-controller": "^8.0.0", "@metamask/base-controller": "^10.0.0", "@metamask/controller-utils": "^13.0.0", + "@metamask/cryptography": "^1.0.0", "@metamask/key-tree": "^10.1.1", "@metamask/keyring-controller": "^28.1.0", "@metamask/messenger": "^3.0.0", "@metamask/seedless-onboarding-controller": "^11.0.1", "@metamask/superstruct": "^3.4.1", "@metamask/utils": "^12.0.0", - "@noble/ciphers": "^1.3.0", "@noble/curves": "^1.9.2", "@noble/hashes": "^1.8.0", "@signinwithethereum/siwe": "^4.2.1", diff --git a/packages/profile-sync-controller/src/shared/encryption/constants.ts b/packages/profile-sync-controller/src/shared/encryption/constants.ts index 6539a63ebeb..3e205becad2 100644 --- a/packages/profile-sync-controller/src/shared/encryption/constants.ts +++ b/packages/profile-sync-controller/src/shared/encryption/constants.ts @@ -1,5 +1,3 @@ -// Nonce/Key Sizes -export const ALGORITHM_NONCE_SIZE = 12; // 12 bytes export const ALGORITHM_KEY_SIZE = 16; // 16 bytes // Scrypt settings diff --git a/packages/profile-sync-controller/src/shared/encryption/encryption.test.ts b/packages/profile-sync-controller/src/shared/encryption/encryption.test.ts index e83dd937c93..6ab27cbb93b 100644 --- a/packages/profile-sync-controller/src/shared/encryption/encryption.test.ts +++ b/packages/profile-sync-controller/src/shared/encryption/encryption.test.ts @@ -203,12 +203,12 @@ describe('encryption tests', () => { await expect( encryption.decryptString(results[0], password2), ).rejects.toThrow( - 'Unable to decrypt string - aes/gcm: invalid ghash tag', + 'Unable to decrypt string - The operation failed for an operation-specific reason', ); await expect( encryption.decryptString(results[1], password1), ).rejects.toThrow( - 'Unable to decrypt string - aes/gcm: invalid ghash tag', + 'Unable to decrypt string - The operation failed for an operation-specific reason', ); }); diff --git a/packages/profile-sync-controller/src/shared/encryption/encryption.ts b/packages/profile-sync-controller/src/shared/encryption/encryption.ts index d0f38fc7e6b..65d89f36519 100644 --- a/packages/profile-sync-controller/src/shared/encryption/encryption.ts +++ b/packages/profile-sync-controller/src/shared/encryption/encryption.ts @@ -1,8 +1,8 @@ -import { gcm } from '@noble/ciphers/aes'; -import { randomBytes } from '@noble/ciphers/webcrypto'; import { scryptAsync } from '@noble/hashes/scrypt'; import { sha256 } from '@noble/hashes/sha256'; import { utf8ToBytes, concatBytes, bytesToHex } from '@noble/hashes/utils'; +import { decrypt, encrypt } from '@metamask/cryptography/aes-gcm'; +import { getErrorMessage } from '@metamask/utils'; import type { NativeScrypt } from '../types/encryption.js'; import { @@ -68,8 +68,7 @@ class EncryptorDecryptor { nativeScryptCrypto, ); } catch (e) { - const errorMessage = e instanceof Error ? e.message : JSON.stringify(e); - throw new Error(`Unable to encrypt string - ${errorMessage}`); + throw new Error(`Unable to encrypt string - ${getErrorMessage(e)}`); } } @@ -93,8 +92,7 @@ class EncryptorDecryptor { `Unsupported encrypted data payload - ${encryptedDataStr}`, ); } catch (e) { - const errorMessage = e instanceof Error ? e.message : JSON.stringify(e); - throw new Error(`Unable to decrypt string - ${errorMessage}`); + throw new Error(`Unable to decrypt string - ${getErrorMessage(e)}`); } } @@ -119,7 +117,7 @@ class EncryptorDecryptor { const plaintextRaw = utf8ToBytes(plaintext); const ciphertextAndNonceAndSalt = concatBytes( salt, - this.#encrypt(plaintextRaw, key), + await this.#encrypt(plaintextRaw, key), ); // Convert to Base64 @@ -174,7 +172,7 @@ class EncryptorDecryptor { ); // Decrypt and return result. - return bytesToUtf8(this.#decrypt(ciphertextAndNonce, key)); + return bytesToUtf8(await this.#decrypt(ciphertextAndNonce, key)); } getSalt(encryptedDataStr: string) { @@ -198,8 +196,7 @@ class EncryptorDecryptor { `Unsupported encrypted data payload - ${encryptedDataStr}`, ); } catch (e) { - const errorMessage = e instanceof Error ? e.message : JSON.stringify(e); - throw new Error(`Unable to get salt - ${errorMessage}`); + throw new Error(`Unable to get salt - ${getErrorMessage(e)}`); } } @@ -218,16 +215,14 @@ class EncryptorDecryptor { return strSet.size === salts.length; } - #encrypt(plaintext: Uint8Array, key: Uint8Array): Uint8Array { - const nonce = randomBytes(ALGORITHM_NONCE_SIZE); - + async #encrypt(plaintext: Uint8Array, key: Uint8Array): Promise { // Encrypt and prepend nonce. - const ciphertext = gcm(key, nonce).encrypt(plaintext); + const { ciphertext, iv } = await encrypt(key, plaintext); - return concatBytes(nonce, ciphertext); + return concatBytes(iv, ciphertext); } - #decrypt(ciphertextAndNonce: Uint8Array, key: Uint8Array): Uint8Array { + async #decrypt(ciphertextAndNonce: Uint8Array, key: Uint8Array): Promise { // Create buffers of nonce and ciphertext. const nonce = ciphertextAndNonce.slice(0, ALGORITHM_NONCE_SIZE); const ciphertext = ciphertextAndNonce.slice( @@ -236,7 +231,7 @@ class EncryptorDecryptor { ); // Decrypt and return result. - return gcm(key, nonce).decrypt(ciphertext); + return decrypt(key, nonce, ciphertext); } async #getOrGenerateScryptKey( diff --git a/packages/profile-sync-controller/tsconfig.build.json b/packages/profile-sync-controller/tsconfig.build.json index 220af8e2b65..9e8726b42af 100644 --- a/packages/profile-sync-controller/tsconfig.build.json +++ b/packages/profile-sync-controller/tsconfig.build.json @@ -9,6 +9,9 @@ { "path": "../base-controller/tsconfig.build.json" }, + { + "path": "../cryptography/tsconfig.build.json" + }, { "path": "../keyring-controller/tsconfig.build.json" }, diff --git a/packages/profile-sync-controller/tsconfig.json b/packages/profile-sync-controller/tsconfig.json index 6542f7e1bf9..6d54bbacab5 100644 --- a/packages/profile-sync-controller/tsconfig.json +++ b/packages/profile-sync-controller/tsconfig.json @@ -4,6 +4,9 @@ { "path": "../base-controller" }, + { + "path": "../cryptography/" + }, { "path": "../controller-utils" }, diff --git a/packages/profile-sync-controller/tsconfig.lint.json b/packages/profile-sync-controller/tsconfig.lint.json index 0a9b3c044c2..3061f6bef02 100644 --- a/packages/profile-sync-controller/tsconfig.lint.json +++ b/packages/profile-sync-controller/tsconfig.lint.json @@ -25,6 +25,9 @@ }, { "path": "../controller-utils/tsconfig.lint.json" - } + }, + { + "path": "../cryptography/tsconfig.lint.json" + }, ] } diff --git a/yarn.lock b/yarn.lock index d51a47c81cf..8581f9ee6e4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6396,7 +6396,7 @@ __metadata: languageName: node linkType: hard -"@metamask/cryptography@workspace:packages/cryptography": +"@metamask/cryptography@npm:^1.0.0, @metamask/cryptography@workspace:packages/cryptography": version: 0.0.0-use.local resolution: "@metamask/cryptography@workspace:packages/cryptography" dependencies: @@ -8291,6 +8291,7 @@ __metadata: "@metamask/auto-changelog": "npm:^6.2.1" "@metamask/base-controller": "npm:^10.0.0" "@metamask/controller-utils": "npm:^13.0.0" + "@metamask/cryptography": "npm:^1.0.0" "@metamask/eth-hd-keyring": "npm:^15.0.0" "@metamask/key-tree": "npm:^10.1.1" "@metamask/keyring-api": "npm:^24.0.0" @@ -8302,7 +8303,6 @@ __metadata: "@metamask/seedless-onboarding-controller": "npm:^11.0.1" "@metamask/superstruct": "npm:^3.4.1" "@metamask/utils": "npm:^12.0.0" - "@noble/ciphers": "npm:^1.3.0" "@noble/curves": "npm:^1.9.2" "@noble/hashes": "npm:^1.8.0" "@signinwithethereum/siwe": "npm:^4.2.1" From fe4ce64ed766dad56976589e8a93fb93e4fc4aaa Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Wed, 30 Sep 2026 15:12:54 +0200 Subject: [PATCH 02/12] Fix lint --- jest.config.packages.cjs | 4 +--- .../src/shared/encryption/encryption.ts | 9 ++++++--- packages/profile-sync-controller/tsconfig.lint.json | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/jest.config.packages.cjs b/jest.config.packages.cjs index 125c04f03dd..b65ce04b056 100644 --- a/jest.config.packages.cjs +++ b/jest.config.packages.cjs @@ -87,9 +87,7 @@ module.exports = { '/../json-rpc-engine/src/v2/index.ts', ], '^@metamask/utils/node$': ['/../utils/src/node.ts'], - '^@metamask/cryptography/(.+)$': [ - '/../cryptography/src/$1', - ], + '^@metamask/cryptography/(.+)$': ['/../cryptography/src/$1'], '^@metamask/(.+)$': [ '/../$1/src', // Some @metamask/* packages we are referencing aren't in this monorepo, diff --git a/packages/profile-sync-controller/src/shared/encryption/encryption.ts b/packages/profile-sync-controller/src/shared/encryption/encryption.ts index 65d89f36519..8b446ce534e 100644 --- a/packages/profile-sync-controller/src/shared/encryption/encryption.ts +++ b/packages/profile-sync-controller/src/shared/encryption/encryption.ts @@ -1,8 +1,8 @@ +import { decrypt, encrypt } from '@metamask/cryptography/aes-gcm'; +import { getErrorMessage } from '@metamask/utils'; import { scryptAsync } from '@noble/hashes/scrypt'; import { sha256 } from '@noble/hashes/sha256'; import { utf8ToBytes, concatBytes, bytesToHex } from '@noble/hashes/utils'; -import { decrypt, encrypt } from '@metamask/cryptography/aes-gcm'; -import { getErrorMessage } from '@metamask/utils'; import type { NativeScrypt } from '../types/encryption.js'; import { @@ -222,7 +222,10 @@ class EncryptorDecryptor { return concatBytes(iv, ciphertext); } - async #decrypt(ciphertextAndNonce: Uint8Array, key: Uint8Array): Promise { + async #decrypt( + ciphertextAndNonce: Uint8Array, + key: Uint8Array, + ): Promise { // Create buffers of nonce and ciphertext. const nonce = ciphertextAndNonce.slice(0, ALGORITHM_NONCE_SIZE); const ciphertext = ciphertextAndNonce.slice( diff --git a/packages/profile-sync-controller/tsconfig.lint.json b/packages/profile-sync-controller/tsconfig.lint.json index 3061f6bef02..b3a13f88a00 100644 --- a/packages/profile-sync-controller/tsconfig.lint.json +++ b/packages/profile-sync-controller/tsconfig.lint.json @@ -28,6 +28,6 @@ }, { "path": "../cryptography/tsconfig.lint.json" - }, + } ] } From 9bf8c6107869e27090c073a57484b81bfc7a7060 Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Wed, 30 Sep 2026 15:15:47 +0200 Subject: [PATCH 03/12] Update CHANGELOG --- packages/profile-sync-controller/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/profile-sync-controller/CHANGELOG.md b/packages/profile-sync-controller/CHANGELOG.md index d66c90c8213..2b3ca2ca5be 100644 --- a/packages/profile-sync-controller/CHANGELOG.md +++ b/packages/profile-sync-controller/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Replace JS AES implementation with `@metamask/cryptography` ([#10621](https://github.com/MetaMask/core/pull/10621)) - Bump `immer` from `^9.0.21` to `^11.1.18` ([#10382](https://github.com/MetaMask/core/pull/10382)) ### Fixed From 836aad08c4b7d27155d3908eaa8d6835f50de6d2 Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Wed, 30 Sep 2026 15:21:59 +0200 Subject: [PATCH 04/12] Restore nonce size constant --- .../profile-sync-controller/src/shared/encryption/constants.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/profile-sync-controller/src/shared/encryption/constants.ts b/packages/profile-sync-controller/src/shared/encryption/constants.ts index 3e205becad2..6539a63ebeb 100644 --- a/packages/profile-sync-controller/src/shared/encryption/constants.ts +++ b/packages/profile-sync-controller/src/shared/encryption/constants.ts @@ -1,3 +1,5 @@ +// Nonce/Key Sizes +export const ALGORITHM_NONCE_SIZE = 12; // 12 bytes export const ALGORITHM_KEY_SIZE = 16; // 16 bytes // Scrypt settings From 8165e14fdcd69e838d23b6cd99cdf1bb8cebda87 Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Wed, 30 Sep 2026 15:22:39 +0200 Subject: [PATCH 05/12] Update README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d75568ec121..96865981328 100644 --- a/README.md +++ b/README.md @@ -633,6 +633,7 @@ linkStyle default opacity:0.5 profile_sync_controller --> address_book_controller; profile_sync_controller --> base_controller; profile_sync_controller --> controller_utils; + profile_sync_controller --> cryptography; profile_sync_controller --> keyring_controller; profile_sync_controller --> messenger; profile_sync_controller --> seedless_onboarding_controller; From 9f91c23505e832ef7c0e4ddb29ff7d83ebcc3f4e Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Wed, 30 Sep 2026 15:49:15 +0200 Subject: [PATCH 06/12] Narrow Uint8Array types --- .../src/shared/encryption/cache.ts | 12 +++--- .../src/shared/encryption/encryption.ts | 43 +++++++++++-------- .../src/shared/types/encryption.ts | 2 +- 3 files changed, 32 insertions(+), 25 deletions(-) diff --git a/packages/profile-sync-controller/src/shared/encryption/cache.ts b/packages/profile-sync-controller/src/shared/encryption/cache.ts index 10c55d90b3f..37fadc92854 100644 --- a/packages/profile-sync-controller/src/shared/encryption/cache.ts +++ b/packages/profile-sync-controller/src/shared/encryption/cache.ts @@ -2,9 +2,9 @@ import { SHARED_SALT } from './constants.js'; import { byteArrayToBase64 } from './utils.js'; type CachedEntry = { - salt: Uint8Array; + salt: Uint8Array; base64Salt: string; - key: Uint8Array; + key: Uint8Array; }; const MAX_PASSWORD_CACHES = 100; @@ -14,7 +14,7 @@ const MAX_SALT_CACHES = 100; * In-Memory Caching derived keys based from a given salt and password. */ type PasswordMemCachedKDF = { - [hashedPassword: string]: Map; + [hashedPassword: string]: Map>; }; let inMemCachedKDF: PasswordMemCachedKDF = {}; const getPasswordCache = (hashedPassword: string) => { @@ -31,7 +31,7 @@ const getPasswordCache = (hashedPassword: string) => { */ export function getCachedKeyBySalt( hashedPassword: string, - salt: Uint8Array, + salt: Uint8Array, ): CachedEntry | undefined { const cache = getPasswordCache(hashedPassword); const base64Salt = byteArrayToBase64(salt); @@ -82,8 +82,8 @@ export function getCachedKeyGeneratedWithSharedSalt( */ export function setCachedKey( hashedPassword: string, - salt: Uint8Array, - key: Uint8Array, + salt: Uint8Array, + key: Uint8Array, ): void { // Max password caches if (Object.keys(inMemCachedKDF).length > MAX_PASSWORD_CACHES) { diff --git a/packages/profile-sync-controller/src/shared/encryption/encryption.ts b/packages/profile-sync-controller/src/shared/encryption/encryption.ts index 8b446ce534e..f50c70858e5 100644 --- a/packages/profile-sync-controller/src/shared/encryption/encryption.ts +++ b/packages/profile-sync-controller/src/shared/encryption/encryption.ts @@ -1,8 +1,12 @@ import { decrypt, encrypt } from '@metamask/cryptography/aes-gcm'; -import { getErrorMessage } from '@metamask/utils'; +import { + getErrorMessage, + stringToBytes, + bytesToHex, + concatBytes, +} from '@metamask/utils'; import { scryptAsync } from '@noble/hashes/scrypt'; import { sha256 } from '@noble/hashes/sha256'; -import { utf8ToBytes, concatBytes, bytesToHex } from '@noble/hashes/utils'; import type { NativeScrypt } from '../types/encryption.js'; import { @@ -53,7 +57,7 @@ class EncryptorDecryptor { // Promise cache for ongoing KDF operations to prevent duplicate work readonly #kdfPromiseCache = new Map< string, - Promise<{ key: Uint8Array; salt: Uint8Array }> + Promise<{ key: Uint8Array; salt: Uint8Array }> >(); async encryptString( @@ -114,11 +118,11 @@ class EncryptorDecryptor { ); // Encrypt and prepend salt. - const plaintextRaw = utf8ToBytes(plaintext); - const ciphertextAndNonceAndSalt = concatBytes( + const plaintextRaw = stringToBytes(plaintext); + const ciphertextAndNonceAndSalt = concatBytes([ salt, await this.#encrypt(plaintextRaw, key), - ); + ]); // Convert to Base64 const encryptedData = byteArrayToBase64(ciphertextAndNonceAndSalt); @@ -215,17 +219,20 @@ class EncryptorDecryptor { return strSet.size === salts.length; } - async #encrypt(plaintext: Uint8Array, key: Uint8Array): Promise { + async #encrypt( + plaintext: Uint8Array, + key: Uint8Array, + ): Promise> { // Encrypt and prepend nonce. const { ciphertext, iv } = await encrypt(key, plaintext); - return concatBytes(iv, ciphertext); + return concatBytes([iv, ciphertext]); } async #decrypt( - ciphertextAndNonce: Uint8Array, - key: Uint8Array, - ): Promise { + ciphertextAndNonce: Uint8Array, + key: Uint8Array, + ): Promise> { // Create buffers of nonce and ciphertext. const nonce = ciphertextAndNonce.slice(0, ALGORITHM_NONCE_SIZE); const ciphertext = ciphertextAndNonce.slice( @@ -240,9 +247,9 @@ class EncryptorDecryptor { async #getOrGenerateScryptKey( password: string, o: EncryptedPayload['o'], - salt?: Uint8Array, + salt?: Uint8Array, nativeScryptCrypto?: NativeScrypt, - ) { + ): Promise<{ key: Uint8Array; salt: Uint8Array }> { const hashedPassword = createSHA256Hash(password); // Check if we already have the key cached @@ -316,11 +323,11 @@ class EncryptorDecryptor { async #performKdfOperation( password: string, o: EncryptedPayload['o'], - salt: Uint8Array, + salt: Uint8Array, hashedPassword: string, nativeScryptCrypto?: NativeScrypt, - ): Promise<{ key: Uint8Array; salt: Uint8Array }> { - let newKey: Uint8Array; + ): Promise<{ key: Uint8Array; salt: Uint8Array }> { + let newKey: Uint8Array; if (nativeScryptCrypto) { newKey = await nativeScryptCrypto( @@ -332,12 +339,12 @@ class EncryptorDecryptor { o.dkLen, ); } else { - newKey = await scryptAsync(password, salt, { + newKey = (await scryptAsync(password, salt, { N: o.N, r: o.r, p: o.p, dkLen: o.dkLen, - }); + })) as Uint8Array; } setCachedKey(hashedPassword, salt, newKey); diff --git a/packages/profile-sync-controller/src/shared/types/encryption.ts b/packages/profile-sync-controller/src/shared/types/encryption.ts index e95ec41fbd9..84f99749880 100644 --- a/packages/profile-sync-controller/src/shared/types/encryption.ts +++ b/packages/profile-sync-controller/src/shared/types/encryption.ts @@ -5,4 +5,4 @@ export declare type NativeScrypt = ( r: number, p: number, size: number, -) => Promise; +) => Promise>; From fd045a618964c2e44826a2853544f07b6f545024 Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Thu, 1 Oct 2026 10:26:51 +0200 Subject: [PATCH 07/12] Fix SHA-256 output following usage of utils --- .../src/shared/encryption/encryption.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/profile-sync-controller/src/shared/encryption/encryption.ts b/packages/profile-sync-controller/src/shared/encryption/encryption.ts index f50c70858e5..6eeddab171e 100644 --- a/packages/profile-sync-controller/src/shared/encryption/encryption.ts +++ b/packages/profile-sync-controller/src/shared/encryption/encryption.ts @@ -4,6 +4,7 @@ import { stringToBytes, bytesToHex, concatBytes, + remove0x, } from '@metamask/utils'; import { scryptAsync } from '@noble/hashes/scrypt'; import { sha256 } from '@noble/hashes/sha256'; @@ -367,5 +368,5 @@ export default encryption; */ export function createSHA256Hash(data: string): string { const hashedData = sha256(data); - return bytesToHex(hashedData); + return remove0x(bytesToHex(hashedData)); } From d6c135fa99b2b87c5fc3e6a73c82a3fca9843891 Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Thu, 1 Oct 2026 10:39:13 +0200 Subject: [PATCH 08/12] Fix tsconfig --- tsconfig.packages.json | 1 + 1 file changed, 1 insertion(+) diff --git a/tsconfig.packages.json b/tsconfig.packages.json index 46fe96683e1..a37993e9af8 100644 --- a/tsconfig.packages.json +++ b/tsconfig.packages.json @@ -22,6 +22,7 @@ "@metamask/profile-sync-controller/user-storage": [ "${configDir}../profile-sync-controller/src/controllers/user-storage/index.ts" ], + "@metamask/cryptography/*": ["${configDir}/../cryptography/src/*"], "@metamask/utils/node": ["${configDir}/../utils/src/node.ts"], "@metamask/*": ["${configDir}/../*/src/index.ts"] } From ee15675fa0bd24af2063e28028fb119e28f9fa15 Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Thu, 1 Oct 2026 11:07:43 +0200 Subject: [PATCH 09/12] Fix tsconfig --- tsconfig.packages.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsconfig.packages.json b/tsconfig.packages.json index a37993e9af8..4fe27b7c168 100644 --- a/tsconfig.packages.json +++ b/tsconfig.packages.json @@ -22,7 +22,7 @@ "@metamask/profile-sync-controller/user-storage": [ "${configDir}../profile-sync-controller/src/controllers/user-storage/index.ts" ], - "@metamask/cryptography/*": ["${configDir}/../cryptography/src/*"], + "@metamask/cryptography/*": ["${configDir}/../cryptography/src/*.ts"], "@metamask/utils/node": ["${configDir}/../utils/src/node.ts"], "@metamask/*": ["${configDir}/../*/src/index.ts"] } From 5cc0186f8f863fa6d3fa72ac0c2164ce0c516c40 Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Thu, 1 Oct 2026 11:11:55 +0200 Subject: [PATCH 10/12] Update suppressions --- oxlint-suppressions.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oxlint-suppressions.json b/oxlint-suppressions.json index 50a72b60d16..626b1252624 100644 --- a/oxlint-suppressions.json +++ b/oxlint-suppressions.json @@ -5385,7 +5385,7 @@ "count": 1 }, "typescript/explicit-function-return-type": { - "count": 2 + "count": 1 }, "typescript/no-unsafe-assignment": { "count": 2 From 0a3cbc489e7970d3c5e521c6e95c489fc5c3a6a1 Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Thu, 1 Oct 2026 13:41:57 +0200 Subject: [PATCH 11/12] Remove nonce size constant again --- .../src/shared/encryption/constants.ts | 2 -- .../src/shared/encryption/encryption.ts | 7 +++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/profile-sync-controller/src/shared/encryption/constants.ts b/packages/profile-sync-controller/src/shared/encryption/constants.ts index 6539a63ebeb..3e205becad2 100644 --- a/packages/profile-sync-controller/src/shared/encryption/constants.ts +++ b/packages/profile-sync-controller/src/shared/encryption/constants.ts @@ -1,5 +1,3 @@ -// Nonce/Key Sizes -export const ALGORITHM_NONCE_SIZE = 12; // 12 bytes export const ALGORITHM_KEY_SIZE = 16; // 16 bytes // Scrypt settings diff --git a/packages/profile-sync-controller/src/shared/encryption/encryption.ts b/packages/profile-sync-controller/src/shared/encryption/encryption.ts index 6eeddab171e..f18f194e5d8 100644 --- a/packages/profile-sync-controller/src/shared/encryption/encryption.ts +++ b/packages/profile-sync-controller/src/shared/encryption/encryption.ts @@ -1,4 +1,4 @@ -import { decrypt, encrypt } from '@metamask/cryptography/aes-gcm'; +import { decrypt, encrypt, IV_LENGTH } from '@metamask/cryptography/aes-gcm'; import { getErrorMessage, stringToBytes, @@ -17,7 +17,6 @@ import { } from './cache.js'; import { ALGORITHM_KEY_SIZE, - ALGORITHM_NONCE_SIZE, MAX_KDF_PROMISE_CACHE_SIZE, SCRYPT_N, SCRYPT_p, @@ -235,9 +234,9 @@ class EncryptorDecryptor { key: Uint8Array, ): Promise> { // Create buffers of nonce and ciphertext. - const nonce = ciphertextAndNonce.slice(0, ALGORITHM_NONCE_SIZE); + const nonce = ciphertextAndNonce.slice(0, IV_LENGTH); const ciphertext = ciphertextAndNonce.slice( - ALGORITHM_NONCE_SIZE, + IV_LENGTH, ciphertextAndNonce.length, ); From 8e2bd0300b0a957b64b32df85f4c6a3c62b76fa5 Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Thu, 1 Oct 2026 13:46:42 +0200 Subject: [PATCH 12/12] Bump version after rebase --- packages/profile-sync-controller/package.json | 2 +- yarn.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/profile-sync-controller/package.json b/packages/profile-sync-controller/package.json index f024f8f379d..92a126d30ed 100644 --- a/packages/profile-sync-controller/package.json +++ b/packages/profile-sync-controller/package.json @@ -76,7 +76,7 @@ "@metamask/address-book-controller": "^8.0.0", "@metamask/base-controller": "^10.0.0", "@metamask/controller-utils": "^13.0.0", - "@metamask/cryptography": "^1.0.0", + "@metamask/cryptography": "^1.1.0", "@metamask/key-tree": "^10.1.1", "@metamask/keyring-controller": "^28.1.0", "@metamask/messenger": "^3.0.0", diff --git a/yarn.lock b/yarn.lock index 8581f9ee6e4..3714c9937d3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6396,7 +6396,7 @@ __metadata: languageName: node linkType: hard -"@metamask/cryptography@npm:^1.0.0, @metamask/cryptography@workspace:packages/cryptography": +"@metamask/cryptography@npm:^1.1.0, @metamask/cryptography@workspace:packages/cryptography": version: 0.0.0-use.local resolution: "@metamask/cryptography@workspace:packages/cryptography" dependencies: @@ -8291,7 +8291,7 @@ __metadata: "@metamask/auto-changelog": "npm:^6.2.1" "@metamask/base-controller": "npm:^10.0.0" "@metamask/controller-utils": "npm:^13.0.0" - "@metamask/cryptography": "npm:^1.0.0" + "@metamask/cryptography": "npm:^1.1.0" "@metamask/eth-hd-keyring": "npm:^15.0.0" "@metamask/key-tree": "npm:^10.1.1" "@metamask/keyring-api": "npm:^24.0.0"