From 0545c1f0c52c6c3d7025040298d4546ddfe41e72 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 2 Sep 2020 17:37:48 +0200 Subject: [PATCH] extract verifying a signed object from the device tracker --- src/matrix/e2ee/DeviceTracker.js | 27 +++++---------------------- src/matrix/e2ee/common.js | 23 +++++++++++++++++++++++ 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/src/matrix/e2ee/DeviceTracker.js b/src/matrix/e2ee/DeviceTracker.js index b085be80..095730ff 100644 --- a/src/matrix/e2ee/DeviceTracker.js +++ b/src/matrix/e2ee/DeviceTracker.js @@ -14,13 +14,11 @@ See the License for the specific language governing permissions and limitations under the License. */ -import anotherjson from "../../../lib/another-json/index.js"; +import {verifyEd25519Signature, SIGNATURE_ALGORITHM} from "./common.js"; const TRACKING_STATUS_OUTDATED = 0; const TRACKING_STATUS_UPTODATE = 1; -const DEVICE_KEYS_SIGNATURE_ALGORITHM = "ed25519"; - // map 1 device from /keys/query response to DeviceIdentity function deviceKeysAsDeviceIdentity(deviceSection) { const deviceId = deviceSection["device_id"]; @@ -200,7 +198,7 @@ export class DeviceTracker { if (deviceIdOnKeys !== deviceId) { return false; } - return this._verifyUserDeviceKeys(deviceKeys); + return this._hasValidSignature(deviceKeys); }); const verifiedKeys = verifiedEntries.map(([, deviceKeys]) => deviceKeys); return {userId, verifiedKeys}; @@ -208,26 +206,11 @@ export class DeviceTracker { return verifiedKeys; } - _verifyUserDeviceKeys(deviceSection) { + _hasValidSignature(deviceSection) { const deviceId = deviceSection["device_id"]; const userId = deviceSection["user_id"]; - const clone = Object.assign({}, deviceSection); - delete clone.unsigned; - delete clone.signatures; - const canonicalJson = anotherjson.stringify(clone); - const key = deviceSection?.keys?.[`${DEVICE_KEYS_SIGNATURE_ALGORITHM}:${deviceId}`]; - const signature = deviceSection?.signatures?.[userId]?.[`${DEVICE_KEYS_SIGNATURE_ALGORITHM}:${deviceId}`]; - try { - if (!signature) { - throw new Error("no signature"); - } - // throws when signature is invalid - this._olmUtil.ed25519_verify(key, canonicalJson, signature); - return true; - } catch (err) { - console.warn("Invalid device signature, ignoring device.", key, canonicalJson, signature, err); - return false; - } + const ed25519Key = deviceSection?.keys?.[`${SIGNATURE_ALGORITHM}:${deviceId}`]; + return verifyEd25519Signature(this._olmUtil, userId, deviceId, ed25519Key, deviceSection); } /** diff --git a/src/matrix/e2ee/common.js b/src/matrix/e2ee/common.js index c5e7399f..9b3b2f26 100644 --- a/src/matrix/e2ee/common.js +++ b/src/matrix/e2ee/common.js @@ -14,6 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ +import anotherjson from "../../../lib/another-json/index.js"; + // use common prefix so it's easy to clear properties that are not e2ee related during session clear export const SESSION_KEY_PREFIX = "e2ee:"; export const OLM_ALGORITHM = "m.olm.v1.curve25519-aes-sha2"; @@ -27,3 +29,24 @@ export class DecryptionError extends Error { this.details = detailsObj; } } + +export const SIGNATURE_ALGORITHM = "ed25519"; + +export function verifyEd25519Signature(olmUtil, userId, deviceOrKeyId, ed25519Key, value) { + const clone = Object.assign({}, value); + delete clone.unsigned; + delete clone.signatures; + const canonicalJson = anotherjson.stringify(clone); + const signature = value?.signatures?.[userId]?.[`${SIGNATURE_ALGORITHM}:${deviceOrKeyId}`]; + try { + if (!signature) { + throw new Error("no signature"); + } + // throws when signature is invalid + this._olmUtil.ed25519_verify(ed25519Key, canonicalJson, signature); + return true; + } catch (err) { + console.warn("Invalid signature, ignoring.", ed25519Key, canonicalJson, signature, err); + return false; + } +}