diff --git a/package.json b/package.json index 9196a3dc8..2c72d2e11 100644 --- a/package.json +++ b/package.json @@ -198,7 +198,7 @@ "@electron/fuses": "1.5.0", "@formatjs/intl": "2.6.7", "@mixer/parallel-prettier": "2.0.3", - "@signalapp/mock-server": "4.2.0", + "@signalapp/mock-server": "4.3.0", "@storybook/addon-a11y": "7.4.5", "@storybook/addon-actions": "7.4.5", "@storybook/addon-controls": "7.4.5", diff --git a/protos/DeviceMessages.proto b/protos/DeviceMessages.proto index 30174af3a..3809a47a2 100644 --- a/protos/DeviceMessages.proto +++ b/protos/DeviceMessages.proto @@ -26,6 +26,7 @@ message ProvisionMessage { optional bytes profileKey = 6; optional bool readReceipts = 7; optional uint32 ProvisioningVersion = 9; + optional bytes masterKey = 13; } enum ProvisioningVersion { diff --git a/ts/textsecure/AccountManager.ts b/ts/textsecure/AccountManager.ts index 9d2541de9..8f3db2a4f 100644 --- a/ts/textsecure/AccountManager.ts +++ b/ts/textsecure/AccountManager.ts @@ -67,6 +67,7 @@ const DAY = 24 * 60 * 60 * 1000; const STARTING_KEY_ID = 1; const PROFILE_KEY_LENGTH = 32; +const MASTER_KEY_LENGTH = 32; const KEY_TOO_OLD_THRESHOLD = 14 * DAY; export const KYBER_KEY_ID_KEY: StorageKeyByServiceIdKind = { @@ -120,6 +121,7 @@ type CreateAccountSharedOptionsType = Readonly<{ aciKeyPair: KeyPairType; pniKeyPair: KeyPairType; profileKey: Uint8Array; + masterKey: Uint8Array | undefined; }>; type CreatePrimaryDeviceOptionsType = Readonly<{ @@ -302,6 +304,7 @@ export default class AccountManager extends EventTarget { const pniKeyPair = generateKeyPair(); const profileKey = getRandomBytes(PROFILE_KEY_LENGTH); const accessKey = deriveAccessKey(profileKey); + const masterKey = getRandomBytes(MASTER_KEY_LENGTH); const registrationBaton = this.server.startRegistration(); try { @@ -314,6 +317,7 @@ export default class AccountManager extends EventTarget { pniKeyPair, profileKey, accessKey, + masterKey, readReceipts: true, }); } finally { @@ -428,6 +432,7 @@ export default class AccountManager extends EventTarget { ourAci, ourPni, readReceipts: Boolean(provisionMessage.readReceipts), + masterKey: provisionMessage.masterKey, }); } finally { this.server.finishRegistration(registrationBaton); @@ -968,6 +973,7 @@ export default class AccountManager extends EventTarget { aciKeyPair, pniKeyPair, profileKey, + masterKey, readReceipts, userAgent, } = options; @@ -1202,6 +1208,9 @@ export default class AccountManager extends EventTarget { if (userAgent) { await storage.put('userAgent', userAgent); } + if (masterKey) { + await storage.put('masterKey', Bytes.toBase64(masterKey)); + } await storage.put('read-receipt-setting', Boolean(readReceipts)); diff --git a/ts/textsecure/ProvisioningCipher.ts b/ts/textsecure/ProvisioningCipher.ts index 78f5d29d8..0b31b6519 100644 --- a/ts/textsecure/ProvisioningCipher.ts +++ b/ts/textsecure/ProvisioningCipher.ts @@ -24,6 +24,7 @@ type ProvisionDecryptResult = { userAgent?: string; readReceipts?: boolean; profileKey?: Uint8Array; + masterKey?: Uint8Array; }; class ProvisioningCipherInner { @@ -87,6 +88,9 @@ class ProvisioningCipherInner { if (provisionMessage.profileKey) { ret.profileKey = provisionMessage.profileKey; } + if (provisionMessage.masterKey) { + ret.masterKey = provisionMessage.masterKey; + } return ret; } diff --git a/yarn.lock b/yarn.lock index 4e36103ea..09a8f9c3e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3901,10 +3901,10 @@ node-gyp-build "^4.2.3" uuid "^8.3.0" -"@signalapp/mock-server@4.2.0": - version "4.2.0" - resolved "https://registry.yarnpkg.com/@signalapp/mock-server/-/mock-server-4.2.0.tgz#836bf1d8cb38b9f66a6f719205e5000cdc7d184b" - integrity sha512-pungaAf3Pel34yIK00nRtHWQHA9VCRjOH11ZBgrEjiMpdA+LPETCU94Do28Q9Un7T8GmNOJ0+cKAhCKuyo1Fow== +"@signalapp/mock-server@4.3.0": + version "4.3.0" + resolved "https://registry.yarnpkg.com/@signalapp/mock-server/-/mock-server-4.3.0.tgz#501d1e0bc9f9fe811189690e7b053dfe9bac7c88" + integrity sha512-zE8+EhuKsQ0byXG1Prkw5hoH0pMySwf+AJNf2sdOTsIJSKLx8/GOP4uG3m/vSOW3m4BoAmVnpNzJryRIjpfAbw== dependencies: "@signalapp/libsignal-client" "^0.30.2" debug "^4.3.2"