Skip to content

Commit

Permalink
Add loadSessionBackupPrivateKeyFromSecretStorage
Browse files Browse the repository at this point in the history
  • Loading branch information
florianduros committed Nov 6, 2024
1 parent fe3ea7c commit e55aee9
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 37 deletions.
8 changes: 4 additions & 4 deletions spec/integ/crypto/megolm-backup.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
createClient,
Crypto,
CryptoEvent,
encodeBase64,
ICreateClientOpts,
IEvent,
IMegolmSessionData,
Expand Down Expand Up @@ -621,11 +622,10 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("megolm-keys backup (%s)", (backe
};
fetchMock.get("express:/_matrix/client/v3/room_keys/keys", fullBackup);

const check = await aliceCrypto.checkKeyBackupAndEnable();
const recoveryKey = await aliceCrypto.getSecretStorageBackupPrivateKey();
expect(recoveryKey).not.toBeNull();
await aliceCrypto.loadSessionBackupPrivateKeyFromSecretStorage();
const decryptionKey = await aliceCrypto.getSessionBackupPrivateKey();
expect(encodeBase64(decryptionKey!)).toStrictEqual(testData.BACKUP_DECRYPTION_KEY_BASE64);

await aliceCrypto.storeSessionBackupPrivateKey(recoveryKey!, check!.backupInfo!.version!);
const result = await aliceCrypto.restoreKeyBackup();
expect(result.imported).toStrictEqual(1);
},
Expand Down
15 changes: 6 additions & 9 deletions src/crypto-api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -470,15 +470,6 @@ export interface CryptoApi {
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/**
* Fetch the backup decryption key we have saved in our secret storage.
*
* This can be used for gossiping the key to other devices.
*
* @returns the key, if any, or null
*/
getSecretStorageBackupPrivateKey(): Promise<Uint8Array | null>;

/**
* Fetch the backup decryption key we have saved in our store.
*
Expand Down Expand Up @@ -511,6 +502,12 @@ export interface CryptoApi {
*/
storeSessionBackupPrivateKey(key: Uint8Array, version: string): Promise<void>;

/**
* Fetch the backup decryption key from the secret storage, fetch the backup info version.
* Store locally the key and the backup info version by calling {@link storeSessionBackupPrivateKey}.
*/
loadSessionBackupPrivateKeyFromSecretStorage(): Promise<void>;

/**
* Get the current status of key backup.
*
Expand Down
14 changes: 7 additions & 7 deletions src/crypto/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1308,6 +1308,13 @@ export class Crypto extends TypedEventEmitter<CryptoEvent, CryptoEventHandlerMap
});
}

/**
* Implementation of {@link Crypto.loadSessionBackupPrivateKeyFromSecretStorage}.
*/
public loadSessionBackupPrivateKeyFromSecretStorage(): Promise<void> {
throw new Error("Not implmeented");
}

/**
* Get the current status of key backup.
*
Expand Down Expand Up @@ -4327,13 +4334,6 @@ export class Crypto extends TypedEventEmitter<CryptoEvent, CryptoEventHandlerMap
): Promise<KeyBackupRestoreResult> {
throw new Error("Not implemented");
}

/**
* Stub function -- getSecretStorageBackupPrivateKey is not implemented here, so throw error
*/
public getSecretStorageBackupPrivateKey(): Promise<Uint8Array | null> {
throw new Error("Not implemented");
}
}

/**
Expand Down
41 changes: 24 additions & 17 deletions src/rust-crypto/rust-crypto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1171,15 +1171,6 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, CryptoEventH
}
}

/**
* Implementation of {@link CryptoApi#getSecretStorageBackupPrivateKey}.
*/
public async getSecretStorageBackupPrivateKey(): Promise<Uint8Array | null> {
const backupKey = await this.secretStorage.get("m.megolm_backup.v1");
if (!backupKey) return null;
return decodeBase64(backupKey);
}

/**
* Fetch the backup decryption key we have saved in our store.
*
Expand Down Expand Up @@ -1214,6 +1205,24 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, CryptoEventH
);
}

/**
* Implementation of {@link CryptoApi#loadSessionBackupPrivateKeyFromSecretStorage}.
*/
public async loadSessionBackupPrivateKeyFromSecretStorage(): Promise<void> {
const backupKey = await this.secretStorage.get("m.megolm_backup.v1");
if (!backupKey) {
throw new Error("loadSessionBackupPrivateKeyFromSecretStorage: missing decryption key in secret storage");
}

const decodedKey = decodeBase64(backupKey);
const keyBackupInfo = await this.backupManager.getServerBackupInfo();
if (!keyBackupInfo) {
throw new Error("loadSessionBackupPrivateKeyFromSecretStorage: unable to get backup version");
}

await this.storeSessionBackupPrivateKey(decodedKey, keyBackupInfo.version);
}

/**
* Get the current status of key backup.
*
Expand Down Expand Up @@ -1323,19 +1332,17 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, CryptoEventH

const backupDecryptor = await this.getBackupDecryptor(backupInfo, privateKeyFromCache);

opts?.progressCallback?.({
stage: "fetch",
});

let result: KeyBackupRestoreResult;
try {
result = await this.backupManager.restoreKeyBackup(backupInfo.version, backupDecryptor, opts);
opts?.progressCallback?.({
stage: "fetch",
});

const result = await this.backupManager.restoreKeyBackup(backupInfo.version, backupDecryptor, opts);
return result;
} finally {
// Free to avoid to keep in memory the decryption key stored in it. To avoid to exposing it to an attacker.
backupDecryptor.free();
}

return result;
}

/**
Expand Down

0 comments on commit e55aee9

Please sign in to comment.