add signature verification tests

This commit is contained in:
Sorunome 2020-06-15 10:26:50 +02:00
parent 9b2952435f
commit e874a5e00b
No known key found for this signature in database
GPG key ID: B19471D07FC9BE9C
4 changed files with 155 additions and 9 deletions

View file

@ -1135,7 +1135,7 @@ class Client {
var outdatedLists = <String, dynamic>{}; var outdatedLists = <String, dynamic>{};
for (var userId in trackedUserIds) { for (var userId in trackedUserIds) {
if (!userDeviceKeys.containsKey(userId)) { if (!userDeviceKeys.containsKey(userId)) {
_userDeviceKeys[userId] = DeviceKeysList(userId); _userDeviceKeys[userId] = DeviceKeysList(userId, this);
} }
var deviceKeysList = userDeviceKeys[userId]; var deviceKeysList = userDeviceKeys[userId];
if (deviceKeysList.outdated) { if (deviceKeysList.outdated) {
@ -1151,7 +1151,7 @@ class Client {
for (final rawDeviceKeyListEntry in response.deviceKeys.entries) { for (final rawDeviceKeyListEntry in response.deviceKeys.entries) {
final userId = rawDeviceKeyListEntry.key; final userId = rawDeviceKeyListEntry.key;
if (!userDeviceKeys.containsKey(userId)) { if (!userDeviceKeys.containsKey(userId)) {
_userDeviceKeys[userId] = DeviceKeysList(userId); _userDeviceKeys[userId] = DeviceKeysList(userId, this);
} }
final oldKeys = final oldKeys =
Map<String, DeviceKeys>.from(_userDeviceKeys[userId].deviceKeys); Map<String, DeviceKeys>.from(_userDeviceKeys[userId].deviceKeys);
@ -1230,7 +1230,7 @@ class Client {
for (final crossSigningKeyListEntry in keys.entries) { for (final crossSigningKeyListEntry in keys.entries) {
final userId = crossSigningKeyListEntry.key; final userId = crossSigningKeyListEntry.key;
if (!userDeviceKeys.containsKey(userId)) { if (!userDeviceKeys.containsKey(userId)) {
_userDeviceKeys[userId] = DeviceKeysList(userId); _userDeviceKeys[userId] = DeviceKeysList(userId, this);
} }
final oldKeys = Map<String, CrossSigningKey>.from( final oldKeys = Map<String, CrossSigningKey>.from(
_userDeviceKeys[userId].crossSigningKeys); _userDeviceKeys[userId].crossSigningKeys);

View file

@ -54,6 +54,8 @@ class DeviceKeysList {
} }
Future<KeyVerification> startVerification() async { Future<KeyVerification> startVerification() async {
print('++++++++++++');
print(client.toString());
final roomId = final roomId =
await User(userId, room: Room(client: client)).startDirectChat(); await User(userId, room: Room(client: client)).startDirectChat();
if (roomId == null) { if (roomId == null) {
@ -95,7 +97,7 @@ class DeviceKeysList {
} }
} }
DeviceKeysList(this.userId); DeviceKeysList(this.userId, this.client);
} }
abstract class SignableKey extends MatrixSignableKey { abstract class SignableKey extends MatrixSignableKey {
@ -239,7 +241,8 @@ abstract class SignableKey extends MatrixSignableKey {
Future<void> setVerified(bool newVerified, [bool sign = true]) { Future<void> setVerified(bool newVerified, [bool sign = true]) {
_verified = newVerified; _verified = newVerified;
if (sign && if (newVerified &&
sign &&
client.encryptionEnabled && client.encryptionEnabled &&
client.encryption.crossSigning.signable([this])) { client.encryption.crossSigning.signable([this])) {
// sign the key! // sign the key!

View file

@ -20,6 +20,10 @@ import 'dart:convert';
import 'package:famedlysdk/famedlysdk.dart'; import 'package:famedlysdk/famedlysdk.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
import 'package:olm/olm.dart' as olm;
import './fake_client.dart';
import './fake_matrix_api.dart';
void main() { void main() {
/// All Tests related to device keys /// All Tests related to device keys
@ -49,6 +53,125 @@ void main() {
expect(json.encode(key.toJson()), json.encode(rawJson)); expect(json.encode(key.toJson()), json.encode(rawJson));
expect(key.directVerified, false); expect(key.directVerified, false);
expect(key.blocked, true); expect(key.blocked, true);
rawJson = <String, dynamic>{
'user_id': '@test:fakeServer.notExisting',
'usage': ['master'],
'keys': {
'ed25519:82mAXjsmbTbrE6zyShpR869jnrANO75H8nYY0nDLoJ8':
'82mAXjsmbTbrE6zyShpR869jnrANO75H8nYY0nDLoJ8',
},
'signatures': {},
};
final crossKey = CrossSigningKey.fromJson(rawJson, null);
expect(json.encode(crossKey.toJson()), json.encode(rawJson));
expect(crossKey.usage.first, 'master');
});
var olmEnabled = true;
try {
olm.init();
olm.Account();
} catch (_) {
olmEnabled = false;
print('[LibOlm] Failed to load LibOlm: ' + _.toString());
}
print('[LibOlm] Enabled: $olmEnabled');
if (!olmEnabled) return;
Client client;
test('setupClient', () async {
client = await getClient();
});
test('set blocked / verified', () async {
final key =
client.userDeviceKeys[client.userID].deviceKeys['OTHERDEVICE'];
final masterKey = client.userDeviceKeys[client.userID].masterKey;
masterKey.setDirectVerified(true);
// we need to populate the ssss cache to be able to test signing easily
final handle = client.encryption.ssss.open();
handle.unlock(recoveryKey: SSSS_KEY);
await handle.maybeCacheAll();
expect(key.verified, true);
await key.setBlocked(true);
expect(key.verified, false);
await key.setBlocked(false);
expect(key.directVerified, false);
expect(key.verified, true); // still verified via cross-sgining
expect(masterKey.verified, true);
await masterKey.setBlocked(true);
expect(masterKey.verified, false);
await masterKey.setBlocked(false);
expect(masterKey.verified, true);
FakeMatrixApi.calledEndpoints.clear();
await key.setVerified(true);
await Future.delayed(Duration(milliseconds: 10));
expect(
FakeMatrixApi.calledEndpoints.keys
.any((k) => k == '/client/r0/keys/signatures/upload'),
true);
expect(key.directVerified, true);
FakeMatrixApi.calledEndpoints.clear();
await key.setVerified(false);
await Future.delayed(Duration(milliseconds: 10));
expect(
FakeMatrixApi.calledEndpoints.keys
.any((k) => k == '/client/r0/keys/signatures/upload'),
false);
expect(key.directVerified, false);
});
test('verification based on signatures', () async {
final user = client.userDeviceKeys[client.userID];
user.masterKey.setDirectVerified(true);
expect(user.deviceKeys['GHTYAJCE'].crossVerified, true);
expect(user.deviceKeys['GHTYAJCE'].signed, true);
expect(user.getKey('GHTYAJCE').crossVerified, true);
expect(user.deviceKeys['OTHERDEVICE'].crossVerified, true);
expect(user.selfSigningKey.crossVerified, true);
expect(
user
.getKey('F9ypFzgbISXCzxQhhSnXMkc1vq12Luna3Nw5rqViOJY')
.crossVerified,
true);
expect(user.userSigningKey.crossVerified, true);
expect(user.verified, UserVerifiedStatus.verified);
user.masterKey.setDirectVerified(false);
expect(user.deviceKeys['GHTYAJCE'].crossVerified, false);
expect(user.deviceKeys['OTHERDEVICE'].crossVerified, false);
expect(user.verified, UserVerifiedStatus.unknown);
user.masterKey.setDirectVerified(true);
user.deviceKeys['GHTYAJCE'].signatures.clear();
expect(user.deviceKeys['GHTYAJCE'].verified,
true); // it's our own device, should be direct verified
expect(
user.deviceKeys['GHTYAJCE'].signed, false); // not verified for others
user.deviceKeys['OTHERDEVICE'].signatures.clear();
expect(user.verified, UserVerifiedStatus.unknownDevice);
});
test('start verification', () async {
var req = client
.userDeviceKeys['@alice:example.com'].deviceKeys['JLAFKJWSCS']
.startVerification();
expect(req != null, true);
expect(req.room != null, false);
req =
await client.userDeviceKeys['@alice:example.com'].startVerification();
expect(req != null, true);
expect(req.room != null, true);
});
test('dispose client', () async {
await client.dispose(closeDatabase: true);
}); });
}); });
} }

View file

@ -1799,7 +1799,12 @@ class FakeMatrixApi extends MockClient {
'ed25519:GHTYAJCE': 'ed25519:GHTYAJCE':
'gjL//fyaFHADt9KBADGag8g7F8Up78B/K1zXeiEPLJo' 'gjL//fyaFHADt9KBADGag8g7F8Up78B/K1zXeiEPLJo'
}, },
'signatures': {}, 'signatures': {
'@test:fakeServer.notExisting': {
'ed25519:F9ypFzgbISXCzxQhhSnXMkc1vq12Luna3Nw5rqViOJY':
'Q4/55vZjEJD7M2EC40bgZqd9Zuy/4C75UPVopJdXeioQVaKtFf6EF0nUUuql0yD+r3hinsZcock0wO6Q2xcoAQ',
},
},
}, },
'OTHERDEVICE': { 'OTHERDEVICE': {
'user_id': '@test:fakeServer.notExisting', 'user_id': '@test:fakeServer.notExisting',
@ -1812,7 +1817,12 @@ class FakeMatrixApi extends MockClient {
'curve25519:OTHERDEVICE': 'blah', 'curve25519:OTHERDEVICE': 'blah',
'ed25519:OTHERDEVICE': 'blah' 'ed25519:OTHERDEVICE': 'blah'
}, },
'signatures': {}, 'signatures': {
'@test:fakeServer.notExisting': {
'ed25519:F9ypFzgbISXCzxQhhSnXMkc1vq12Luna3Nw5rqViOJY':
'o7ucKPWrF2VKx7wYqP1f+aw4QohLMz7kX+SIw6aWCYsLC3XyIlg8rX/7QQ9B8figCVnRK7IjtjWvQodBCfWCAA',
},
},
}, },
}, },
'@othertest:fakeServer.notExisting': { '@othertest:fakeServer.notExisting': {
@ -1860,7 +1870,12 @@ class FakeMatrixApi extends MockClient {
'ed25519:F9ypFzgbISXCzxQhhSnXMkc1vq12Luna3Nw5rqViOJY': 'ed25519:F9ypFzgbISXCzxQhhSnXMkc1vq12Luna3Nw5rqViOJY':
'F9ypFzgbISXCzxQhhSnXMkc1vq12Luna3Nw5rqViOJY', 'F9ypFzgbISXCzxQhhSnXMkc1vq12Luna3Nw5rqViOJY',
}, },
'signatures': {}, 'signatures': {
'@test:fakeServer.notExisting': {
'ed25519:82mAXjsmbTbrE6zyShpR869jnrANO75H8nYY0nDLoJ8':
'afkrbGvPn5Zb5zc7Lk9cz2skI3QrzI/L0st1GS+/GATxNjMzc6vKmGu7r9cMb1GJxy4RdeUpfH3L7Fs/fNL1Dw',
},
},
}, },
'@othertest:fakeServer.notExisting': { '@othertest:fakeServer.notExisting': {
'user_id': '@othertest:fakeServer.notExisting', 'user_id': '@othertest:fakeServer.notExisting',
@ -1879,7 +1894,12 @@ class FakeMatrixApi extends MockClient {
'ed25519:0PiwulzJ/RU86LlzSSZ8St80HUMN3dqjKa/orIJoA0g': 'ed25519:0PiwulzJ/RU86LlzSSZ8St80HUMN3dqjKa/orIJoA0g':
'0PiwulzJ/RU86LlzSSZ8St80HUMN3dqjKa/orIJoA0g', '0PiwulzJ/RU86LlzSSZ8St80HUMN3dqjKa/orIJoA0g',
}, },
'signatures': {}, 'signatures': {
'@test:fakeServer.notExisting': {
'ed25519:82mAXjsmbTbrE6zyShpR869jnrANO75H8nYY0nDLoJ8':
'pvgbZxEbllaElhpiRnb7/uOIUhrglvHCFnpoxr3/5ZrWa0EK/uaefhex9eEV4uBLrHjHg2ymwdNaM7ap9+sBBg',
},
},
}, },
'@othertest:fakeServer.notExisting': { '@othertest:fakeServer.notExisting': {
'user_id': '@othertest:fakeServer.notExisting', 'user_id': '@othertest:fakeServer.notExisting',