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
Expose new method CryptoApi.crossSignDevice (#3930)
This commit is contained in:
committed by
GitHub
parent
3f246c6080
commit
d90ae11e2b
@@ -31,8 +31,10 @@ import {
|
|||||||
SELF_CROSS_SIGNING_PRIVATE_KEY_BASE64,
|
SELF_CROSS_SIGNING_PRIVATE_KEY_BASE64,
|
||||||
SELF_CROSS_SIGNING_PUBLIC_KEY_BASE64,
|
SELF_CROSS_SIGNING_PUBLIC_KEY_BASE64,
|
||||||
SIGNED_CROSS_SIGNING_KEYS_DATA,
|
SIGNED_CROSS_SIGNING_KEYS_DATA,
|
||||||
|
SIGNED_TEST_DEVICE_DATA,
|
||||||
USER_CROSS_SIGNING_PRIVATE_KEY_BASE64,
|
USER_CROSS_SIGNING_PRIVATE_KEY_BASE64,
|
||||||
} from "../../test-utils/test-data";
|
} from "../../test-utils/test-data";
|
||||||
|
import * as testData from "../../test-utils/test-data";
|
||||||
import { E2EKeyResponder } from "../../test-utils/E2EKeyResponder";
|
import { E2EKeyResponder } from "../../test-utils/E2EKeyResponder";
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@@ -97,6 +99,12 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("cross-signing (%s)", (backend: s
|
|||||||
/** an object which intercepts `/keys/upload` requests on the test homeserver */
|
/** an object which intercepts `/keys/upload` requests on the test homeserver */
|
||||||
new E2EKeyReceiver(homeserverUrl);
|
new E2EKeyReceiver(homeserverUrl);
|
||||||
|
|
||||||
|
// Silence warnings from the backup manager
|
||||||
|
fetchMock.getOnce(new URL("/_matrix/client/v3/room_keys/version", homeserverUrl).toString(), {
|
||||||
|
status: 404,
|
||||||
|
body: { errcode: "M_NOT_FOUND" },
|
||||||
|
});
|
||||||
|
|
||||||
await initCrypto(aliceClient);
|
await initCrypto(aliceClient);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -339,4 +347,48 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("cross-signing (%s)", (backend: s
|
|||||||
expect(userSigningKeyId).toBe(getPubKey(crossSigningKeys.user_signing_key));
|
expect(userSigningKeyId).toBe(getPubKey(crossSigningKeys.user_signing_key));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("crossSignDevice", () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
|
||||||
|
// make sure that there is another device which we can sign
|
||||||
|
e2eKeyResponder.addDeviceKeys(SIGNED_TEST_DEVICE_DATA);
|
||||||
|
|
||||||
|
// Complete initialsync, to get the outgoing requests going
|
||||||
|
mockInitialApiRequests(aliceClient.getHomeserverUrl());
|
||||||
|
syncResponder.sendOrQueueSyncResponse({ next_batch: 1 });
|
||||||
|
await aliceClient.startClient();
|
||||||
|
await syncPromise(aliceClient);
|
||||||
|
|
||||||
|
// Wait for legacy crypto to find the device
|
||||||
|
await jest.advanceTimersByTimeAsync(10);
|
||||||
|
|
||||||
|
const devices = await aliceClient.getCrypto()!.getUserDeviceInfo([aliceClient.getSafeUserId()]);
|
||||||
|
expect(devices.get(aliceClient.getSafeUserId())!.has(testData.TEST_DEVICE_ID)).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
jest.useRealTimers();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("fails for an unknown device", async () => {
|
||||||
|
await expect(aliceClient.getCrypto()!.crossSignDevice("unknown")).rejects.toThrow("Unknown device");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("cross-signs the device", async () => {
|
||||||
|
mockSetupCrossSigningRequests();
|
||||||
|
await aliceClient.getCrypto()!.bootstrapCrossSigning({});
|
||||||
|
|
||||||
|
fetchMock.mockClear();
|
||||||
|
await aliceClient.getCrypto()!.crossSignDevice(testData.TEST_DEVICE_ID);
|
||||||
|
|
||||||
|
// check that a sig for the device was uploaded
|
||||||
|
const calls = fetchMock.calls("upload-sigs");
|
||||||
|
expect(calls.length).toEqual(1);
|
||||||
|
const body = JSON.parse(calls[0][1]!.body as string);
|
||||||
|
const deviceSig = body[aliceClient.getSafeUserId()][testData.TEST_DEVICE_ID];
|
||||||
|
expect(deviceSig).toHaveProperty("signatures");
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ export interface CryptoApi {
|
|||||||
/**
|
/**
|
||||||
* Mark the given device as locally verified.
|
* Mark the given device as locally verified.
|
||||||
*
|
*
|
||||||
* Marking a devices as locally verified has much the same effect as completing the verification dance, or receiving
|
* Marking a device as locally verified has much the same effect as completing the verification dance, or receiving
|
||||||
* a cross-signing signature for it.
|
* a cross-signing signature for it.
|
||||||
*
|
*
|
||||||
* @param userId - owner of the device
|
* @param userId - owner of the device
|
||||||
@@ -175,6 +175,21 @@ export interface CryptoApi {
|
|||||||
*/
|
*/
|
||||||
setDeviceVerified(userId: string, deviceId: string, verified?: boolean): Promise<void>;
|
setDeviceVerified(userId: string, deviceId: string, verified?: boolean): Promise<void>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cross-sign one of our own devices.
|
||||||
|
*
|
||||||
|
* This will create a signature for the device using our self-signing key, and publish that signature.
|
||||||
|
* Cross-signing a device indicates, to our other devices and to other users, that we have verified that it really
|
||||||
|
* belongs to us.
|
||||||
|
*
|
||||||
|
* Requires that cross-signing has been set up on this device (normally by calling {@link bootstrapCrossSigning}.
|
||||||
|
*
|
||||||
|
* *Note*: Do not call this unless you have verified, somehow, that the device is genuine!
|
||||||
|
*
|
||||||
|
* @param deviceId - ID of the device to be signed.
|
||||||
|
*/
|
||||||
|
crossSignDevice(deviceId: string): Promise<void>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether cross signing:
|
* Checks whether cross signing:
|
||||||
* - is enabled on this account and trusted by this device
|
* - is enabled on this account and trusted by this device
|
||||||
|
|||||||
@@ -2306,6 +2306,15 @@ export class Crypto extends TypedEventEmitter<CryptoEvent, CryptoEventHandlerMap
|
|||||||
await this.setDeviceVerification(userId, deviceId, verified);
|
await this.setDeviceVerification(userId, deviceId, verified);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blindly cross-sign one of our other devices.
|
||||||
|
*
|
||||||
|
* Implementation of {@link CryptoApi#crossSignDevice}.
|
||||||
|
*/
|
||||||
|
public async crossSignDevice(deviceId: string): Promise<void> {
|
||||||
|
await this.setDeviceVerified(this.userId, deviceId, true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the blocked/verified state of the given device
|
* Update the blocked/verified state of the given device
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -572,6 +572,27 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blindly cross-sign one of our other devices.
|
||||||
|
*
|
||||||
|
* Implementation of {@link CryptoApi#crossSignDevice}.
|
||||||
|
*/
|
||||||
|
public async crossSignDevice(deviceId: string): Promise<void> {
|
||||||
|
const device: RustSdkCryptoJs.Device | undefined = await this.olmMachine.getDevice(
|
||||||
|
new RustSdkCryptoJs.UserId(this.userId),
|
||||||
|
new RustSdkCryptoJs.DeviceId(deviceId),
|
||||||
|
);
|
||||||
|
if (!device) {
|
||||||
|
throw new Error(`Unknown device ${deviceId}`);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const outgoingRequest: RustSdkCryptoJs.SignatureUploadRequest = await device.verify();
|
||||||
|
await this.outgoingRequestProcessor.makeOutgoingRequest(outgoingRequest);
|
||||||
|
} finally {
|
||||||
|
device.free();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of {@link CryptoApi#getDeviceVerificationStatus}.
|
* Implementation of {@link CryptoApi#getDeviceVerificationStatus}.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user