Skip to content

Commit

Permalink
Merge branch 'rav/element-r/45_backup_integ_test' into valere/rust_ba…
Browse files Browse the repository at this point in the history
…ckup_status_api
  • Loading branch information
richvdh authored Jul 27, 2023
2 parents 5da8144 + d033c1c commit 94582a5
Show file tree
Hide file tree
Showing 9 changed files with 487 additions and 416 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/cypress.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ concurrency:
jobs:
cypress:
name: Cypress
uses: matrix-org/matrix-react-sdk/.github/workflows/cypress.yaml@v3.75.0
uses: matrix-org/matrix-react-sdk/.github/workflows/cypress.yaml@v3.76.0
permissions:
actions: read
issues: read
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/downstream-artifacts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ concurrency:
jobs:
build-element-web:
name: Build element-web
uses: matrix-org/matrix-react-sdk/.github/workflows/element-web.yaml@v3.75.0
uses: matrix-org/matrix-react-sdk/.github/workflows/element-web.yaml@v3.76.0
with:
matrix-js-sdk-sha: ${{ github.sha }}
react-sdk-repository: matrix-org/matrix-react-sdk
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
"jwt-decode": "^3.1.2",
"loglevel": "^1.7.1",
"matrix-events-sdk": "0.0.1",
"matrix-widget-api": "^1.3.1",
"matrix-widget-api": "^1.5.0",
"oidc-client-ts": "^2.2.4",
"p-retry": "4",
"sdp-transform": "^2.14.1",
Expand Down Expand Up @@ -101,7 +101,7 @@
"browserify-swap": "^0.2.2",
"debug": "^4.3.4",
"domexception": "^4.0.0",
"eslint": "8.44.0",
"eslint": "8.45.0",
"eslint-config-google": "^0.14.0",
"eslint-config-prettier": "^8.5.0",
"eslint-import-resolver-typescript": "^3.5.1",
Expand All @@ -110,7 +110,7 @@
"eslint-plugin-jsdoc": "^46.0.0",
"eslint-plugin-matrix-org": "^1.0.0",
"eslint-plugin-tsdoc": "^0.2.17",
"eslint-plugin-unicorn": "^47.0.0",
"eslint-plugin-unicorn": "^48.0.0",
"exorcist": "^2.0.0",
"fake-indexeddb": "^4.0.0",
"fetch-mock-jest": "^1.5.1",
Expand Down
53 changes: 52 additions & 1 deletion spec/integ/crypto/cross-signing.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { CRYPTO_BACKENDS, InitCrypto, syncPromise } from "../../test-utils/test-
import { AuthDict, createClient, CryptoEvent, MatrixClient } from "../../../src";
import { mockInitialApiRequests, mockSetupCrossSigningRequests } from "../../test-utils/mockEndpoints";
import { encryptAES } from "../../../src/crypto/aes";
import { CryptoCallbacks } from "../../../src/crypto-api";
import { CryptoCallbacks, CrossSigningKey } from "../../../src/crypto-api";
import { SECRET_STORAGE_ALGORITHM_V1_AES } from "../../../src/secret-storage";
import { ISyncResponder, SyncResponder } from "../../test-utils/SyncResponder";
import { E2EKeyReceiver } from "../../test-utils/E2EKeyReceiver";
Expand Down Expand Up @@ -288,4 +288,55 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("cross-signing (%s)", (backend: s
expect(isCrossSigningReady).toBeTruthy();
});
});

describe("getCrossSigningKeyId", () => {
/**
* Intercept /keys/device_signing/upload request and return the cross signing keys
* https://spec.matrix.org/v1.7/client-server-api/#post_matrixclientv3keysdevice_signingupload
*
* @returns the cross signing keys
*/
function awaitCrossSigningKeysUpload() {
return new Promise<any>((resolve) => {
fetchMock.post(
// legacy crypto uses /unstable/; /v3/ is correct
{
url: new RegExp("/_matrix/client/(unstable|v3)/keys/device_signing/upload"),
name: "upload-keys",
},
(url, options) => {
const content = JSON.parse(options.body as string);
resolve(content);
return {};
},
// Override the routes define in `mockSetupCrossSigningRequests`
{ overwriteRoutes: true },
);
});
}

it("should return the cross signing key id for each cross signing key", async () => {
mockSetupCrossSigningRequests();

// Intercept cross signing keys upload
const crossSigningKeysPromise = awaitCrossSigningKeysUpload();

// provide a UIA callback, so that the cross-signing keys are uploaded
const authDict = { type: "test" };
await bootstrapCrossSigning(authDict);
// Get the cross signing keys
const crossSigningKeys = await crossSigningKeysPromise;

const getPubKey = (crossSigningKey: any) => Object.values(crossSigningKey!.keys)[0];

const masterKeyId = await aliceClient.getCrypto()!.getCrossSigningKeyId();
expect(masterKeyId).toBe(getPubKey(crossSigningKeys.master_key));

const selfSigningKeyId = await aliceClient.getCrypto()!.getCrossSigningKeyId(CrossSigningKey.SelfSigning);
expect(selfSigningKeyId).toBe(getPubKey(crossSigningKeys.self_signing_key));

const userSigningKeyId = await aliceClient.getCrypto()!.getCrossSigningKeyId(CrossSigningKey.UserSigning);
expect(userSigningKeyId).toBe(getPubKey(crossSigningKeys.user_signing_key));
});
});
});
2 changes: 1 addition & 1 deletion spec/unit/rust-crypto/rust-crypto.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ describe("RustCrypto", () => {
});
});

