From 2a2a40af7acfe88ae5de73776ce70da0469fe3e1 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Fri, 6 Dec 2019 17:51:20 +0000 Subject: [PATCH] Add separate check for secret storage keys Decryption vs. signing keys are calculated differently and so require separate check functions. --- src/client.js | 24 ++++++++++++++++++------ src/crypto/index.js | 30 +++++++++++++++++++++++++----- 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/src/client.js b/src/client.js index bd8c249a2..c3d5e24e6 100644 --- a/src/client.js +++ b/src/client.js @@ -1027,13 +1027,12 @@ function wrapCryptoFuncs(MatrixClient, names) { */ /** - * Checks that a given private key matches a given public key. - * This can be used by the getCrossSigningKey or getSecretStorageKey callbacks - * to verify that the private key it is about to supply is the one that was - * requested. + * Checks that a given cross-signing private key matches a given public key. + * This can be used by the getCrossSigningKey callback to verify that the + * private key it is about to supply is the one that was requested. * The cross-signing API is currently UNSTABLE and may change without notice. * - * @function module:client~MatrixClient#checkPrivateKey + * @function module:client~MatrixClient#checkCrossSigningPrivateKey * @param {Uint8Array} privateKey The private key * @param {string} expectedPublicKey The public key * @returns {boolean} true if the key matches, otherwise false @@ -1046,7 +1045,7 @@ wrapCryptoFuncs(MatrixClient, [ "checkUserTrust", "checkDeviceTrust", "checkOwnCrossSigningTrust", - "checkPrivateKey", + "checkCrossSigningPrivateKey", ]); /** @@ -1176,6 +1175,18 @@ MatrixClient.prototype.checkEventSenderTrust = async function(event) { * @param {string} keyId The new default key ID */ +/** + * Checks that a given secret storage private key matches a given public key. + * This can be used by the getSecretStorageKey callback to verify that the + * private key it is about to supply is the one that was requested. + * The Secure Secret Storage API is currently UNSTABLE and may change without notice. + * + * @function module:client~MatrixClient#checkSecretStoragePrivateKey + * @param {Uint8Array} privateKey The private key + * @param {string} expectedPublicKey The public key + * @returns {boolean} true if the key matches, otherwise false + */ + wrapCryptoFuncs(MatrixClient, [ "createRecoveryKeyFromPassphrase", "bootstrapSecretStorage", @@ -1187,6 +1198,7 @@ wrapCryptoFuncs(MatrixClient, [ "requestSecret", "getDefaultSecretStorageKeyId", "setDefaultSecretStorageKeyId", + "checkSecretStoragePrivateKey", ]); /** diff --git a/src/crypto/index.js b/src/crypto/index.js index 77d338672..bc01fc2e7 100644 --- a/src/crypto/index.js +++ b/src/crypto/index.js @@ -467,16 +467,36 @@ Crypto.prototype.setDefaultSecretStorageKeyId = function(k) { }; /** - * Checks that a given private key matches a given public key. - * This can be used by the getCrossSigningKey or getSecretStorageKey callbacks - * to verify that the private key it is about to supply is the one that was - * requested. + * Checks that a given secret storage private key matches a given public key. + * This can be used by the getSecretStorageKey callback to verify that the + * private key it is about to supply is the one that was requested. * * @param {Uint8Array} privateKey The private key * @param {string} expectedPublicKey The public key * @returns {boolean} true if the key matches, otherwise false */ -Crypto.prototype.checkPrivateKey = function(privateKey, expectedPublicKey) { +Crypto.prototype.checkSecretStoragePrivateKey = function(privateKey, expectedPublicKey) { + let decryption = null; + try { + decryption = new global.Olm.PkDecryption(); + const gotPubkey = decryption.init_with_private_key(privateKey); + // make sure it agrees with the given pubkey + return gotPubkey === expectedPublicKey; + } finally { + if (decryption) decryption.free(); + } +}; + +/** + * Checks that a given cross-signing private key matches a given public key. + * This can be used by the getCrossSigningKey callback to verify that the + * private key it is about to supply is the one that was requested. + * + * @param {Uint8Array} privateKey The private key + * @param {string} expectedPublicKey The public key + * @returns {boolean} true if the key matches, otherwise false + */ +Crypto.prototype.checkCrossSigningPrivateKey = function(privateKey, expectedPublicKey) { let signing = null; try { signing = new global.Olm.PkSigning();