1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-08-07 23:02:56 +03:00

Test typescriptification - crypto unit tests pt 1 (#2440)

* enamed:    spec/unit/crypto/secrets.spec.js -> spec/unit/crypto/secrets.spec.ts

Signed-off-by: Kerry Archibald <kerrya@element.io>

* fix ts issues in secrets.spec

Signed-off-by: Kerry Archibald <kerrya@element.io>

* renamed:    spec/unit/crypto/outgoing-room-key-requests.spec.js -> spec/unit/crypto/outgoing-room-key-requests.spec.ts

Signed-off-by: Kerry Archibald <kerrya@element.io>

* fix ts issues in outgoing-room-key-requests.spec.ts

Signed-off-by: Kerry Archibald <kerrya@element.io>

* renamed:    spec/unit/crypto/DeviceList.spec.js -> spec/unit/crypto/DeviceList.spec.ts

Signed-off-by: Kerry Archibald <kerrya@element.io>

* fix ts issues in DeviceList.spec

Signed-off-by: Kerry Archibald <kerrya@element.io>
This commit is contained in:
Kerry
2022-06-08 12:39:08 +02:00
committed by GitHub
parent 2982bd79f6
commit 8f5162c40d
3 changed files with 83 additions and 61 deletions

View File

@@ -1,7 +1,7 @@
/*
Copyright 2017 Vector Creations Ltd
Copyright 2018, 2019 New Vector Ltd
Copyright 2019 The Matrix.org Foundation C.I.C.
Copyright 2019, 2022 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.
@@ -20,8 +20,10 @@ import { logger } from "../../../src/logger";
import * as utils from "../../../src/utils";
import { MemoryCryptoStore } from "../../../src/crypto/store/memory-crypto-store";
import { DeviceList } from "../../../src/crypto/DeviceList";
import { IDownloadKeyResult, MatrixClient } from "../../../src";
import { OlmDevice } from "../../../src/crypto/OlmDevice";
const signedDeviceList = {
const signedDeviceList: IDownloadKeyResult = {
"failures": {},
"device_keys": {
"@test1:sw1v.org": {
@@ -45,13 +47,15 @@ const signedDeviceList = {
"m.megolm.v1.aes-sha2",
],
"device_id": "HGKAWHRVJQ",
"unsigned": {},
"unsigned": {
"device_display_name": "",
},
},
},
},
};
const signedDeviceList2 = {
const signedDeviceList2: IDownloadKeyResult = {
"failures": {},
"device_keys": {
"@test2:sw1v.org": {
@@ -75,7 +79,9 @@ const signedDeviceList2 = {
"m.megolm.v1.aes-sha2",
],
"device_id": "QJVRHWAKGH",
"unsigned": {},
"unsigned": {
"device_display_name": "",
},
},
},
},
@@ -104,10 +110,10 @@ describe('DeviceList', function() {
downloadKeysForUsers: downloadSpy,
getUserId: () => '@test1:sw1v.org',
deviceId: 'HGKAWHRVJQ',
};
} as unknown as MatrixClient;
const mockOlm = {
verifySignature: function(key, message, signature) {},
};
} as unknown as OlmDevice;
const dl = new DeviceList(baseApis, cryptoStore, mockOlm, keyDownloadChunkSize);
deviceLists.push(dl);
return dl;
@@ -118,7 +124,7 @@ describe('DeviceList', function() {
dl.startTrackingDeviceList('@test1:sw1v.org');
const queryDefer1 = utils.defer();
const queryDefer1 = utils.defer<IDownloadKeyResult>();
downloadSpy.mockReturnValue(queryDefer1.promise);
const prom1 = dl.refreshOutdatedDeviceLists();
@@ -138,7 +144,7 @@ describe('DeviceList', function() {
dl.startTrackingDeviceList('@test1:sw1v.org');
const queryDefer1 = utils.defer();
const queryDefer1 = utils.defer<IDownloadKeyResult>();
downloadSpy.mockReturnValue(queryDefer1.promise);
const prom1 = dl.refreshOutdatedDeviceLists();
@@ -155,6 +161,7 @@ describe('DeviceList', function() {
dl.saveIfDirty().then(() => {
// the first request completes
queryDefer1.resolve({
failures: {},
device_keys: {
'@test1:sw1v.org': {},
},
@@ -166,7 +173,7 @@ describe('DeviceList', function() {
logger.log("Creating new devicelist to simulate app reload");
downloadSpy.mockReset();
const dl2 = createTestDeviceList();
const queryDefer3 = utils.defer();
const queryDefer3 = utils.defer<IDownloadKeyResult>();
downloadSpy.mockReturnValue(queryDefer3.promise);
const prom3 = dl2.refreshOutdatedDeviceLists();
@@ -190,9 +197,9 @@ describe('DeviceList', function() {
dl.startTrackingDeviceList('@test1:sw1v.org');
dl.startTrackingDeviceList('@test2:sw1v.org');
const queryDefer1 = utils.defer();
const queryDefer1 = utils.defer<IDownloadKeyResult>();
downloadSpy.mockReturnValueOnce(queryDefer1.promise);
const queryDefer2 = utils.defer();
const queryDefer2 = utils.defer<IDownloadKeyResult>();
downloadSpy.mockReturnValueOnce(queryDefer2.promise);
const prom1 = dl.refreshOutdatedDeviceLists();

View File

@@ -43,13 +43,15 @@ const requests = [
describe.each([
["IndexedDBCryptoStore",
() => new IndexedDBCryptoStore(global.indexedDB, "tests")],
() => new IndexedDBCryptoStore(global.indexedDB, "tests")],
["LocalStorageCryptoStore",
() => new IndexedDBCryptoStore(undefined, "tests")],
() => new IndexedDBCryptoStore(undefined, "tests")],
["MemoryCryptoStore", () => {
const store = new IndexedDBCryptoStore(undefined, "tests");
store._backend = new MemoryCryptoStore();
store._backendPromise = Promise.resolve(store._backend);
// @ts-ignore set private properties
store.backend = new MemoryCryptoStore();
// @ts-ignore
store.backendPromise = Promise.resolve(store.backend);
return store;
}],
])("Outgoing room key requests [%s]", function(name, dbFactory) {
@@ -64,22 +66,22 @@ describe.each([
});
it("getAllOutgoingRoomKeyRequestsByState retrieves all entries in a given state",
async () => {
const r = await
async () => {
const r = await
store.getAllOutgoingRoomKeyRequestsByState(RoomKeyRequestState.Sent);
expect(r).toHaveLength(2);
requests.filter((e) => e.state === RoomKeyRequestState.Sent).forEach((e) => {
expect(r).toContainEqual(e);
expect(r).toHaveLength(2);
requests.filter((e) => e.state === RoomKeyRequestState.Sent).forEach((e) => {
expect(r).toContainEqual(e);
});
});
});
test("getOutgoingRoomKeyRequestByState retrieves any entry in a given state",
async () => {
const r =
async () => {
const r =
await store.getOutgoingRoomKeyRequestByState([RoomKeyRequestState.Sent]);
expect(r).not.toBeNull();
expect(r).not.toBeUndefined();
expect(r.state).toEqual(RoomKeyRequestState.Sent);
expect(requests).toContainEqual(r);
});
expect(r).not.toBeNull();
expect(r).not.toBeUndefined();
expect(r.state).toEqual(RoomKeyRequestState.Sent);
expect(requests).toContainEqual(r);
});
});

View File

@@ -1,5 +1,5 @@
/*
Copyright 2019 The Matrix.org Foundation C.I.C.
Copyright 2019, 2022 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.
@@ -24,15 +24,18 @@ import { encryptAES } from "../../../src/crypto/aes";
import { resetCrossSigningKeys, createSecretStorageKey } from "./crypto-utils";
import { logger } from '../../../src/logger';
import * as utils from "../../../src/utils";
import { ICreateClientOpts } from '../../../src';
import { ISecretStorageKeyInfo } from '../../../src/crypto/api';
try {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const crypto = require('crypto');
utils.setCrypto(crypto);
} catch (err) {
logger.log('nodejs was compiled without crypto support');
}
async function makeTestClient(userInfo, options) {
async function makeTestClient(userInfo: { userId: string, deviceId: string}, options: Partial<ICreateClientOpts> = {}) {
const client = (new TestClient(
userInfo.userId, userInfo.deviceId, undefined, undefined, options,
)).client;
@@ -46,7 +49,7 @@ async function makeTestClient(userInfo, options) {
await client.initCrypto();
// No need to download keys for these tests
client.crypto.downloadKeys = async function() {};
jest.spyOn(client.crypto, 'downloadKeys').mockResolvedValue({});
return client;
}
@@ -54,7 +57,7 @@ async function makeTestClient(userInfo, options) {
// Wrapper around pkSign to return a signed object. pkSign returns the
// signature, rather than the signed object.
function sign(obj, key, userId) {
olmlib.pkSign(obj, key, userId);
olmlib.pkSign(obj, key, userId, '');
return obj;
}
@@ -84,7 +87,7 @@ describe("Secrets", function() {
},
};
const getKey = jest.fn(e => {
const getKey = jest.fn().mockImplementation(async e => {
expect(Object.keys(e.keys)).toEqual(["abc"]);
return ['abc', key];
});
@@ -93,7 +96,7 @@ describe("Secrets", function() {
{ userId: "@alice:example.com", deviceId: "Osborne2" },
{
cryptoCallbacks: {
getCrossSigningKey: t => signingKey,
getCrossSigningKey: async t => signingKey,
getSecretStorageKey: getKey,
},
},
@@ -104,17 +107,19 @@ describe("Secrets", function() {
const secretStorage = alice.crypto.secretStorage;
alice.setAccountData = async function(eventType, contents, callback) {
alice.store.storeAccountDataEvents([
new MatrixEvent({
type: eventType,
content: contents,
}),
]);
if (callback) {
callback();
}
};
jest.spyOn(alice, 'setAccountData').mockImplementation(
async function(eventType, contents, callback) {
alice.store.storeAccountDataEvents([
new MatrixEvent({
type: eventType,
content: contents,
}),
]);
if (callback) {
callback(undefined, undefined);
}
return {};
});
const keyAccountData = {
algorithm: SECRET_STORAGE_ALGORITHM_V1_AES,
@@ -170,7 +175,7 @@ describe("Secrets", function() {
it("should encrypt with default key if keys is null", async function() {
const key = new Uint8Array(16);
for (let i = 0; i < 16; i++) key[i] = i;
const getKey = jest.fn(e => {
const getKey = jest.fn().mockImplementation(async e => {
expect(Object.keys(e.keys)).toEqual([newKeyId]);
return [newKeyId, key];
});
@@ -193,11 +198,12 @@ describe("Secrets", function() {
content: contents,
}),
]);
return {};
};
resetCrossSigningKeys(alice);
const { keyId: newKeyId } = await alice.addSecretStorageKey(
SECRET_STORAGE_ALGORITHM_V1_AES,
SECRET_STORAGE_ALGORITHM_V1_AES, { pubkey: undefined, key: undefined },
);
// we don't await on this because it waits for the event to come down the sync
// which won't happen in the test setup
@@ -306,7 +312,7 @@ describe("Secrets", function() {
it("bootstraps when no storage or cross-signing keys locally", async function() {
const key = new Uint8Array(16);
for (let i = 0; i < 16; i++) key[i] = i;
const getKey = jest.fn(e => {
const getKey = jest.fn().mockImplementation(async e => {
return [Object.keys(e.keys)[0], key];
});
@@ -321,8 +327,8 @@ describe("Secrets", function() {
},
},
);
bob.uploadDeviceSigningKeys = async () => {};
bob.uploadKeySignatures = async () => {};
bob.uploadDeviceSigningKeys = async () => ({});
bob.uploadKeySignatures = jest.fn().mockResolvedValue(undefined);
bob.setAccountData = async function(eventType, contents, callback) {
const event = new MatrixEvent({
type: eventType,
@@ -332,10 +338,11 @@ describe("Secrets", function() {
event,
]);
this.emit("accountData", event);
return {};
};
await bob.bootstrapCrossSigning({
authUploadDeviceSigningKeys: async func => await func({}),
authUploadDeviceSigningKeys: async func => { await func({}); },
});
await bob.bootstrapSecretStorage({
createSecretStorageKey,
@@ -419,7 +426,7 @@ describe("Secrets", function() {
});
it("adds passphrase checking if it's lacking", async function() {
let crossSigningKeys = {
let crossSigningKeys: Record<string, Uint8Array> = {
master: XSK,
user_signing: USK,
self_signing: SSK,
@@ -431,9 +438,9 @@ describe("Secrets", function() {
{ userId: "@alice:example.com", deviceId: "Osborne2" },
{
cryptoCallbacks: {
getCrossSigningKey: t => crossSigningKeys[t],
getCrossSigningKey: async t => crossSigningKeys[t],
saveCrossSigningKeys: k => crossSigningKeys = k,
getSecretStorageKey: ({ keys }, name) => {
getSecretStorageKey: async ({ keys }, name) => {
for (const keyId of Object.keys(keys)) {
if (secretStorageKeys[keyId]) {
return [keyId, secretStorageKeys[keyId]];
@@ -489,6 +496,8 @@ describe("Secrets", function() {
}),
]);
alice.crypto.deviceList.storeCrossSigningForUser("@alice:example.com", {
firstUse: false,
crossSigningVerifiedBefore: false,
keys: {
master: {
user_id: "@alice:example.com",
@@ -529,14 +538,15 @@ describe("Secrets", function() {
});
alice.store.storeAccountDataEvents([event]);
this.emit("accountData", event);
return {};
};
await alice.bootstrapSecretStorage();
await alice.bootstrapSecretStorage({});
expect(alice.getAccountData("m.secret_storage.default_key").getContent())
.toEqual({ key: "key_id" });
const keyInfo = alice.getAccountData("m.secret_storage.key.key_id")
.getContent();
.getContent() as ISecretStorageKeyInfo;
expect(keyInfo.algorithm)
.toEqual("m.secret_storage.v1.aes-hmac-sha2");
expect(keyInfo.passphrase).toEqual({
@@ -551,7 +561,7 @@ describe("Secrets", function() {
alice.stopClient();
});
it("fixes backup keys in the wrong format", async function() {
let crossSigningKeys = {
let crossSigningKeys: Record<string, Uint8Array> = {
master: XSK,
user_signing: USK,
self_signing: SSK,
@@ -563,9 +573,9 @@ describe("Secrets", function() {
{ userId: "@alice:example.com", deviceId: "Osborne2" },
{
cryptoCallbacks: {
getCrossSigningKey: t => crossSigningKeys[t],
getCrossSigningKey: async t => crossSigningKeys[t],
saveCrossSigningKeys: k => crossSigningKeys = k,
getSecretStorageKey: ({ keys }, name) => {
getSecretStorageKey: async ({ keys }, name) => {
for (const keyId of Object.keys(keys)) {
if (secretStorageKeys[keyId]) {
return [keyId, secretStorageKeys[keyId]];
@@ -630,6 +640,8 @@ describe("Secrets", function() {
}),
]);
alice.crypto.deviceList.storeCrossSigningForUser("@alice:example.com", {
firstUse: false,
crossSigningVerifiedBefore: false,
keys: {
master: {
user_id: "@alice:example.com",
@@ -670,9 +682,10 @@ describe("Secrets", function() {
});
alice.store.storeAccountDataEvents([event]);
this.emit("accountData", event);
return {};
};
await alice.bootstrapSecretStorage();
await alice.bootstrapSecretStorage({});
const backupKey = alice.getAccountData("m.megolm_backup.v1")
.getContent();