1
0
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:
Hubert Chathi
2019-06-05 15:27:31 -04:00
parent 0c714ba4a1
commit 6f6e7ea921
5 changed files with 113 additions and 41 deletions

View File

@@ -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(
{
keys: {
"ed25519:Dynabook": "bob+base64+ed25519+key",
},
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": bobDevice.deviceEd25519Key,
"curve25519:Dynabook": bobDevice.deviceCurve25519Key,
},
"Dynabook",
);
};
},
});
alice.downloadKeys = () => {
return Promise.resolve();
};
bob.setDeviceVerified = expect.createSpy();
bob.getStoredDevice = () => {
return DeviceInfo.fromStorage(
{
keys: {
"ed25519:Osborne2": "alice+base64+ed25519+key",
},
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": 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);
});
});

View File

@@ -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.

View File

@@ -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.
*

View File

@@ -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`,
);
}
}
}

View File

@@ -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 });