You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-07-31 15:24:23 +03:00
ElementR: Add CryptoApi.getCrossSigningKeyId
(#3619)
* Add `CryptoApi.getCrossSigningKeyId` * Rename `CrossSigningPubKey` to `CrossSigningKeyInfo` * Remove old eslint disable * Review changes * Review changes
This commit is contained in:
@ -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";
|
||||
@ -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));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -168,7 +168,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);
|
||||
});
|
||||
|
@ -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,
|
||||
@ -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",
|
||||
|
@ -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
|
||||
@ -503,6 +504,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}
|
||||
*/
|
||||
|
@ -41,6 +41,7 @@ import {
|
||||
ImportRoomKeyProgressData,
|
||||
ImportRoomKeysOpts,
|
||||
VerificationRequest,
|
||||
CrossSigningKeyInfo,
|
||||
} from "../crypto-api";
|
||||
import { deviceKeysToDeviceMap, rustDeviceToJsDevice } from "./device-converter";
|
||||
import { IDownloadKeyResult, IQueryKeysRequest } from "../client";
|
||||
@ -417,8 +418,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];
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user