You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-11-28 05:03:59 +03:00
verify cross-signing key with SAS
This commit is contained in:
@@ -22,6 +22,7 @@ try {
|
||||
}
|
||||
|
||||
import expect from 'expect';
|
||||
import olmlib from '../../../../lib/crypto/olmlib';
|
||||
|
||||
import sdk from '../../../..';
|
||||
|
||||
@@ -78,38 +79,35 @@ describe("SAS verification", function() {
|
||||
},
|
||||
);
|
||||
|
||||
alice.setDeviceVerified = expect.createSpy();
|
||||
alice.getDeviceEd25519Key = () => {
|
||||
return "alice+base64+ed25519+key";
|
||||
};
|
||||
alice.getStoredDevice = () => {
|
||||
return DeviceInfo.fromStorage(
|
||||
{
|
||||
const aliceDevice = alice._crypto._olmDevice;
|
||||
const bobDevice = bob._crypto._olmDevice;
|
||||
|
||||
alice._crypto._deviceList.storeDevicesForUser("@bob:example.com", {
|
||||
Dynabook: {
|
||||
user_id: "@bob:example.com",
|
||||
device_id: "Dynabook",
|
||||
algorithms: [olmlib.OLM_ALGORITHM, olmlib.MEGOLM_ALGORITHM],
|
||||
keys: {
|
||||
"ed25519:Dynabook": "bob+base64+ed25519+key",
|
||||
"ed25519:Dynabook": bobDevice.deviceEd25519Key,
|
||||
"curve25519:Dynabook": bobDevice.deviceCurve25519Key,
|
||||
},
|
||||
},
|
||||
"Dynabook",
|
||||
);
|
||||
};
|
||||
});
|
||||
alice.downloadKeys = () => {
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
bob.setDeviceVerified = expect.createSpy();
|
||||
bob.getStoredDevice = () => {
|
||||
return DeviceInfo.fromStorage(
|
||||
{
|
||||
bob._crypto._deviceList.storeDevicesForUser("@alice:example.com", {
|
||||
Osborne2: {
|
||||
user_id: "@alice:example.com",
|
||||
device_id: "Osborne2",
|
||||
algorithms: [olmlib.OLM_ALGORITHM, olmlib.MEGOLM_ALGORITHM],
|
||||
keys: {
|
||||
"ed25519:Osborne2": "alice+base64+ed25519+key",
|
||||
"ed25519:Osborne2": aliceDevice.deviceEd25519Key,
|
||||
"curve25519:Osborne2": aliceDevice.deviceCurve25519Key,
|
||||
},
|
||||
},
|
||||
"Osborne2",
|
||||
);
|
||||
};
|
||||
bob.getDeviceEd25519Key = () => {
|
||||
return "bob+base64+ed25519+key";
|
||||
};
|
||||
});
|
||||
bob.downloadKeys = () => {
|
||||
return Promise.resolve();
|
||||
};
|
||||
@@ -180,10 +178,12 @@ describe("SAS verification", function() {
|
||||
expect(macMethod).toBe("hkdf-hmac-sha256");
|
||||
|
||||
// make sure Alice and Bob verified each other
|
||||
expect(alice.setDeviceVerified)
|
||||
.toHaveBeenCalledWith(bob.getUserId(), bob.deviceId);
|
||||
expect(bob.setDeviceVerified)
|
||||
.toHaveBeenCalledWith(alice.getUserId(), alice.deviceId);
|
||||
const bobDevice
|
||||
= await alice.getStoredDevice("@bob:example.com", "Dynabook");
|
||||
expect(bobDevice.isVerified()).toBeTruthy();
|
||||
const aliceDevice
|
||||
= await bob.getStoredDevice("@alice:example.com", "Osborne2");
|
||||
expect(aliceDevice.isVerified()).toBeTruthy();
|
||||
});
|
||||
|
||||
it("should be able to verify using the old MAC", async function() {
|
||||
@@ -218,10 +218,40 @@ describe("SAS verification", function() {
|
||||
|
||||
expect(macMethod).toBe("hmac-sha256");
|
||||
|
||||
expect(alice.setDeviceVerified)
|
||||
.toHaveBeenCalledWith(bob.getUserId(), bob.deviceId);
|
||||
expect(bob.setDeviceVerified)
|
||||
.toHaveBeenCalledWith(alice.getUserId(), alice.deviceId);
|
||||
const bobDevice
|
||||
= await alice.getStoredDevice("@bob:example.com", "Dynabook");
|
||||
expect(bobDevice.isVerified()).toBeTruthy();
|
||||
const aliceDevice
|
||||
= await bob.getStoredDevice("@alice:example.com", "Osborne2");
|
||||
expect(aliceDevice.isVerified()).toBeTruthy();
|
||||
});
|
||||
|
||||
it("should verify a cross-signing key", async function() {
|
||||
const privateKeys = {};
|
||||
alice.on("cross-signing:savePrivateKeys", function(e) {
|
||||
privateKeys.alice = e;
|
||||
});
|
||||
await alice.resetCrossSigningKeys();
|
||||
bob.on("cross-signing:savePrivateKeys", function(e) {
|
||||
privateKeys.bob = e;
|
||||
});
|
||||
await bob.resetCrossSigningKeys();
|
||||
|
||||
bob.on("cross-signing:getKey", function(e) {
|
||||
e.done(privateKeys.bob[e.type]);
|
||||
});
|
||||
|
||||
bob._crypto._deviceList.storeCrossSigningForUser("@alice:example.com", {
|
||||
keys: alice._crypto._crossSigningInfo.keys,
|
||||
});
|
||||
await Promise.all([
|
||||
aliceVerifier.verify(),
|
||||
bobPromise.then((verifier) => verifier.verify()),
|
||||
]);
|
||||
|
||||
expect(alice.checkDeviceTrust("@bob:example.com", "Dynabook")).toBe(1);
|
||||
expect(bob.checkUserTrust("@alice:example.com")).toBe(6);
|
||||
expect(bob.checkDeviceTrust("@alice:example.com", "Osborne2")).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -854,6 +854,9 @@ MatrixClient.prototype.resetCrossSigningKeys
|
||||
MatrixClient.prototype.setCrossSigningKeys
|
||||
= wrapCryptoFunc("setCrossSigningKeys");
|
||||
|
||||
MatrixClient.prototype.getCrossSigningId
|
||||
= wrapCryptoFunc("getCrossSigningId");
|
||||
|
||||
/**
|
||||
* Cancel a room key request for this event if one is ongoing and resend the
|
||||
* request.
|
||||
|
||||
@@ -286,6 +286,18 @@ Crypto.prototype.setCrossSigningKeys = function(keys) {
|
||||
this._baseApis.emit("cross-signing:keysChanged", {});
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the user's cross-signing key ID.
|
||||
*
|
||||
* @param {string} type The type of key to get the ID of. One of "master",
|
||||
* "self_signing", or "user_signing". Defaults to "master".
|
||||
*
|
||||
* @returns {string} the key ID
|
||||
*/
|
||||
Crypto.prototype.getCrossSigningId = function(type) {
|
||||
return this._crossSigningInfo.getId(type);
|
||||
};
|
||||
|
||||
/**
|
||||
* Check whether a given user is trusted.
|
||||
*
|
||||
|
||||
@@ -22,6 +22,7 @@ limitations under the License.
|
||||
import {MatrixEvent} from '../../models/event';
|
||||
import {EventEmitter} from 'events';
|
||||
import logger from '../../logger';
|
||||
import DeviceInfo from '../deviceinfo';
|
||||
|
||||
export default class VerificationBase extends EventEmitter {
|
||||
/**
|
||||
@@ -192,11 +193,24 @@ export default class VerificationBase extends EventEmitter {
|
||||
for (const [keyId, keyInfo] of Object.entries(keys)) {
|
||||
const deviceId = keyId.split(':', 2)[1];
|
||||
const device = await this._baseApis.getStoredDevice(userId, deviceId);
|
||||
if (!device) {
|
||||
logger.warn(`verification: Could not find device ${deviceId} to verify`);
|
||||
} else {
|
||||
if (device) {
|
||||
await verifier(keyId, device, keyInfo);
|
||||
verifiedDevices.push(deviceId);
|
||||
} else {
|
||||
const crossSigningInfo = this._baseApis._crypto._deviceList
|
||||
.getStoredCrossSigningForUser(userId);
|
||||
if (crossSigningInfo && crossSigningInfo.getId() === deviceId) {
|
||||
await verifier(keyId, DeviceInfo.fromStorage({
|
||||
keys: {
|
||||
[keyId]: deviceId,
|
||||
},
|
||||
}, deviceId), keyInfo);
|
||||
verifiedDevices.push(deviceId);
|
||||
} else {
|
||||
logger.warn(
|
||||
`verification: Could not find device ${deviceId} to verify`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -354,19 +354,32 @@ export default class SAS extends Base {
|
||||
}
|
||||
|
||||
_sendMAC(olmSAS, method) {
|
||||
const keyId = `ed25519:${this._baseApis.deviceId}`;
|
||||
const mac = {};
|
||||
const keyList = [];
|
||||
const baseInfo = "MATRIX_KEY_VERIFICATION_MAC"
|
||||
+ this._baseApis.getUserId() + this._baseApis.deviceId
|
||||
+ this.userId + this.deviceId
|
||||
+ this.transactionId;
|
||||
|
||||
mac[keyId] = olmSAS[macMethods[method]](
|
||||
const deviceKeyId = `ed25519:${this._baseApis.deviceId}`;
|
||||
mac[deviceKeyId] = olmSAS[macMethods[method]](
|
||||
this._baseApis.getDeviceEd25519Key(),
|
||||
baseInfo + keyId,
|
||||
baseInfo + deviceKeyId,
|
||||
);
|
||||
keyList.push(deviceKeyId);
|
||||
|
||||
const crossSigningId = this._baseApis.getCrossSigningId();
|
||||
if (crossSigningId) {
|
||||
const crossSigningKeyId = `ed25519:${crossSigningId}`;
|
||||
mac[crossSigningKeyId] = olmSAS[macMethods[method]](
|
||||
crossSigningId,
|
||||
baseInfo + crossSigningKeyId,
|
||||
);
|
||||
keyList.push(crossSigningKeyId);
|
||||
}
|
||||
|
||||
const keys = olmSAS[macMethods[method]](
|
||||
keyId,
|
||||
keyList.sort().join(","),
|
||||
baseInfo + "KEY_IDS",
|
||||
);
|
||||
this._sendToDevice("m.key.verification.mac", { mac, keys });
|
||||
|
||||
Reference in New Issue
Block a user