You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-12-05 17:02:07 +03:00
Create key backup with secret storage
When secret storage is enable, create a random key for encrypting key backups and store it in SSSS.
This commit is contained in:
@@ -53,6 +53,7 @@ import { isCryptoAvailable } from './crypto';
|
|||||||
import { decodeRecoveryKey } from './crypto/recoverykey';
|
import { decodeRecoveryKey } from './crypto/recoverykey';
|
||||||
import { keyFromAuthData } from './crypto/key_passphrase';
|
import { keyFromAuthData } from './crypto/key_passphrase';
|
||||||
import { randomString } from './randomstring';
|
import { randomString } from './randomstring';
|
||||||
|
import { encodeBase64 } from '../lib/crypto/olmlib';
|
||||||
|
|
||||||
const SCROLLBACK_DELAY_MS = 3000;
|
const SCROLLBACK_DELAY_MS = 3000;
|
||||||
const CRYPTO_ENABLED = isCryptoAvailable();
|
const CRYPTO_ENABLED = isCryptoAvailable();
|
||||||
@@ -1437,7 +1438,7 @@ MatrixClient.prototype.disableKeyBackup = function() {
|
|||||||
* when restoring the backup as an alternative to entering the recovery key.
|
* when restoring the backup as an alternative to entering the recovery key.
|
||||||
* Optional.
|
* Optional.
|
||||||
* @param {boolean} [opts.secureSecretStorage = false] Whether to use Secure
|
* @param {boolean} [opts.secureSecretStorage = false] Whether to use Secure
|
||||||
* Secret Storage (MSC1946) to store the key encrypting key backups.
|
* Secret Storage to store the key encrypting key backups.
|
||||||
* Optional, defaults to false.
|
* Optional, defaults to false.
|
||||||
*
|
*
|
||||||
* @returns {Promise<object>} Object that can be passed to createKeyBackupVersion and
|
* @returns {Promise<object>} Object that can be passed to createKeyBackupVersion and
|
||||||
@@ -1451,28 +1452,25 @@ MatrixClient.prototype.prepareKeyBackupVersion = async function(
|
|||||||
throw new Error("End-to-end encryption disabled");
|
throw new Error("End-to-end encryption disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (secureSecretStorage) {
|
const [keyInfo, encodedPrivateKey, privateKey] =
|
||||||
logger.log("Preparing key backup version with Secure Secret Storage");
|
|
||||||
|
|
||||||
// Ensure Secure Secret Storage is ready for use
|
|
||||||
if (!this.hasSecretStorageKey()) {
|
|
||||||
throw new Error("Secure Secret Storage has no keys, needs bootstrapping");
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error("Not yet implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
const [keyInfo, encodedPrivateKey] =
|
|
||||||
await this.createRecoveryKeyFromPassphrase(password);
|
await this.createRecoveryKeyFromPassphrase(password);
|
||||||
|
|
||||||
|
if (secureSecretStorage) {
|
||||||
|
await this.storeSecret("m.megolm_backup.v1", encodeBase64(privateKey));
|
||||||
|
logger.info("Key backup private key stored in secret storage");
|
||||||
|
}
|
||||||
|
|
||||||
// Reshape objects into form expected for key backup
|
// Reshape objects into form expected for key backup
|
||||||
|
const authData = {
|
||||||
|
public_key: keyInfo.pubkey,
|
||||||
|
};
|
||||||
|
if (keyInfo.passphrase) {
|
||||||
|
authData.private_key_salt = keyInfo.passphrase.salt;
|
||||||
|
authData.private_key_iterations = keyInfo.passphrase.iterations;
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
algorithm: olmlib.MEGOLM_BACKUP_ALGORITHM,
|
algorithm: olmlib.MEGOLM_BACKUP_ALGORITHM,
|
||||||
auth_data: {
|
auth_data: authData,
|
||||||
public_key: keyInfo.pubkey,
|
|
||||||
private_key_salt: keyInfo.passphrase.salt,
|
|
||||||
private_key_iterations: keyInfo.passphrase.iterations,
|
|
||||||
},
|
|
||||||
recovery_key: encodedPrivateKey,
|
recovery_key: encodedPrivateKey,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -296,8 +296,9 @@ Crypto.prototype.init = async function() {
|
|||||||
* @param {string} password Passphrase string that can be entered by the user
|
* @param {string} password Passphrase string that can be entered by the user
|
||||||
* when restoring the backup as an alternative to entering the recovery key.
|
* when restoring the backup as an alternative to entering the recovery key.
|
||||||
* Optional.
|
* Optional.
|
||||||
* @returns {Promise<Array>} Array with public key metadata and encoded private
|
* @returns {Promise<Array>} Array with public key metadata, encoded private
|
||||||
* recovery key which should be disposed of after displaying to the user.
|
* recovery key which should be disposed of after displaying to the user,
|
||||||
|
* and raw private key to avoid round tripping if needed.
|
||||||
*/
|
*/
|
||||||
Crypto.prototype.createRecoveryKeyFromPassphrase = async function(password) {
|
Crypto.prototype.createRecoveryKeyFromPassphrase = async function(password) {
|
||||||
const decryption = new global.Olm.PkDecryption();
|
const decryption = new global.Olm.PkDecryption();
|
||||||
@@ -314,8 +315,9 @@ Crypto.prototype.createRecoveryKeyFromPassphrase = async function(password) {
|
|||||||
} else {
|
} else {
|
||||||
keyInfo.pubkey = decryption.generate_key();
|
keyInfo.pubkey = decryption.generate_key();
|
||||||
}
|
}
|
||||||
const encodedPrivateKey = encodeRecoveryKey(decryption.get_private_key());
|
const privateKey = decryption.get_private_key();
|
||||||
return [keyInfo, encodedPrivateKey];
|
const encodedPrivateKey = encodeRecoveryKey(privateKey);
|
||||||
|
return [keyInfo, encodedPrivateKey, privateKey];
|
||||||
} finally {
|
} finally {
|
||||||
decryption.free();
|
decryption.free();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user