diff --git a/src/client.js b/src/client.js index d0e320919..a8e4ddcf1 100644 --- a/src/client.js +++ b/src/client.js @@ -51,8 +51,8 @@ import logger from './logger'; import Crypto from './crypto'; import { isCryptoAvailable } from './crypto'; -import { encodeRecoveryKey, decodeRecoveryKey } from './crypto/recoverykey'; -import { keyFromPassphrase, keyFromAuthData } from './crypto/key_passphrase'; +import { decodeRecoveryKey } from './crypto/recoverykey'; +import { keyFromAuthData } from './crypto/key_passphrase'; import { randomString } from './randomstring'; // Disable warnings for now: we use deprecated bluebird functions @@ -1428,29 +1428,19 @@ MatrixClient.prototype.prepareKeyBackupVersion = async function( } } - const decryption = new global.Olm.PkDecryption(); - try { - let publicKey; - const authData = {}; - if (password) { - const keyInfo = await keyFromPassphrase(password); - publicKey = decryption.init_with_private_key(keyInfo.key); - authData.private_key_salt = keyInfo.salt; - authData.private_key_iterations = keyInfo.iterations; - } else { - publicKey = decryption.generate_key(); - } + const [keyInfo, encodedPrivateKey] = + await this.createRecoveryKeyFromPassphrase(password); - authData.public_key = publicKey; - - return { - algorithm: olmlib.MEGOLM_BACKUP_ALGORITHM, - auth_data: authData, - recovery_key: encodeRecoveryKey(decryption.get_private_key()), - }; - } finally { - decryption.free(); - } + // Reshape objects into form expected for key backup + return { + algorithm: olmlib.MEGOLM_BACKUP_ALGORITHM, + auth_data: { + public_key: keyInfo.pubkey, + private_key_salt: keyInfo.passphrase.salt, + private_key_iterations: keyInfo.passphrase.iterations, + }, + recovery_key: encodedPrivateKey, + }; }; /** diff --git a/src/crypto/index.js b/src/crypto/index.js index de67e5c25..2c9514f77 100644 --- a/src/crypto/index.js +++ b/src/crypto/index.js @@ -325,18 +325,26 @@ Crypto.prototype.init = async function() { * @param {string} password Passphrase string that can be entered by the user * when restoring the backup as an alternative to entering the recovery key. * Optional. - * @returns {Promise} The user-facing recovery key string. + * @returns {Promise} Array with public key metadata and encoded private + * recovery key which should be disposed of after displaying to the user. */ Crypto.prototype.createRecoveryKeyFromPassphrase = async function(password) { const decryption = new global.Olm.PkDecryption(); try { + const keyInfo = {}; if (password) { - const keyInfo = await keyFromPassphrase(password); - decryption.init_with_private_key(keyInfo.key); + const derivation = await keyFromPassphrase(password); + keyInfo.passphrase = { + algorithm: "m.pbkdf2", + iterations: derivation.iterations, + salt: derivation.salt, + }; + keyInfo.pubkey = decryption.init_with_private_key(derivation.key); } else { - decryption.generate_key(); + keyInfo.pubkey = decryption.generate_key(); } - return encodeRecoveryKey(decryption.get_private_key()); + const encodedPrivateKey = encodeRecoveryKey(decryption.get_private_key()); + return [keyInfo, encodedPrivateKey]; } finally { decryption.free(); }