You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-11-25 05:23:13 +03:00
Adjust types and APIs to match React SDK
Various small tweaks and alignments to match React SDK as part of TypeScript conversion. Part of https://github.com/vector-im/element-web/issues/15350
This commit is contained in:
@@ -14,7 +14,7 @@
|
|||||||
"build:minify-browser": "terser dist/browser-matrix.js --compress --mangle --source-map --output dist/browser-matrix.min.js",
|
"build:minify-browser": "terser dist/browser-matrix.js --compress --mangle --source-map --output dist/browser-matrix.min.js",
|
||||||
"gendoc": "jsdoc -c jsdoc.json -P package.json",
|
"gendoc": "jsdoc -c jsdoc.json -P package.json",
|
||||||
"lint": "yarn lint:types && yarn lint:js",
|
"lint": "yarn lint:types && yarn lint:js",
|
||||||
"lint:js": "eslint --max-warnings 76 src spec",
|
"lint:js": "eslint --max-warnings 73 src spec",
|
||||||
"lint:types": "tsc --noEmit",
|
"lint:types": "tsc --noEmit",
|
||||||
"test": "jest spec/ --coverage --testEnvironment node",
|
"test": "jest spec/ --coverage --testEnvironment node",
|
||||||
"test:watch": "jest spec/ --coverage --testEnvironment node --watch"
|
"test:watch": "jest spec/ --coverage --testEnvironment node --watch"
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ describe("Secrets", function() {
|
|||||||
};
|
};
|
||||||
resetCrossSigningKeys(alice);
|
resetCrossSigningKeys(alice);
|
||||||
|
|
||||||
const newKeyId = await alice.addSecretStorageKey(
|
const { keyId: newKeyId } = await alice.addSecretStorageKey(
|
||||||
SECRET_STORAGE_ALGORITHM_V1_AES,
|
SECRET_STORAGE_ALGORITHM_V1_AES,
|
||||||
);
|
);
|
||||||
// we don't await on this because it waits for the event to come down the sync
|
// we don't await on this because it waits for the event to come down the sync
|
||||||
@@ -226,8 +226,8 @@ describe("Secrets", function() {
|
|||||||
],
|
],
|
||||||
{
|
{
|
||||||
cryptoCallbacks: {
|
cryptoCallbacks: {
|
||||||
onSecretRequested: e => {
|
onSecretRequested: (userId, deviceId, requestId, secretName, deviceTrust) => {
|
||||||
expect(e.name).toBe("foo");
|
expect(secretName).toBe("foo");
|
||||||
return "bar";
|
return "bar";
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -235,7 +235,14 @@ function keyFromRecoverySession(session, decryptionKey) {
|
|||||||
* {
|
* {
|
||||||
* keys: {
|
* keys: {
|
||||||
* <key name>: {
|
* <key name>: {
|
||||||
* pubkey: {UInt8Array}
|
* "algorithm": "m.secret_storage.v1.aes-hmac-sha2",
|
||||||
|
* "passphrase": {
|
||||||
|
* "algorithm": "m.pbkdf2",
|
||||||
|
* "iterations": 500000,
|
||||||
|
* "salt": "..."
|
||||||
|
* },
|
||||||
|
* "iv": "...",
|
||||||
|
* "mac": "..."
|
||||||
* }, ...
|
* }, ...
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
@@ -247,6 +254,7 @@ function keyFromRecoverySession(session, decryptionKey) {
|
|||||||
* desired to avoid user prompts.
|
* desired to avoid user prompts.
|
||||||
* Args:
|
* Args:
|
||||||
* {string} keyId the ID of the new key
|
* {string} keyId the ID of the new key
|
||||||
|
* {object} keyInfo Infomation about the key as above for `getSecretStorageKey`
|
||||||
* {Uint8Array} key the new private key
|
* {Uint8Array} key the new private key
|
||||||
*
|
*
|
||||||
* @param {function} [opts.cryptoCallbacks.onSecretRequested]
|
* @param {function} [opts.cryptoCallbacks.onSecretRequested]
|
||||||
@@ -1434,7 +1442,7 @@ wrapCryptoFuncs(MatrixClient, [
|
|||||||
* containing the key, or rejects if the key cannot be obtained.
|
* containing the key, or rejects if the key cannot be obtained.
|
||||||
* Returns:
|
* Returns:
|
||||||
* {Promise} A promise which resolves to key creation data for
|
* {Promise} A promise which resolves to key creation data for
|
||||||
* SecretStorage#addKey: an object with `passphrase` and/or `pubkey` fields.
|
* SecretStorage#addKey: an object with `passphrase` etc fields.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1449,7 +1457,9 @@ wrapCryptoFuncs(MatrixClient, [
|
|||||||
* @param {string} [keyName] the name of the key. If not given, a random
|
* @param {string} [keyName] the name of the key. If not given, a random
|
||||||
* name will be generated.
|
* name will be generated.
|
||||||
*
|
*
|
||||||
* @return {string} the name of the key
|
* @return {object} An object with:
|
||||||
|
* keyId: {string} the ID of the key
|
||||||
|
* keyInfo: {object} details about the key (iv, mac, passphrase)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2009,7 +2019,7 @@ MatrixClient.prototype.isValidRecoveryKey = function(recoveryKey) {
|
|||||||
*
|
*
|
||||||
* @param {string} password Passphrase
|
* @param {string} password Passphrase
|
||||||
* @param {object} backupInfo Backup metadata from `checkKeyBackup`
|
* @param {object} backupInfo Backup metadata from `checkKeyBackup`
|
||||||
* @return {Promise<Buffer>} key backup key
|
* @return {Promise<Uint8Array>} key backup key
|
||||||
*/
|
*/
|
||||||
MatrixClient.prototype.keyBackupKeyFromPassword = function(
|
MatrixClient.prototype.keyBackupKeyFromPassword = function(
|
||||||
password, backupInfo,
|
password, backupInfo,
|
||||||
@@ -2024,7 +2034,7 @@ MatrixClient.prototype.keyBackupKeyFromPassword = function(
|
|||||||
* The cross-signing API is currently UNSTABLE and may change without notice.
|
* The cross-signing API is currently UNSTABLE and may change without notice.
|
||||||
*
|
*
|
||||||
* @param {string} recoveryKey The recovery key
|
* @param {string} recoveryKey The recovery key
|
||||||
* @return {Buffer} key backup key
|
* @return {Uint8Array} key backup key
|
||||||
*/
|
*/
|
||||||
MatrixClient.prototype.keyBackupKeyFromRecoveryKey = function(recoveryKey) {
|
MatrixClient.prototype.keyBackupKeyFromRecoveryKey = function(recoveryKey) {
|
||||||
return decodeRecoveryKey(recoveryKey);
|
return decodeRecoveryKey(recoveryKey);
|
||||||
|
|||||||
@@ -344,14 +344,14 @@ class SSSSCryptoCallbacks {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addPrivateKey(keyId, privKey) {
|
addPrivateKey(keyId, keyInfo, privKey) {
|
||||||
this._privateKeys.set(keyId, privKey);
|
this._privateKeys.set(keyId, privKey);
|
||||||
// Also pass along to application to cache if it wishes
|
// Also pass along to application to cache if it wishes
|
||||||
if (
|
if (
|
||||||
this._delegateCryptoCallbacks &&
|
this._delegateCryptoCallbacks &&
|
||||||
this._delegateCryptoCallbacks.cacheSecretStorageKey
|
this._delegateCryptoCallbacks.cacheSecretStorageKey
|
||||||
) {
|
) {
|
||||||
this._delegateCryptoCallbacks.cacheSecretStorageKey(keyId, privKey);
|
this._delegateCryptoCallbacks.cacheSecretStorageKey(keyId, keyInfo, privKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,25 +81,27 @@ export class SecretStorage extends EventEmitter {
|
|||||||
* @param {string} [keyId] the ID of the key. If not given, a random
|
* @param {string} [keyId] the ID of the key. If not given, a random
|
||||||
* ID will be generated.
|
* ID will be generated.
|
||||||
*
|
*
|
||||||
* @return {string} the ID of the key
|
* @return {object} An object with:
|
||||||
|
* keyId: {string} the ID of the key
|
||||||
|
* keyInfo: {object} details about the key (iv, mac, passphrase)
|
||||||
*/
|
*/
|
||||||
async addKey(algorithm, opts, keyId) {
|
async addKey(algorithm, opts, keyId) {
|
||||||
const keyData = {algorithm};
|
const keyInfo = {algorithm};
|
||||||
|
|
||||||
if (!opts) opts = {};
|
if (!opts) opts = {};
|
||||||
|
|
||||||
if (opts.name) {
|
if (opts.name) {
|
||||||
keyData.name = opts.name;
|
keyInfo.name = opts.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (algorithm === SECRET_STORAGE_ALGORITHM_V1_AES) {
|
if (algorithm === SECRET_STORAGE_ALGORITHM_V1_AES) {
|
||||||
if (opts.passphrase) {
|
if (opts.passphrase) {
|
||||||
keyData.passphrase = opts.passphrase;
|
keyInfo.passphrase = opts.passphrase;
|
||||||
}
|
}
|
||||||
if (opts.key) {
|
if (opts.key) {
|
||||||
const {iv, mac} = await SecretStorage._calculateKeyCheck(opts.key);
|
const {iv, mac} = await SecretStorage._calculateKeyCheck(opts.key);
|
||||||
keyData.iv = iv;
|
keyInfo.iv = iv;
|
||||||
keyData.mac = mac;
|
keyInfo.mac = mac;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`Unknown key algorithm ${opts.algorithm}`);
|
throw new Error(`Unknown key algorithm ${opts.algorithm}`);
|
||||||
@@ -116,10 +118,13 @@ export class SecretStorage extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await this._baseApis.setAccountData(
|
await this._baseApis.setAccountData(
|
||||||
`m.secret_storage.key.${keyId}`, keyData,
|
`m.secret_storage.key.${keyId}`, keyInfo,
|
||||||
);
|
);
|
||||||
|
|
||||||
return keyId;
|
return {
|
||||||
|
keyId,
|
||||||
|
keyInfo,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -457,13 +462,13 @@ export class SecretStorage extends EventEmitter {
|
|||||||
if (!this._cryptoCallbacks.onSecretRequested) {
|
if (!this._cryptoCallbacks.onSecretRequested) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const secret = await this._cryptoCallbacks.onSecretRequested({
|
const secret = await this._cryptoCallbacks.onSecretRequested(
|
||||||
user_id: sender,
|
sender,
|
||||||
device_id: deviceId,
|
deviceId,
|
||||||
request_id: content.request_id,
|
content.request_id,
|
||||||
name: content.name,
|
content.name,
|
||||||
device_trust: this._baseApis.checkDeviceTrust(sender, deviceId),
|
this._baseApis.checkDeviceTrust(sender, deviceId),
|
||||||
});
|
);
|
||||||
if (secret) {
|
if (secret) {
|
||||||
logger.info(`Preparing ${content.name} secret for ${deviceId}`);
|
logger.info(`Preparing ${content.name} secret for ${deviceId}`);
|
||||||
const payload = {
|
const payload = {
|
||||||
|
|||||||
@@ -633,7 +633,7 @@ Crypto.prototype.bootstrapCrossSigning = async function({
|
|||||||
* containing the key, or rejects if the key cannot be obtained.
|
* containing the key, or rejects if the key cannot be obtained.
|
||||||
* Returns:
|
* Returns:
|
||||||
* {Promise} A promise which resolves to key creation data for
|
* {Promise} A promise which resolves to key creation data for
|
||||||
* SecretStorage#addKey: an object with `passphrase` and/or `pubkey` fields.
|
* SecretStorage#addKey: an object with `passphrase` etc fields.
|
||||||
*/
|
*/
|
||||||
Crypto.prototype.bootstrapSecretStorage = async function({
|
Crypto.prototype.bootstrapSecretStorage = async function({
|
||||||
createSecretStorageKey = async () => ({ }),
|
createSecretStorageKey = async () => ({ }),
|
||||||
@@ -663,13 +663,13 @@ Crypto.prototype.bootstrapSecretStorage = async function({
|
|||||||
opts.key = privateKey;
|
opts.key = privateKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
const keyId = await secretStorage.addKey(
|
const { keyId, keyInfo } = await secretStorage.addKey(
|
||||||
SECRET_STORAGE_ALGORITHM_V1_AES, opts,
|
SECRET_STORAGE_ALGORITHM_V1_AES, opts,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (privateKey) {
|
if (privateKey) {
|
||||||
// make the private key available to encrypt 4S secrets
|
// make the private key available to encrypt 4S secrets
|
||||||
builder.ssssCryptoCallbacks.addPrivateKey(keyId, privateKey);
|
builder.ssssCryptoCallbacks.addPrivateKey(keyId, keyInfo, privateKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
await secretStorage.setDefaultKeyId(keyId);
|
await secretStorage.setDefaultKeyId(keyId);
|
||||||
@@ -682,9 +682,9 @@ Crypto.prototype.bootstrapSecretStorage = async function({
|
|||||||
{keys: {[keyId]: keyInfo}}, "",
|
{keys: {[keyId]: keyInfo}}, "",
|
||||||
);
|
);
|
||||||
if (key) {
|
if (key) {
|
||||||
const keyData = key[1];
|
const privateKey = key[1];
|
||||||
builder.ssssCryptoCallbacks.addPrivateKey(keyId, keyData);
|
builder.ssssCryptoCallbacks.addPrivateKey(keyId, keyInfo, privateKey);
|
||||||
const {iv, mac} = await SecretStorage._calculateKeyCheck(keyData);
|
const {iv, mac} = await SecretStorage._calculateKeyCheck(privateKey);
|
||||||
keyInfo.iv = iv;
|
keyInfo.iv = iv;
|
||||||
keyInfo.mac = mac;
|
keyInfo.mac = mac;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2015, 2016 OpenMarket Ltd
|
Copyright 2015, 2016 OpenMarket Ltd
|
||||||
Copyright 2017 Vector Creations Ltd
|
Copyright 2017 Vector Creations Ltd
|
||||||
Copyright 2019 The Matrix.org Foundation C.I.C.
|
Copyright 2019, 2020 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.
|
||||||
@@ -113,7 +113,7 @@ export function setCryptoStoreFactory(fac) {
|
|||||||
cryptoStoreFactory = fac;
|
cryptoStoreFactory = fac;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ICreateClientOpts {
|
export interface ICreateClientOpts {
|
||||||
baseUrl: string;
|
baseUrl: string;
|
||||||
idBaseUrl?: string;
|
idBaseUrl?: string;
|
||||||
store?: Store;
|
store?: Store;
|
||||||
@@ -126,6 +126,7 @@ interface ICreateClientOpts {
|
|||||||
identityServer?: any;
|
identityServer?: any;
|
||||||
localTimeoutMs?: number;
|
localTimeoutMs?: number;
|
||||||
useAuthorizationHeader?: boolean;
|
useAuthorizationHeader?: boolean;
|
||||||
|
timelineSupport?: boolean;
|
||||||
queryParams?: Record<string, unknown>;
|
queryParams?: Record<string, unknown>;
|
||||||
deviceToImport?: {
|
deviceToImport?: {
|
||||||
olmDevice: {
|
olmDevice: {
|
||||||
@@ -136,26 +137,54 @@ interface ICreateClientOpts {
|
|||||||
userId: string;
|
userId: string;
|
||||||
deviceId: string;
|
deviceId: string;
|
||||||
};
|
};
|
||||||
|
pickleKey?: string;
|
||||||
sessionStore?: any;
|
sessionStore?: any;
|
||||||
unstableClientRelationAggregation?: boolean;
|
unstableClientRelationAggregation?: boolean;
|
||||||
verificationMethods?: Array<any>;
|
verificationMethods?: Array<any>;
|
||||||
forceTURN?: boolean;
|
forceTURN?: boolean;
|
||||||
fallbackICEServerAllowed?: boolean;
|
fallbackICEServerAllowed?: boolean;
|
||||||
cryptoCallbacks?: {
|
cryptoCallbacks?: ICryptoCallbacks;
|
||||||
getCrossSigningKey?: (keyType: string, pubKey: Uint8Array) => Promise<Uint8Array>;
|
}
|
||||||
saveCrossSigningKeys?: (keys: Record<string, Uint8Array>) => unknown;
|
|
||||||
shouldUpgradeDeviceVerifications?: (
|
export interface ICryptoCallbacks {
|
||||||
users: Record<string, any>
|
getCrossSigningKey?: (keyType: string, pubKey: Uint8Array) => Promise<Uint8Array>;
|
||||||
) => Promise<Array<string>>;
|
saveCrossSigningKeys?: (keys: Record<string, Uint8Array>) => unknown;
|
||||||
getSecretStorageKey?: (
|
shouldUpgradeDeviceVerifications?: (
|
||||||
keys: {keys: Record<string, {pubkey: Uint8Array}>}, name: string
|
users: Record<string, any>
|
||||||
) => Promise<[string, Uint8Array] | null>;
|
) => Promise<Array<string>>;
|
||||||
cacheSecretStorageKey?: (keyId: string, key: Uint8Array) => unknown;
|
getSecretStorageKey?: (
|
||||||
onSecretRequested?: (
|
keys: {keys: Record<string, ISecretStorageKeyInfo>}, name: string
|
||||||
name: string, userId: string, deviceId: string,
|
) => Promise<[string, Uint8Array] | null>;
|
||||||
requestId: string, deviceTrust: any
|
cacheSecretStorageKey?: (
|
||||||
) => Promise<string>;
|
keyId: string, keyInfo: ISecretStorageKeyInfo, key: Uint8Array
|
||||||
|
) => void;
|
||||||
|
onSecretRequested?: (
|
||||||
|
userId: string, deviceId: string,
|
||||||
|
requestId: string, secretName: string, deviceTrust: IDeviceTrustLevel
|
||||||
|
) => Promise<string>;
|
||||||
|
getDehydrationKey?: (
|
||||||
|
keyInfo: ISecretStorageKeyInfo,
|
||||||
|
checkFunc: (Uint8Array) => void,
|
||||||
|
) => Promise<Uint8Array>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Move this to `SecretStorage` once converted
|
||||||
|
export interface ISecretStorageKeyInfo {
|
||||||
|
passphrase?: {
|
||||||
|
algorithm: "m.pbkdf2";
|
||||||
|
iterations: number;
|
||||||
|
salt: string;
|
||||||
};
|
};
|
||||||
|
iv?: string;
|
||||||
|
mac?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Move this to `CrossSigning` once converted
|
||||||
|
export interface IDeviceTrustLevel {
|
||||||
|
isVerified(): boolean;
|
||||||
|
isCrossSigningVerified(): boolean;
|
||||||
|
isLocallyVerified(): boolean;
|
||||||
|
isTofu(): boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user