From d94c991a8559adef4245c6fc49e5337ec23976ee Mon Sep 17 00:00:00 2001 From: Florian Duros Date: Thu, 12 Sep 2024 10:49:45 +0200 Subject: [PATCH 1/8] Move `crypto/recoverykey.ts` to `crypto-api/recovery-key.ts` --- src/client.ts | 9 ++++-- src/crypto-api/index.ts | 1 + .../recovery-key.ts} | 28 +++++++++---------- src/crypto/backup.ts | 2 +- src/crypto/index.ts | 3 +- src/rust-crypto/rust-crypto.ts | 2 +- 6 files changed, 26 insertions(+), 19 deletions(-) rename src/{crypto/recoverykey.ts => crypto-api/recovery-key.ts} (70%) diff --git a/src/client.ts b/src/client.ts index ca506caa042..42e0d6789b2 100644 --- a/src/client.ts +++ b/src/client.ts @@ -85,7 +85,6 @@ import { isCryptoAvailable, } from "./crypto/index.ts"; import { DeviceInfo } from "./crypto/deviceinfo.ts"; -import { decodeRecoveryKey } from "./crypto/recoverykey.ts"; import { keyFromAuthData } from "./crypto/key_passphrase.ts"; import { User, UserEvent, UserEventHandlerMap } from "./models/user.ts"; import { getHttpUriForMxc } from "./content-repo.ts"; @@ -223,7 +222,13 @@ import { LocalNotificationSettings } from "./@types/local_notifications.ts"; import { buildFeatureSupportMap, Feature, ServerSupport } from "./feature.ts"; import { BackupDecryptor, CryptoBackend } from "./common-crypto/CryptoBackend.ts"; import { RUST_SDK_STORE_PREFIX } from "./rust-crypto/constants.ts"; -import { BootstrapCrossSigningOpts, CrossSigningKeyInfo, CryptoApi, ImportRoomKeysOpts } from "./crypto-api/index.ts"; +import { + BootstrapCrossSigningOpts, + CrossSigningKeyInfo, + CryptoApi, + decodeRecoveryKey, + ImportRoomKeysOpts, +} from "./crypto-api/index.ts"; import { DeviceInfoMap } from "./crypto/DeviceList.ts"; import { AddSecretStorageKeyOpts, diff --git a/src/crypto-api/index.ts b/src/crypto-api/index.ts index 6b9db3811dc..1b1340aa184 100644 --- a/src/crypto-api/index.ts +++ b/src/crypto-api/index.ts @@ -967,3 +967,4 @@ export interface OwnDeviceKeys { export * from "./verification.ts"; export * from "./keybackup.ts"; +export * from "./recovery-key.ts"; diff --git a/src/crypto/recoverykey.ts b/src/crypto-api/recovery-key.ts similarity index 70% rename from src/crypto/recoverykey.ts rename to src/crypto-api/recovery-key.ts index 3d7c12d4acf..9578a484c23 100644 --- a/src/crypto/recoverykey.ts +++ b/src/crypto-api/recovery-key.ts @@ -1,18 +1,18 @@ /* -Copyright 2018 New Vector Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ + * Copyright 2024 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ import bs58 from "bs58"; diff --git a/src/crypto/backup.ts b/src/crypto/backup.ts index 3ac6a3ddc0b..b7bbb7e55c3 100644 --- a/src/crypto/backup.ts +++ b/src/crypto/backup.ts @@ -27,7 +27,6 @@ import { DeviceTrustLevel } from "./CrossSigning.ts"; import { keyFromPassphrase } from "./key_passphrase.ts"; import { encodeUri, safeSet, sleep } from "../utils.ts"; import { IndexedDBCryptoStore } from "./store/indexeddb-crypto-store.ts"; -import { encodeRecoveryKey } from "./recoverykey.ts"; import { calculateKeyCheck, decryptAES, encryptAES, IEncryptedPayload } from "./aes.ts"; import { Curve25519SessionData, @@ -41,6 +40,7 @@ import { CryptoEvent } from "./index.ts"; import { ClientPrefix, HTTPError, MatrixError, Method } from "../http-api/index.ts"; import { BackupTrustInfo } from "../crypto-api/keybackup.ts"; import { BackupDecryptor } from "../common-crypto/CryptoBackend.ts"; +import { encodeRecoveryKey } from "../crypto-api"; const KEY_BACKUP_KEYS_PER_REQUEST = 200; const KEY_BACKUP_CHECK_RATE_LIMIT = 5000; // ms diff --git a/src/crypto/index.ts b/src/crypto/index.ts index 420160c0de4..d72e41a6e3d 100644 --- a/src/crypto/index.ts +++ b/src/crypto/index.ts @@ -42,7 +42,6 @@ import { VerificationBase } from "./verification/Base.ts"; import { ReciprocateQRCode, SCAN_QR_CODE_METHOD, SHOW_QR_CODE_METHOD } from "./verification/QRCode.ts"; import { SAS as SASVerification } from "./verification/SAS.ts"; import { keyFromPassphrase } from "./key_passphrase.ts"; -import { decodeRecoveryKey, encodeRecoveryKey } from "./recoverykey.ts"; import { VerificationRequest } from "./verification/request/VerificationRequest.ts"; import { InRoomChannel, InRoomRequests } from "./verification/request/InRoomChannel.ts"; import { Request, ToDeviceChannel, ToDeviceRequests } from "./verification/request/ToDeviceChannel.ts"; @@ -89,8 +88,10 @@ import { BootstrapCrossSigningOpts, CrossSigningKeyInfo, CrossSigningStatus, + decodeRecoveryKey, DecryptionFailureCode, DeviceVerificationStatus, + encodeRecoveryKey, EventEncryptionInfo, EventShieldColour, EventShieldReason, diff --git a/src/rust-crypto/rust-crypto.ts b/src/rust-crypto/rust-crypto.ts index c43b3911c26..a8fe10f0506 100644 --- a/src/rust-crypto/rust-crypto.ts +++ b/src/rust-crypto/rust-crypto.ts @@ -58,6 +58,7 @@ import { OwnDeviceKeys, UserVerificationStatus, VerificationRequest, + encodeRecoveryKey, } from "../crypto-api/index.ts"; import { deviceKeysToDeviceMap, rustDeviceToJsDevice } from "./device-converter.ts"; import { IDownloadKeyResult, IQueryKeysRequest } from "../client.ts"; @@ -66,7 +67,6 @@ import { SECRET_STORAGE_ALGORITHM_V1_AES, ServerSideSecretStorage } from "../sec import { CrossSigningIdentity } from "./CrossSigningIdentity.ts"; import { secretStorageCanAccessSecrets, secretStorageContainsCrossSigningKeys } from "./secret-storage.ts"; import { keyFromPassphrase } from "../crypto/key_passphrase.ts"; -import { encodeRecoveryKey } from "../crypto/recoverykey.ts"; import { isVerificationEvent, RustVerificationRequest, verificationMethodIdentifierToMethod } from "./verification.ts"; import { EventType, MsgType } from "../@types/event.ts"; import { CryptoEvent } from "../crypto/index.ts"; From 59384a4a77b236284eff4dede9e450a7a2f503c2 Mon Sep 17 00:00:00 2001 From: Florian Duros Date: Thu, 12 Sep 2024 10:54:37 +0200 Subject: [PATCH 2/8] Re-export `crypto-api/recovery-key` into `crypto/recoverykey` --- src/crypto/recoverykey.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/crypto/recoverykey.ts diff --git a/src/crypto/recoverykey.ts b/src/crypto/recoverykey.ts new file mode 100644 index 00000000000..6ce5d3f07e6 --- /dev/null +++ b/src/crypto/recoverykey.ts @@ -0,0 +1,18 @@ +/* +Copyright 2018 New Vector Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Re-export to avoid breaking changes +export * from "../crypto-api/recovery-key.ts"; From 50d8b5b34bc13639f467c335421cbf25c1ff565e Mon Sep 17 00:00:00 2001 From: Florian Duros Date: Thu, 12 Sep 2024 14:32:22 +0200 Subject: [PATCH 3/8] Add a bit of doc --- src/crypto-api/recovery-key.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/crypto-api/recovery-key.ts b/src/crypto-api/recovery-key.ts index 9578a484c23..ded9178fe4f 100644 --- a/src/crypto-api/recovery-key.ts +++ b/src/crypto-api/recovery-key.ts @@ -21,6 +21,10 @@ import bs58 from "bs58"; const OLM_RECOVERY_KEY_PREFIX = [0x8b, 0x01]; const KEY_SIZE = 32; +/** + * Encode a recovery key using base58 encoding. + * @param key + */ export function encodeRecoveryKey(key: ArrayLike): string | undefined { const buf = Buffer.alloc(OLM_RECOVERY_KEY_PREFIX.length + key.length + 1); buf.set(OLM_RECOVERY_KEY_PREFIX, 0); @@ -36,6 +40,10 @@ export function encodeRecoveryKey(key: ArrayLike): string | undefined { return base58key.match(/.{1,4}/g)?.join(" "); } +/** + * Decode a recovery key from base58 encoding. + * @param recoveryKey + */ export function decodeRecoveryKey(recoveryKey: string): Uint8Array { const result = bs58.decode(recoveryKey.replace(/ /g, "")); From e60af5ab3162a4ee42a7bc044950739fc3ef78c1 Mon Sep 17 00:00:00 2001 From: Florian Duros Date: Thu, 12 Sep 2024 14:42:47 +0200 Subject: [PATCH 4/8] Deprecate `MatrixClient.isValidRecoveryKey` and `MatrixClient.keyBackupKeyFromRecoveryKey` --- src/client.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/client.ts b/src/client.ts index 42e0d6789b2..6746e505bcd 100644 --- a/src/client.ts +++ b/src/client.ts @@ -3632,6 +3632,12 @@ export class MatrixClient extends TypedEventEmitter Date: Thu, 12 Sep 2024 17:33:16 +0200 Subject: [PATCH 5/8] Import `index.ts` directly --- src/crypto/backup.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crypto/backup.ts b/src/crypto/backup.ts index b7bbb7e55c3..2dc374f9868 100644 --- a/src/crypto/backup.ts +++ b/src/crypto/backup.ts @@ -40,7 +40,7 @@ import { CryptoEvent } from "./index.ts"; import { ClientPrefix, HTTPError, MatrixError, Method } from "../http-api/index.ts"; import { BackupTrustInfo } from "../crypto-api/keybackup.ts"; import { BackupDecryptor } from "../common-crypto/CryptoBackend.ts"; -import { encodeRecoveryKey } from "../crypto-api"; +import { encodeRecoveryKey } from "../crypto-api/index.ts"; const KEY_BACKUP_KEYS_PER_REQUEST = 200; const KEY_BACKUP_CHECK_RATE_LIMIT = 5000; // ms From 87bd00ebb691243a63866d413dcdee219c00a867 Mon Sep 17 00:00:00 2001 From: Florian Duros Date: Thu, 12 Sep 2024 17:34:49 +0200 Subject: [PATCH 6/8] Update `recovery-key.ts` doc --- src/crypto-api/recovery-key.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/crypto-api/recovery-key.ts b/src/crypto-api/recovery-key.ts index ded9178fe4f..4b27b5a8ef8 100644 --- a/src/crypto-api/recovery-key.ts +++ b/src/crypto-api/recovery-key.ts @@ -22,7 +22,7 @@ const OLM_RECOVERY_KEY_PREFIX = [0x8b, 0x01]; const KEY_SIZE = 32; /** - * Encode a recovery key using base58 encoding. + * Encode a recovery key using the Matrix {@link https://spec.matrix.org/v1.11/appendices/#cryptographic-key-representation | Cryptographic key representation} * @param key */ export function encodeRecoveryKey(key: ArrayLike): string | undefined { @@ -41,7 +41,7 @@ export function encodeRecoveryKey(key: ArrayLike): string | undefined { } /** - * Decode a recovery key from base58 encoding. + * Decode a recovery key encoded with the Matrix {@link https://spec.matrix.org/v1.11/appendices/#cryptographic-key-representation | Cryptographic key representation} encoding. * @param recoveryKey */ export function decodeRecoveryKey(recoveryKey: string): Uint8Array { From b46f5d6efc2426565428259128599996e53872d6 Mon Sep 17 00:00:00 2001 From: Florian Duros Date: Thu, 12 Sep 2024 18:14:32 +0200 Subject: [PATCH 7/8] Add tests for `decodeRecoveryKey` --- spec/unit/rust-crypto/recovery-key.spec.ts | 44 ++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 spec/unit/rust-crypto/recovery-key.spec.ts diff --git a/spec/unit/rust-crypto/recovery-key.spec.ts b/spec/unit/rust-crypto/recovery-key.spec.ts new file mode 100644 index 00000000000..c488b7d06fe --- /dev/null +++ b/spec/unit/rust-crypto/recovery-key.spec.ts @@ -0,0 +1,44 @@ +/* + * Copyright 2024 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { decodeRecoveryKey, encodeRecoveryKey } from "../../../src/crypto-api"; + +describe("recovery key", () => { + describe("decodeRecoveryKey", () => { + it("should thrown an incorrect length error", () => { + const key = [0, 1]; + const encodedKey = encodeRecoveryKey(key)!; + + expect(() => decodeRecoveryKey(encodedKey)).toThrow("Incorrect length"); + }); + + it("should thrown an incorrect parity", () => { + const key = Array.from({ length: 32 }, (_, i) => i); + let encodedKey = encodeRecoveryKey(key)!; + // Mutate the encoded key to have incorrect parity + encodedKey = encodedKey.replace("EsSz", "EsSZ"); + + expect(() => decodeRecoveryKey(encodedKey!)).toThrow("Incorrect parity"); + }); + + it("should decode a valid encoded key", () => { + const key = Array.from({ length: 32 }, (_, i) => i); + const encodedKey = encodeRecoveryKey(key)!; + + expect(decodeRecoveryKey(encodedKey)).toEqual(new Uint8Array(key)); + }); + }); +}); From cee26e510af87d404b1ba536550374923cb65e14 Mon Sep 17 00:00:00 2001 From: Florian Duros Date: Fri, 13 Sep 2024 11:37:59 +0200 Subject: [PATCH 8/8] Move `recovery-key.spec.ts` file --- spec/unit/{rust-crypto => crypto-api}/recovery-key.spec.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename spec/unit/{rust-crypto => crypto-api}/recovery-key.spec.ts (100%) diff --git a/spec/unit/rust-crypto/recovery-key.spec.ts b/spec/unit/crypto-api/recovery-key.spec.ts similarity index 100% rename from spec/unit/rust-crypto/recovery-key.spec.ts rename to spec/unit/crypto-api/recovery-key.spec.ts