it("getCrossSigningKeyId", async () => {
it("getCrossSigningKeyId when there is no cross signing keys", async () => {
const rustCrypto = await makeTestRustCrypto();
await expect(rustCrypto.getCrossSigningKeyId()).resolves.toBe(null);
});
Expand Down
11 changes: 3 additions & 8 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ import { LocalNotificationSettings } from "./@types/local_notifications";
import { buildFeatureSupportMap, Feature, ServerSupport } from "./feature";
import { CryptoBackend } from "./common-crypto/CryptoBackend";
import { RUST_SDK_STORE_PREFIX } from "./rust-crypto/constants";
import { BootstrapCrossSigningOpts, CryptoApi, ImportRoomKeysOpts } from "./crypto-api";
import { BootstrapCrossSigningOpts, CrossSigningKeyInfo, CryptoApi, ImportRoomKeysOpts } from "./crypto-api";
import { DeviceInfoMap } from "./crypto/DeviceList";
import {
AddSecretStorageKeyOpts,
Expand Down Expand Up @@ -524,13 +524,8 @@ export interface Capabilities {
[UNSTABLE_MSC3882_CAPABILITY.altName]?: IMSC3882GetLoginTokenCapability;
}

/* eslint-disable camelcase */
export interface ICrossSigningKey {
keys: { [algorithm: string]: string };
signatures?: ISignatures;
usage: string[];
user_id: string;
}
/** @deprecated prefer {@link CrossSigningKeyInfo}. */
export type ICrossSigningKey = CrossSigningKeyInfo;

enum CrossSigningKeyType {
MasterKey = "master_key",
Expand Down
12 changes: 12 additions & 0 deletions src/crypto-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { UIAuthCallback } from "./interactive-auth";
import { AddSecretStorageKeyOpts, SecretStorageCallbacks, SecretStorageKeyDescription } from "./secret-storage";
import { VerificationRequest } from "./crypto-api/verification";
import { KeyBackupInfo } from "./crypto-api/keybackup";
import { ISignatures } from "./@types/signed";

/**
* Public interface to the cryptography parts of the js-sdk
Expand Down Expand Up @@ -526,6 +527,17 @@ export enum CrossSigningKey {
UserSigning = "user_signing",
}

/**
* Information on one of the cross-signing keys.
* @see https://spec.matrix.org/v1.7/client-server-api/#post_matrixclientv3keysdevice_signingupload
*/
export interface CrossSigningKeyInfo {
keys: { [algorithm: string]: string };
signatures?: ISignatures;
usage: string[];
user_id: string;
}

/**
* Recovery key created by {@link CryptoApi#createRecoveryKeyFromPassphrase}
*/
Expand Down
42 changes: 40 additions & 2 deletions src/rust-crypto/rust-crypto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import {
ImportRoomKeyProgressData,
ImportRoomKeysOpts,
VerificationRequest,
CrossSigningKeyInfo,
} from "../crypto-api";
import { deviceKeysToDeviceMap, rustDeviceToJsDevice } from "./device-converter";
import { IDownloadKeyResult, IQueryKeysRequest } from "../client";
Expand Down Expand Up @@ -438,8 +439,45 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
* Implementation of {@link CryptoApi#getCrossSigningKeyId}
*/
public async getCrossSigningKeyId(type: CrossSigningKey = CrossSigningKey.Master): Promise<string | null> {
// TODO
return null;
const userIdentity: RustSdkCryptoJs.OwnUserIdentity | undefined = await this.olmMachine.getIdentity(
new RustSdkCryptoJs.UserId(this.userId),
);

const crossSigningStatus: RustSdkCryptoJs.CrossSigningStatus = await this.olmMachine.crossSigningStatus();
const privateKeysOnDevice =
crossSigningStatus.hasMaster && crossSigningStatus.hasUserSigning && crossSigningStatus.hasSelfSigning;

if (!userIdentity || !privateKeysOnDevice) {
// The public or private keys are not available on this device
return null;
}

if (!userIdentity.isVerified()) {
// We have both public and private keys, but they don't match!
return null;
}

let key: string;
switch (type) {
case CrossSigningKey.Master:
key = userIdentity.masterKey;
break;
case CrossSigningKey.SelfSigning:
key = userIdentity.selfSigningKey;
break;
case CrossSigningKey.UserSigning:
key = userIdentity.userSigningKey;
break;
default:
// Unknown type
return null;
}

const parsedKey: CrossSigningKeyInfo = JSON.parse(key);
// `keys` is an object with { [`ed25519:${pubKey}`]: pubKey }
// We assume only a single key, and we want the bare form without type
// prefix, so we select the values.
return Object.values(parsedKey.keys)[0];
}

/**
Expand Down
Loading

0 comments on commit 94582a5

Please sign in to comment.