You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-11-26 17:03:12 +03:00
Moar typescriptification
This commit is contained in:
@@ -114,7 +114,7 @@ import url from "url";
|
|||||||
import { randomString } from "./randomstring";
|
import { randomString } from "./randomstring";
|
||||||
import { ReadStream } from "fs";
|
import { ReadStream } from "fs";
|
||||||
import { WebStorageSessionStore } from "./store/session/webstorage";
|
import { WebStorageSessionStore } from "./store/session/webstorage";
|
||||||
import { BackupManager, IKeyBackupCheck, TrustInfo } from "./crypto/backup";
|
import { BackupManager, IKeyBackupCheck, IPreparedKeyBackupVersion, TrustInfo } from "./crypto/backup";
|
||||||
import { DEFAULT_TREE_POWER_LEVELS_TEMPLATE, MSC3089TreeSpace } from "./models/MSC3089TreeSpace";
|
import { DEFAULT_TREE_POWER_LEVELS_TEMPLATE, MSC3089TreeSpace } from "./models/MSC3089TreeSpace";
|
||||||
|
|
||||||
export type Store = StubStore | MemoryStore | LocalIndexedDBStoreBackend | RemoteIndexedDBStoreBackend;
|
export type Store = StubStore | MemoryStore | LocalIndexedDBStoreBackend | RemoteIndexedDBStoreBackend;
|
||||||
@@ -2180,7 +2180,7 @@ export class MatrixClient extends EventEmitter {
|
|||||||
public async prepareKeyBackupVersion(
|
public async prepareKeyBackupVersion(
|
||||||
password: string,
|
password: string,
|
||||||
opts: IKeyBackupPrepareOpts = { secureSecretStorage: false },
|
opts: IKeyBackupPrepareOpts = { secureSecretStorage: false },
|
||||||
): Promise<IKeyBackupVersion> {
|
): Promise<Pick<IPreparedKeyBackupVersion, "algorithm" | "auth_data" | "recovery_key">> {
|
||||||
if (!this.crypto) {
|
if (!this.crypto) {
|
||||||
throw new Error("End-to-end encryption disabled");
|
throw new Error("End-to-end encryption disabled");
|
||||||
}
|
}
|
||||||
@@ -2198,7 +2198,7 @@ export class MatrixClient extends EventEmitter {
|
|||||||
algorithm,
|
algorithm,
|
||||||
auth_data,
|
auth_data,
|
||||||
recovery_key,
|
recovery_key,
|
||||||
} as any; // TODO: Types
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2313,7 +2313,7 @@ export class MatrixClient extends EventEmitter {
|
|||||||
* Back up session keys to the homeserver.
|
* Back up session keys to the homeserver.
|
||||||
* @param {string} roomId ID of the room that the keys are for Optional.
|
* @param {string} roomId ID of the room that the keys are for Optional.
|
||||||
* @param {string} sessionId ID of the session that the keys are for Optional.
|
* @param {string} sessionId ID of the session that the keys are for Optional.
|
||||||
* @param {integer} version backup version Optional.
|
* @param {number} version backup version Optional.
|
||||||
* @param {object} data Object keys to send
|
* @param {object} data Object keys to send
|
||||||
* @return {Promise} a promise that will resolve when the keys
|
* @return {Promise} a promise that will resolve when the keys
|
||||||
* are uploaded
|
* are uploaded
|
||||||
@@ -2388,7 +2388,7 @@ export class MatrixClient extends EventEmitter {
|
|||||||
* @param {string} recoveryKey The recovery key
|
* @param {string} recoveryKey The recovery key
|
||||||
* @return {Uint8Array} key backup key
|
* @return {Uint8Array} key backup key
|
||||||
*/
|
*/
|
||||||
public keyBackupKeyFromRecoveryKey(recoveryKey: string): Uint8Array {
|
public keyBackupKeyFromRecoveryKey(recoveryKey: string): ArrayLike<number> {
|
||||||
return decodeRecoveryKey(recoveryKey);
|
return decodeRecoveryKey(recoveryKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2478,9 +2478,7 @@ export class MatrixClient extends EventEmitter {
|
|||||||
opts: IKeyBackupRestoreOpts,
|
opts: IKeyBackupRestoreOpts,
|
||||||
): Promise<IKeyBackupRestoreResult> {
|
): Promise<IKeyBackupRestoreResult> {
|
||||||
const privKey = decodeRecoveryKey(recoveryKey);
|
const privKey = decodeRecoveryKey(recoveryKey);
|
||||||
return this.restoreKeyBackup(
|
return this.restoreKeyBackup(privKey, targetRoomId, targetSessionId, backupInfo, opts);
|
||||||
privKey, targetRoomId, targetSessionId, backupInfo, opts,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Types
|
// TODO: Types
|
||||||
@@ -2498,7 +2496,7 @@ export class MatrixClient extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async restoreKeyBackup(
|
private async restoreKeyBackup(
|
||||||
privKey: Uint8Array,
|
privKey: ArrayLike<number>,
|
||||||
targetRoomId: string,
|
targetRoomId: string,
|
||||||
targetSessionId: string,
|
targetSessionId: string,
|
||||||
backupInfo: IKeyBackupVersion,
|
backupInfo: IKeyBackupVersion,
|
||||||
|
|||||||
@@ -296,7 +296,7 @@ export class CrossSigningInfo extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const privateKeys: Record<string, Uint8Array> = {};
|
const privateKeys: Record<string, Uint8Array> = {};
|
||||||
const keys: Record<string, object> = {};
|
const keys: Record<string, any> = {}; // TODO types
|
||||||
let masterSigning;
|
let masterSigning;
|
||||||
let masterPub;
|
let masterPub;
|
||||||
|
|
||||||
@@ -719,12 +719,12 @@ export function createCryptoStoreCacheCallbacks(store: CryptoStore, olmDevice: O
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
const pickleKey = Buffer.from(olmDevice._pickleKey);
|
const pickleKey = Buffer.from(olmDevice._pickleKey);
|
||||||
key = await encryptAES(encodeBase64(key), pickleKey, type);
|
const encryptedKey = await encryptAES(encodeBase64(key), pickleKey, type);
|
||||||
return store.doTxn(
|
return store.doTxn(
|
||||||
'readwrite',
|
'readwrite',
|
||||||
[IndexedDBCryptoStore.STORE_ACCOUNT],
|
[IndexedDBCryptoStore.STORE_ACCOUNT],
|
||||||
(txn) => {
|
(txn) => {
|
||||||
store.storeSecretStorePrivateKey(txn, type, key);
|
store.storeSecretStorePrivateKey(txn, type, encryptedKey);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
Copyright 2020 - 2021 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -14,6 +14,8 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import type { BinaryLike } from "crypto";
|
||||||
|
|
||||||
import { getCrypto } from '../utils';
|
import { getCrypto } from '../utils';
|
||||||
import { decodeBase64, encodeBase64 } from './olmlib';
|
import { decodeBase64, encodeBase64 } from './olmlib';
|
||||||
|
|
||||||
@@ -23,6 +25,12 @@ const subtleCrypto = (typeof window !== "undefined" && window.crypto) ?
|
|||||||
// salt for HKDF, with 8 bytes of zeros
|
// salt for HKDF, with 8 bytes of zeros
|
||||||
const zeroSalt = new Uint8Array(8);
|
const zeroSalt = new Uint8Array(8);
|
||||||
|
|
||||||
|
interface IEncryptedPayload {
|
||||||
|
iv: string;
|
||||||
|
ciphertext: string;
|
||||||
|
mac: string;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* encrypt a string in Node.js
|
* encrypt a string in Node.js
|
||||||
*
|
*
|
||||||
@@ -31,7 +39,7 @@ const zeroSalt = new Uint8Array(8);
|
|||||||
* @param {string} name the name of the secret
|
* @param {string} name the name of the secret
|
||||||
* @param {string} ivStr the initialization vector to use
|
* @param {string} ivStr the initialization vector to use
|
||||||
*/
|
*/
|
||||||
async function encryptNode(data: string, key: Uint8Array, name: string, ivStr?: string) {
|
async function encryptNode(data: string, key: Uint8Array, name: string, ivStr?: string): Promise<IEncryptedPayload> {
|
||||||
const crypto = getCrypto();
|
const crypto = getCrypto();
|
||||||
if (!crypto) {
|
if (!crypto) {
|
||||||
throw new Error("No usable crypto implementation");
|
throw new Error("No usable crypto implementation");
|
||||||
@@ -77,7 +85,7 @@ async function encryptNode(data: string, key: Uint8Array, name: string, ivStr?:
|
|||||||
* @param {Uint8Array} key the encryption key to use
|
* @param {Uint8Array} key the encryption key to use
|
||||||
* @param {string} name the name of the secret
|
* @param {string} name the name of the secret
|
||||||
*/
|
*/
|
||||||
async function decryptNode(data: IData, key: Uint8Array, name: string) {
|
async function decryptNode(data: IEncryptedPayload, key: Uint8Array, name: string): Promise<string> {
|
||||||
const crypto = getCrypto();
|
const crypto = getCrypto();
|
||||||
if (!crypto) {
|
if (!crypto) {
|
||||||
throw new Error("No usable crypto implementation");
|
throw new Error("No usable crypto implementation");
|
||||||
@@ -100,10 +108,9 @@ async function decryptNode(data: IData, key: Uint8Array, name: string) {
|
|||||||
+ decipher.final("utf8");
|
+ decipher.final("utf8");
|
||||||
}
|
}
|
||||||
|
|
||||||
function deriveKeysNode(key, name) {
|
function deriveKeysNode(key: BinaryLike, name: string): [Buffer, Buffer] {
|
||||||
const crypto = getCrypto();
|
const crypto = getCrypto();
|
||||||
const prk = crypto.createHmac("sha256", zeroSalt)
|
const prk = crypto.createHmac("sha256", zeroSalt).update(key).digest();
|
||||||
.update(key).digest();
|
|
||||||
|
|
||||||
const b = Buffer.alloc(1, 1);
|
const b = Buffer.alloc(1, 1);
|
||||||
const aesKey = crypto.createHmac("sha256", prk)
|
const aesKey = crypto.createHmac("sha256", prk)
|
||||||
@@ -123,7 +130,7 @@ function deriveKeysNode(key, name) {
|
|||||||
* @param {string} name the name of the secret
|
* @param {string} name the name of the secret
|
||||||
* @param {string} ivStr the initialization vector to use
|
* @param {string} ivStr the initialization vector to use
|
||||||
*/
|
*/
|
||||||
async function encryptBrowser(data: string, key: Uint8Array, name: string, ivStr?: string) {
|
async function encryptBrowser(data: string, key: Uint8Array, name: string, ivStr?: string): Promise<IEncryptedPayload> {
|
||||||
let iv;
|
let iv;
|
||||||
if (ivStr) {
|
if (ivStr) {
|
||||||
iv = decodeBase64(ivStr);
|
iv = decodeBase64(ivStr);
|
||||||
@@ -163,12 +170,6 @@ async function encryptBrowser(data: string, key: Uint8Array, name: string, ivStr
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IData {
|
|
||||||
ciphertext: string;
|
|
||||||
iv: string;
|
|
||||||
mac: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* decrypt a string in the browser
|
* decrypt a string in the browser
|
||||||
*
|
*
|
||||||
@@ -179,7 +180,7 @@ interface IData {
|
|||||||
* @param {Uint8Array} key the encryption key to use
|
* @param {Uint8Array} key the encryption key to use
|
||||||
* @param {string} name the name of the secret
|
* @param {string} name the name of the secret
|
||||||
*/
|
*/
|
||||||
async function decryptBrowser(data: IData, key: Uint8Array, name: string) {
|
async function decryptBrowser(data: IEncryptedPayload, key: Uint8Array, name: string): Promise<string> {
|
||||||
const [aesKey, hmacKey] = await deriveKeysBrowser(key, name);
|
const [aesKey, hmacKey] = await deriveKeysBrowser(key, name);
|
||||||
|
|
||||||
const ciphertext = decodeBase64(data.ciphertext);
|
const ciphertext = decodeBase64(data.ciphertext);
|
||||||
@@ -206,7 +207,7 @@ async function decryptBrowser(data: IData, key: Uint8Array, name: string) {
|
|||||||
return new TextDecoder().decode(new Uint8Array(plaintext));
|
return new TextDecoder().decode(new Uint8Array(plaintext));
|
||||||
}
|
}
|
||||||
|
|
||||||
async function deriveKeysBrowser(key, name) {
|
async function deriveKeysBrowser(key: Uint8Array, name: string): Promise<[CryptoKey, CryptoKey]> {
|
||||||
const hkdfkey = await subtleCrypto.importKey(
|
const hkdfkey = await subtleCrypto.importKey(
|
||||||
'raw',
|
'raw',
|
||||||
key,
|
key,
|
||||||
@@ -252,11 +253,11 @@ async function deriveKeysBrowser(key, name) {
|
|||||||
return await Promise.all([aesProm, hmacProm]);
|
return await Promise.all([aesProm, hmacProm]);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function encryptAES(data: string, key: Uint8Array, name: string, ivStr?: string) {
|
export function encryptAES(data: string, key: Uint8Array, name: string, ivStr?: string): Promise<IEncryptedPayload> {
|
||||||
return subtleCrypto ? encryptBrowser(data, key, name, ivStr) : encryptNode(data, key, name, ivStr);
|
return subtleCrypto ? encryptBrowser(data, key, name, ivStr) : encryptNode(data, key, name, ivStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function decryptAES(data: IData, key: Uint8Array, name: string) {
|
export function decryptAES(data: IEncryptedPayload, key: Uint8Array, name: string): Promise<string> {
|
||||||
return subtleCrypto ? decryptBrowser(data, key, name) : decryptNode(data, key, name);
|
return subtleCrypto ? decryptBrowser(data, key, name) : decryptNode(data, key, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,16 +29,11 @@ import { keyFromPassphrase } from './key_passphrase';
|
|||||||
import { sleep } from "../utils";
|
import { sleep } from "../utils";
|
||||||
import { IndexedDBCryptoStore } from './store/indexeddb-crypto-store';
|
import { IndexedDBCryptoStore } from './store/indexeddb-crypto-store';
|
||||||
import { encodeRecoveryKey } from './recoverykey';
|
import { encodeRecoveryKey } from './recoverykey';
|
||||||
|
import { IKeyBackupVersion } from "./keybackup";
|
||||||
|
|
||||||
const KEY_BACKUP_KEYS_PER_REQUEST = 200;
|
const KEY_BACKUP_KEYS_PER_REQUEST = 200;
|
||||||
|
|
||||||
type AuthData = Record<string, any>;
|
type AuthData = IKeyBackupVersion["auth_data"];
|
||||||
|
|
||||||
type BackupInfo = {
|
|
||||||
algorithm: string,
|
|
||||||
auth_data: AuthData, // eslint-disable-line camelcase
|
|
||||||
[properties: string]: any,
|
|
||||||
};
|
|
||||||
|
|
||||||
type SigInfo = {
|
type SigInfo = {
|
||||||
deviceId: string,
|
deviceId: string,
|
||||||
@@ -54,13 +49,22 @@ export type TrustInfo = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export interface IKeyBackupCheck {
|
export interface IKeyBackupCheck {
|
||||||
backupInfo: BackupInfo;
|
backupInfo: IKeyBackupVersion;
|
||||||
trustInfo: TrustInfo;
|
trustInfo: TrustInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* eslint-disable camelcase */
|
||||||
|
export interface IPreparedKeyBackupVersion {
|
||||||
|
algorithm: string;
|
||||||
|
auth_data: AuthData;
|
||||||
|
recovery_key: string;
|
||||||
|
privateKey: Uint8Array;
|
||||||
|
}
|
||||||
|
/* eslint-enable camelcase */
|
||||||
|
|
||||||
/** A function used to get the secret key for a backup.
|
/** A function used to get the secret key for a backup.
|
||||||
*/
|
*/
|
||||||
type GetKey = () => Promise<Uint8Array>;
|
type GetKey = () => Promise<ArrayLike<number>>;
|
||||||
|
|
||||||
interface BackupAlgorithmClass {
|
interface BackupAlgorithmClass {
|
||||||
algorithmName: string;
|
algorithmName: string;
|
||||||
@@ -77,7 +81,7 @@ interface BackupAlgorithm {
|
|||||||
encryptSession(data: Record<string, any>): Promise<any>;
|
encryptSession(data: Record<string, any>): Promise<any>;
|
||||||
decryptSessions(ciphertexts: Record<string, any>): Promise<Record<string, any>[]>;
|
decryptSessions(ciphertexts: Record<string, any>): Promise<Record<string, any>[]>;
|
||||||
authData: AuthData;
|
authData: AuthData;
|
||||||
keyMatches(key: Uint8Array): Promise<boolean>;
|
keyMatches(key: ArrayLike<number>): Promise<boolean>;
|
||||||
free(): void;
|
free(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +90,7 @@ interface BackupAlgorithm {
|
|||||||
*/
|
*/
|
||||||
export class BackupManager {
|
export class BackupManager {
|
||||||
private algorithm: BackupAlgorithm | undefined;
|
private algorithm: BackupAlgorithm | undefined;
|
||||||
public backupInfo: BackupInfo | undefined; // The info dict from /room_keys/version
|
public backupInfo: IKeyBackupVersion | undefined; // The info dict from /room_keys/version
|
||||||
public checkedForBackup: boolean; // Have we checked the server for a backup we can use?
|
public checkedForBackup: boolean; // Have we checked the server for a backup we can use?
|
||||||
private sendingBackups: boolean; // Are we currently sending backups?
|
private sendingBackups: boolean; // Are we currently sending backups?
|
||||||
constructor(private readonly baseApis: MatrixClient, public readonly getKey: GetKey) {
|
constructor(private readonly baseApis: MatrixClient, public readonly getKey: GetKey) {
|
||||||
@@ -98,7 +102,7 @@ export class BackupManager {
|
|||||||
return this.backupInfo && this.backupInfo.version;
|
return this.backupInfo && this.backupInfo.version;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async makeAlgorithm(info: BackupInfo, getKey: GetKey): Promise<BackupAlgorithm> {
|
public static async makeAlgorithm(info: IKeyBackupVersion, getKey: GetKey): Promise<BackupAlgorithm> {
|
||||||
const Algorithm = algorithmsByName[info.algorithm];
|
const Algorithm = algorithmsByName[info.algorithm];
|
||||||
if (!Algorithm) {
|
if (!Algorithm) {
|
||||||
throw new Error("Unknown backup algorithm");
|
throw new Error("Unknown backup algorithm");
|
||||||
@@ -106,7 +110,7 @@ export class BackupManager {
|
|||||||
return await Algorithm.init(info.auth_data, getKey);
|
return await Algorithm.init(info.auth_data, getKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async enableKeyBackup(info: BackupInfo): Promise<void> {
|
public async enableKeyBackup(info: IKeyBackupVersion): Promise<void> {
|
||||||
this.backupInfo = info;
|
this.backupInfo = info;
|
||||||
if (this.algorithm) {
|
if (this.algorithm) {
|
||||||
this.algorithm.free();
|
this.algorithm.free();
|
||||||
@@ -145,7 +149,8 @@ export class BackupManager {
|
|||||||
public async prepareKeyBackupVersion(
|
public async prepareKeyBackupVersion(
|
||||||
key?: string | Uint8Array | null,
|
key?: string | Uint8Array | null,
|
||||||
algorithm?: string | undefined,
|
algorithm?: string | undefined,
|
||||||
): Promise<BackupInfo> {
|
// eslint-disable-next-line camelcase
|
||||||
|
): Promise<IPreparedKeyBackupVersion> {
|
||||||
const Algorithm = algorithm ? algorithmsByName[algorithm] : DefaultAlgorithm;
|
const Algorithm = algorithm ? algorithmsByName[algorithm] : DefaultAlgorithm;
|
||||||
if (!Algorithm) {
|
if (!Algorithm) {
|
||||||
throw new Error("Unknown backup algorithm");
|
throw new Error("Unknown backup algorithm");
|
||||||
@@ -161,7 +166,7 @@ export class BackupManager {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public async createKeyBackupVersion(info: BackupInfo): Promise<void> {
|
public async createKeyBackupVersion(info: IKeyBackupVersion): Promise<void> {
|
||||||
this.algorithm = await BackupManager.makeAlgorithm(info, this.getKey);
|
this.algorithm = await BackupManager.makeAlgorithm(info, this.getKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,14 +176,14 @@ export class BackupManager {
|
|||||||
* one of the user's verified devices, start backing up
|
* one of the user's verified devices, start backing up
|
||||||
* to it.
|
* to it.
|
||||||
*/
|
*/
|
||||||
public async checkAndStart(): Promise<{backupInfo: BackupInfo, trustInfo: TrustInfo}> {
|
public async checkAndStart(): Promise<IKeyBackupCheck> {
|
||||||
logger.log("Checking key backup status...");
|
logger.log("Checking key backup status...");
|
||||||
if (this.baseApis.isGuest()) {
|
if (this.baseApis.isGuest()) {
|
||||||
logger.log("Skipping key backup check since user is guest");
|
logger.log("Skipping key backup check since user is guest");
|
||||||
this.checkedForBackup = true;
|
this.checkedForBackup = true;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
let backupInfo: BackupInfo;
|
let backupInfo: IKeyBackupVersion;
|
||||||
try {
|
try {
|
||||||
backupInfo = await this.baseApis.getKeyBackupVersion();
|
backupInfo = await this.baseApis.getKeyBackupVersion();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -255,7 +260,7 @@ export class BackupManager {
|
|||||||
* ]
|
* ]
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
public async isKeyBackupTrusted(backupInfo: BackupInfo): Promise<TrustInfo> {
|
public async isKeyBackupTrusted(backupInfo: IKeyBackupVersion): Promise<TrustInfo> {
|
||||||
const ret = {
|
const ret = {
|
||||||
usable: false,
|
usable: false,
|
||||||
trusted_locally: false,
|
trusted_locally: false,
|
||||||
@@ -569,7 +574,7 @@ export class Curve25519 implements BackupAlgorithm {
|
|||||||
): Promise<[Uint8Array, AuthData]> {
|
): Promise<[Uint8Array, AuthData]> {
|
||||||
const decryption = new global.Olm.PkDecryption();
|
const decryption = new global.Olm.PkDecryption();
|
||||||
try {
|
try {
|
||||||
const authData: AuthData = {};
|
const authData: Partial<AuthData> = {};
|
||||||
if (!key) {
|
if (!key) {
|
||||||
authData.public_key = decryption.generate_key();
|
authData.public_key = decryption.generate_key();
|
||||||
} else if (key instanceof Uint8Array) {
|
} else if (key instanceof Uint8Array) {
|
||||||
@@ -585,7 +590,7 @@ export class Curve25519 implements BackupAlgorithm {
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
decryption.get_private_key(),
|
decryption.get_private_key(),
|
||||||
authData,
|
authData as AuthData,
|
||||||
];
|
];
|
||||||
} finally {
|
} finally {
|
||||||
decryption.free();
|
decryption.free();
|
||||||
|
|||||||
@@ -138,11 +138,6 @@ interface IDeviceVerificationUpgrade {
|
|||||||
* could be established
|
* could be established
|
||||||
*/
|
*/
|
||||||
|
|
||||||
interface IOlmSessionResult {
|
|
||||||
device: DeviceInfo;
|
|
||||||
sessionId?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IUserOlmSession {
|
interface IUserOlmSession {
|
||||||
deviceIdKey: string;
|
deviceIdKey: string;
|
||||||
sessions: {
|
sessions: {
|
||||||
@@ -1079,17 +1074,17 @@ export class Crypto extends EventEmitter {
|
|||||||
* @param {Uint8Array} key the private key
|
* @param {Uint8Array} key the private key
|
||||||
* @returns {Promise} so you can catch failures
|
* @returns {Promise} so you can catch failures
|
||||||
*/
|
*/
|
||||||
public async storeSessionBackupPrivateKey(key: Uint8Array): Promise<void> {
|
public async storeSessionBackupPrivateKey(key: ArrayLike<number>): Promise<void> {
|
||||||
if (!(key instanceof Uint8Array)) {
|
if (!(key instanceof Uint8Array)) {
|
||||||
throw new Error(`storeSessionBackupPrivateKey expects Uint8Array, got ${key}`);
|
throw new Error(`storeSessionBackupPrivateKey expects Uint8Array, got ${key}`);
|
||||||
}
|
}
|
||||||
const pickleKey = Buffer.from(this.olmDevice._pickleKey);
|
const pickleKey = Buffer.from(this.olmDevice._pickleKey);
|
||||||
key = await encryptAES(olmlib.encodeBase64(key), pickleKey, "m.megolm_backup.v1");
|
const encryptedKey = await encryptAES(olmlib.encodeBase64(key), pickleKey, "m.megolm_backup.v1");
|
||||||
return this.cryptoStore.doTxn(
|
return this.cryptoStore.doTxn(
|
||||||
'readwrite',
|
'readwrite',
|
||||||
[IndexedDBCryptoStore.STORE_ACCOUNT],
|
[IndexedDBCryptoStore.STORE_ACCOUNT],
|
||||||
(txn) => {
|
(txn) => {
|
||||||
this.cryptoStore.storeSecretStorePrivateKey(txn, "m.megolm_backup.v1", key);
|
this.cryptoStore.storeSecretStorePrivateKey(txn, "m.megolm_backup.v1", encryptedKey);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -2573,7 +2568,7 @@ export class Crypto extends EventEmitter {
|
|||||||
* an Object mapping from userId to deviceId to
|
* an Object mapping from userId to deviceId to
|
||||||
* {@link module:crypto~OlmSessionResult}
|
* {@link module:crypto~OlmSessionResult}
|
||||||
*/
|
*/
|
||||||
ensureOlmSessionsForUsers(users: string[]): Promise<IOlmSessionResult> {
|
ensureOlmSessionsForUsers(users: string[]): Promise<Record<string, Record<string, olmlib.IOlmSessionResult>>> {
|
||||||
const devicesByUser = {};
|
const devicesByUser = {};
|
||||||
|
|
||||||
for (let i = 0; i < users.length; ++i) {
|
for (let i = 0; i < users.length; ++i) {
|
||||||
@@ -2598,9 +2593,7 @@ export class Crypto extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return olmlib.ensureOlmSessionsForDevices(
|
return olmlib.ensureOlmSessionsForDevices(this.olmDevice, this.baseApis, devicesByUser);
|
||||||
this.olmDevice, this.baseApis, devicesByUser,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -3259,9 +3252,7 @@ export class Crypto extends EventEmitter {
|
|||||||
}
|
}
|
||||||
const devicesByUser = {};
|
const devicesByUser = {};
|
||||||
devicesByUser[sender] = [device];
|
devicesByUser[sender] = [device];
|
||||||
await olmlib.ensureOlmSessionsForDevices(
|
await olmlib.ensureOlmSessionsForDevices(this.olmDevice, this.baseApis, devicesByUser, true);
|
||||||
this.olmDevice, this.baseApis, devicesByUser, true,
|
|
||||||
);
|
|
||||||
|
|
||||||
this.lastNewSessionForced[sender][deviceKey] = Date.now();
|
this.lastNewSessionForced[sender][deviceKey] = Date.now();
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ export interface IKeyBackupVersion {
|
|||||||
count: number;
|
count: number;
|
||||||
etag: string;
|
etag: string;
|
||||||
version: string; // number contained within
|
version: string; // number contained within
|
||||||
recovery_key: string;
|
|
||||||
}
|
}
|
||||||
/* eslint-enable camelcase */
|
/* eslint-enable camelcase */
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,11 @@ export const MEGOLM_ALGORITHM = Algorithm.Megolm;
|
|||||||
*/
|
*/
|
||||||
export const MEGOLM_BACKUP_ALGORITHM = Algorithm.MegolmBackup;
|
export const MEGOLM_BACKUP_ALGORITHM = Algorithm.MegolmBackup;
|
||||||
|
|
||||||
|
export interface IOlmSessionResult {
|
||||||
|
device: DeviceInfo;
|
||||||
|
sessionId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encrypt an event payload for an Olm device
|
* Encrypt an event payload for an Olm device
|
||||||
*
|
*
|
||||||
@@ -209,11 +214,11 @@ export async function ensureOlmSessionsForDevices(
|
|||||||
olmDevice: OlmDevice,
|
olmDevice: OlmDevice,
|
||||||
baseApis: MatrixClient,
|
baseApis: MatrixClient,
|
||||||
devicesByUser: Record<string, DeviceInfo[]>,
|
devicesByUser: Record<string, DeviceInfo[]>,
|
||||||
force: boolean,
|
force = false,
|
||||||
otkTimeout: number,
|
otkTimeout?: number,
|
||||||
failedServers: string[],
|
failedServers?: string[],
|
||||||
log: Logger,
|
log: Logger = logger,
|
||||||
) {
|
): Promise<Record<string, Record<string, IOlmSessionResult>>> {
|
||||||
if (typeof force === "number") {
|
if (typeof force === "number") {
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
// @ts-ignore - backwards compatibility
|
// @ts-ignore - backwards compatibility
|
||||||
@@ -224,9 +229,6 @@ export async function ensureOlmSessionsForDevices(
|
|||||||
otkTimeout = force;
|
otkTimeout = force;
|
||||||
force = false;
|
force = false;
|
||||||
}
|
}
|
||||||
if (!log) {
|
|
||||||
log = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
const devicesWithoutSession = [
|
const devicesWithoutSession = [
|
||||||
// [userId, deviceId], ...
|
// [userId, deviceId], ...
|
||||||
@@ -439,9 +441,9 @@ async function _verifyKeyAndStartSession(
|
|||||||
return sid;
|
return sid;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IObject {
|
export interface IObject {
|
||||||
unsigned: object;
|
unsigned?: object;
|
||||||
signatures: object;
|
signatures?: object;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -555,7 +557,7 @@ export function pkVerify(obj: IObject, pubKey: string, userId: string) {
|
|||||||
* @param {Uint8Array} uint8Array The data to encode.
|
* @param {Uint8Array} uint8Array The data to encode.
|
||||||
* @return {string} The base64.
|
* @return {string} The base64.
|
||||||
*/
|
*/
|
||||||
export function encodeBase64(uint8Array: ArrayBuffer): string {
|
export function encodeBase64(uint8Array: ArrayBuffer | Uint8Array): string {
|
||||||
return Buffer.from(uint8Array).toString("base64");
|
return Buffer.from(uint8Array).toString("base64");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export function encodeRecoveryKey(key: ArrayLike<number>): string {
|
|||||||
return base58key.match(/.{1,4}/g).join(" ");
|
return base58key.match(/.{1,4}/g).join(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function decodeRecoveryKey(recoveryKey: string): ArrayLike<number> {
|
export function decodeRecoveryKey(recoveryKey: string): Uint8Array {
|
||||||
const result = bs58.decode(recoveryKey.replace(/ /g, ''));
|
const result = bs58.decode(recoveryKey.replace(/ /g, ''));
|
||||||
|
|
||||||
let parity = 0;
|
let parity = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user