refactor: port encryption tests

This commit is contained in:
Nicolas Werner 2021-10-28 03:40:52 +02:00
parent 32c6e0ec6e
commit e6f77924d6
No known key found for this signature in database
GPG Key ID: C8D75E610773F2D9
10 changed files with 506 additions and 487 deletions

View File

@ -1,4 +1,3 @@
// @dart=2.9
/*
* Famedly Matrix SDK
* Copyright (C) 2020 Famedly GmbH
@ -33,9 +32,9 @@ void main() {
Logs().level = Level.error;
var olmEnabled = true;
Client client;
Map<String, dynamic> oldSecret;
String origKeyId;
late Client client;
late Map<String, dynamic> oldSecret;
late String origKeyId;
test('setupClient', () async {
client = await getClient();
@ -53,8 +52,8 @@ void main() {
Logs().i('[LibOlm] Enabled: $olmEnabled');
if (!olmEnabled) return;
Bootstrap bootstrap;
bootstrap = client.encryption.bootstrap(
Bootstrap? bootstrap;
bootstrap = client.encryption!.bootstrap(
onUpdate: () async {
while (bootstrap == null) {
await Future.delayed(Duration(milliseconds: 5));
@ -82,7 +81,7 @@ void main() {
while (bootstrap.state != BootstrapState.done) {
await Future.delayed(Duration(milliseconds: 50));
}
final defaultKey = client.encryption.ssss.open();
final defaultKey = client.encryption!.ssss.open();
await defaultKey.unlock(passphrase: 'foxies');
// test all the x-signing keys match up
@ -95,8 +94,8 @@ void main() {
expect(
pubKey,
client.userDeviceKeys[client.userID]
.getCrossSigningKey(keyType)
.publicKey);
?.getCrossSigningKey(keyType)
?.publicKey);
} finally {
keyObj.free();
}
@ -104,14 +103,15 @@ void main() {
await defaultKey.store('foxes', 'floof');
await Future.delayed(Duration(milliseconds: 50));
oldSecret = json.decode(json.encode(client.accountData['foxes'].content));
oldSecret =
json.decode(json.encode(client.accountData['foxes']!.content));
origKeyId = defaultKey.keyId;
}, timeout: Timeout(Duration(minutes: 2)));
test('change recovery passphrase', () async {
if (!olmEnabled) return;
Bootstrap bootstrap;
bootstrap = client.encryption.bootstrap(
Bootstrap? bootstrap;
bootstrap = client.encryption!.bootstrap(
onUpdate: () async {
while (bootstrap == null) {
await Future.delayed(Duration(milliseconds: 5));
@ -121,7 +121,7 @@ void main() {
} else if (bootstrap.state == BootstrapState.askUseExistingSsss) {
bootstrap.useExistingSsss(false);
} else if (bootstrap.state == BootstrapState.askUnlockSsss) {
await bootstrap.oldSsssKeys[client.encryption.ssss.defaultKeyId]
await bootstrap.oldSsssKeys![client.encryption!.ssss.defaultKeyId]!
.unlock(passphrase: 'foxies');
bootstrap.unlockedSsss();
} else if (bootstrap.state == BootstrapState.askNewSsss) {
@ -136,7 +136,7 @@ void main() {
while (bootstrap.state != BootstrapState.done) {
await Future.delayed(Duration(milliseconds: 50));
}
final defaultKey = client.encryption.ssss.open();
final defaultKey = client.encryption!.ssss.open();
await defaultKey.unlock(passphrase: 'newfoxies');
// test all the x-signing keys match up
@ -149,8 +149,8 @@ void main() {
expect(
pubKey,
client.userDeviceKeys[client.userID]
.getCrossSigningKey(keyType)
.publicKey);
?.getCrossSigningKey(keyType)
?.publicKey);
} finally {
keyObj.free();
}
@ -161,11 +161,11 @@ void main() {
test('change passphrase with multiple keys', () async {
if (!olmEnabled) return;
await client.setAccountData(client.userID, 'foxes', oldSecret);
await client.setAccountData(client.userID!, 'foxes', oldSecret);
await Future.delayed(Duration(milliseconds: 50));
Bootstrap bootstrap;
bootstrap = client.encryption.bootstrap(
Bootstrap? bootstrap;
bootstrap = client.encryption!.bootstrap(
onUpdate: () async {
while (bootstrap == null) {
await Future.delayed(Duration(milliseconds: 5));
@ -175,9 +175,10 @@ void main() {
} else if (bootstrap.state == BootstrapState.askUseExistingSsss) {
bootstrap.useExistingSsss(false);
} else if (bootstrap.state == BootstrapState.askUnlockSsss) {
await bootstrap.oldSsssKeys[client.encryption.ssss.defaultKeyId]
await bootstrap.oldSsssKeys![client.encryption!.ssss.defaultKeyId]!
.unlock(passphrase: 'newfoxies');
await bootstrap.oldSsssKeys[origKeyId].unlock(passphrase: 'foxies');
await bootstrap.oldSsssKeys![origKeyId]!
.unlock(passphrase: 'foxies');
bootstrap.unlockedSsss();
} else if (bootstrap.state == BootstrapState.askNewSsss) {
await bootstrap.newSsss('supernewfoxies');
@ -191,7 +192,7 @@ void main() {
while (bootstrap.state != BootstrapState.done) {
await Future.delayed(Duration(milliseconds: 50));
}
final defaultKey = client.encryption.ssss.open();
final defaultKey = client.encryption!.ssss.open();
await defaultKey.unlock(passphrase: 'supernewfoxies');
// test all the x-signing keys match up
@ -204,8 +205,8 @@ void main() {
expect(
pubKey,
client.userDeviceKeys[client.userID]
.getCrossSigningKey(keyType)
.publicKey);
?.getCrossSigningKey(keyType)
?.publicKey);
} finally {
keyObj.free();
}
@ -217,8 +218,8 @@ void main() {
test('setup new ssss', () async {
if (!olmEnabled) return;
client.accountData.clear();
Bootstrap bootstrap;
bootstrap = client.encryption.bootstrap(
Bootstrap? bootstrap;
bootstrap = client.encryption!.bootstrap(
onUpdate: () async {
while (bootstrap == null) {
await Future.delayed(Duration(milliseconds: 5));
@ -236,18 +237,18 @@ void main() {
while (bootstrap.state != BootstrapState.done) {
await Future.delayed(Duration(milliseconds: 50));
}
final defaultKey = client.encryption.ssss.open();
final defaultKey = client.encryption!.ssss.open();
await defaultKey.unlock(passphrase: 'thenewestfoxies');
}, timeout: Timeout(Duration(minutes: 2)));
test('bad ssss', () async {
if (!olmEnabled) return;
client.accountData.clear();
await client.setAccountData(client.userID, 'foxes', oldSecret);
await client.setAccountData(client.userID!, 'foxes', oldSecret);
await Future.delayed(Duration(milliseconds: 50));
var askedBadSsss = false;
Bootstrap bootstrap;
bootstrap = client.encryption.bootstrap(
Bootstrap? bootstrap;
bootstrap = client.encryption!.bootstrap(
onUpdate: () async {
while (bootstrap == null) {
await Future.delayed(Duration(milliseconds: 5));

View File

@ -1,4 +1,3 @@
// @dart=2.9
/*
* Famedly Matrix SDK
* Copyright (C) 2020 Famedly GmbH
@ -32,7 +31,7 @@ void main() {
Logs().level = Level.error;
var olmEnabled = true;
Client client;
late Client client;
test('setupClient', () async {
try {
@ -50,41 +49,43 @@ void main() {
test('basic things', () async {
if (!olmEnabled) return;
expect(client.encryption.crossSigning.enabled, true);
expect(client.encryption?.crossSigning.enabled, true);
});
test('selfSign', () async {
if (!olmEnabled) return;
final key = client.userDeviceKeys[client.userID].masterKey;
final key = client.userDeviceKeys[client.userID]!.masterKey!;
key.setDirectVerified(false);
FakeMatrixApi.calledEndpoints.clear();
await client.encryption.crossSigning.selfSign(recoveryKey: ssssKey);
await client.encryption!.crossSigning.selfSign(recoveryKey: ssssKey);
expect(key.directVerified, true);
expect(
FakeMatrixApi.calledEndpoints
.containsKey('/client/r0/keys/signatures/upload'),
true);
expect(await client.encryption.crossSigning.isCached(), true);
expect(await client.encryption!.crossSigning.isCached(), true);
});
test('signable', () async {
if (!olmEnabled) return;
expect(
client.encryption.crossSigning
.signable([client.userDeviceKeys[client.userID].masterKey]),
client.encryption!.crossSigning
.signable([client.userDeviceKeys[client.userID!]!.masterKey!]),
true);
expect(
client.encryption.crossSigning.signable([
client.userDeviceKeys[client.userID].deviceKeys[client.deviceID]
client.encryption!.crossSigning.signable([
client.userDeviceKeys[client.userID!]!.deviceKeys[client.deviceID!]!
]),
false);
expect(
client.encryption.crossSigning.signable(
[client.userDeviceKeys[client.userID].deviceKeys['OTHERDEVICE']]),
client.encryption!.crossSigning.signable([
client.userDeviceKeys[client.userID!]!.deviceKeys['OTHERDEVICE']!
]),
true);
expect(
client.encryption.crossSigning.signable([
client.userDeviceKeys['@alice:example.com'].deviceKeys['JLAFKJWSCS']
client.encryption!.crossSigning.signable([
client
.userDeviceKeys['@alice:example.com']!.deviceKeys['JLAFKJWSCS']!
]),
false);
});
@ -92,24 +93,24 @@ void main() {
test('sign', () async {
if (!olmEnabled) return;
FakeMatrixApi.calledEndpoints.clear();
await client.encryption.crossSigning.sign([
client.userDeviceKeys[client.userID].masterKey,
client.userDeviceKeys[client.userID].deviceKeys['OTHERDEVICE'],
client.userDeviceKeys['@othertest:fakeServer.notExisting'].masterKey
await client.encryption!.crossSigning.sign([
client.userDeviceKeys[client.userID!]!.masterKey!,
client.userDeviceKeys[client.userID!]!.deviceKeys['OTHERDEVICE']!,
client.userDeviceKeys['@othertest:fakeServer.notExisting']!.masterKey!
]);
final body = json.decode(FakeMatrixApi
.calledEndpoints['/client/r0/keys/signatures/upload'].first);
.calledEndpoints['/client/r0/keys/signatures/upload']!.first);
expect(body['@test:fakeServer.notExisting']?.containsKey('OTHERDEVICE'),
true);
expect(
body['@test:fakeServer.notExisting'].containsKey(
client.userDeviceKeys[client.userID].masterKey.publicKey),
client.userDeviceKeys[client.userID]!.masterKey!.publicKey),
true);
expect(
body['@othertest:fakeServer.notExisting'].containsKey(client
.userDeviceKeys['@othertest:fakeServer.notExisting']
.masterKey
.publicKey),
?.masterKey
?.publicKey),
true);
});

View File

@ -1,4 +1,3 @@
// @dart=2.9
/*
* Famedly Matrix SDK
* Copyright (C) 2020 Famedly GmbH
@ -29,10 +28,10 @@ void main() {
Logs().level = Level.error;
var olmEnabled = true;
Client client;
late Client client;
final roomId = '!726s6s6q:example.com';
Room room;
Map<String, dynamic> payload;
late Room room;
late Map<String, dynamic> payload;
final now = DateTime.now();
test('setupClient', () async {
@ -47,12 +46,12 @@ void main() {
if (!olmEnabled) return;
client = await getClient();
room = client.getRoomById(roomId);
room = client.getRoomById(roomId)!;
});
test('encrypt payload', () async {
if (!olmEnabled) return;
payload = await client.encryption.encryptGroupMessagePayload(roomId, {
payload = await client.encryption!.encryptGroupMessagePayload(roomId, {
'msgtype': 'm.text',
'text': 'Hello foxies!',
});
@ -72,10 +71,10 @@ void main() {
room: room,
originServerTs: now,
eventId: '\$event',
senderId: client.userID,
senderId: client.userID!,
);
final decryptedEvent =
await client.encryption.decryptRoomEvent(roomId, encryptedEvent);
await client.encryption!.decryptRoomEvent(roomId, encryptedEvent);
expect(decryptedEvent.type, 'm.room.message');
expect(decryptedEvent.content['msgtype'], 'm.text');
expect(decryptedEvent.content['text'], 'Hello foxies!');
@ -83,7 +82,7 @@ void main() {
test('decrypt payload nocache', () async {
if (!olmEnabled) return;
client.encryption.keyManager.clearInboundGroupSessions();
client.encryption!.keyManager.clearInboundGroupSessions();
final encryptedEvent = Event(
type: EventTypes.Encrypted,
content: payload,
@ -94,11 +93,11 @@ void main() {
senderId: '@alice:example.com',
);
final decryptedEvent =
await client.encryption.decryptRoomEvent(roomId, encryptedEvent);
await client.encryption!.decryptRoomEvent(roomId, encryptedEvent);
expect(decryptedEvent.type, 'm.room.message');
expect(decryptedEvent.content['msgtype'], 'm.text');
expect(decryptedEvent.content['text'], 'Hello foxies!');
await client.encryption
await client.encryption!
.decryptRoomEvent(roomId, encryptedEvent, store: true);
});

View File

@ -1,4 +1,3 @@
// @dart=2.9
/*
* Famedly Matrix SDK
* Copyright (C) 2020 Famedly GmbH
@ -35,11 +34,11 @@ void main() {
Logs().level = Level.error;
var olmEnabled = true;
Client client;
late Client client;
final otherClient = Client('othertestclient',
httpClient: FakeMatrixApi(), databaseBuilder: getDatabase);
DeviceKeys device;
Map<String, dynamic> payload;
late DeviceKeys device;
late Map<String, dynamic> payload;
test('setupClient', () async {
try {
@ -83,7 +82,7 @@ void main() {
test('encryptToDeviceMessage', () async {
if (!olmEnabled) return;
payload = await otherClient.encryption
payload = await otherClient.encryption!
.encryptToDeviceMessage([device], 'm.to_device', {'hello': 'foxies'});
});
@ -95,15 +94,15 @@ void main() {
content: payload[client.userID][client.deviceID],
);
final decryptedEvent =
await client.encryption.decryptToDeviceEvent(encryptedEvent);
await client.encryption!.decryptToDeviceEvent(encryptedEvent);
expect(decryptedEvent.type, 'm.to_device');
expect(decryptedEvent.content['hello'], 'foxies');
});
test('decryptToDeviceEvent nocache', () async {
if (!olmEnabled) return;
client.encryption.olmManager.olmSessions.clear();
payload = await otherClient.encryption.encryptToDeviceMessage(
client.encryption!.olmManager.olmSessions.clear();
payload = await otherClient.encryption!.encryptToDeviceMessage(
[device], 'm.to_device', {'hello': 'superfoxies'});
final encryptedEvent = ToDeviceEvent(
sender: '@othertest:fakeServer.notExisting',
@ -111,7 +110,7 @@ void main() {
content: payload[client.userID][client.deviceID],
);
final decryptedEvent =
await client.encryption.decryptToDeviceEvent(encryptedEvent);
await client.encryption!.decryptToDeviceEvent(encryptedEvent);
expect(decryptedEvent.type, 'm.to_device');
expect(decryptedEvent.content['hello'], 'superfoxies');
});

View File

@ -1,4 +1,3 @@
// @dart=2.9
/*
* Famedly Matrix SDK
* Copyright (C) 2020 Famedly GmbH
@ -32,7 +31,7 @@ void main() {
Logs().level = Level.error;
var olmEnabled = true;
Client client;
late Client client;
test('setupClient', () async {
try {
@ -55,7 +54,7 @@ void main() {
final sessionKey =
'AgAAAAAQcQ6XrFJk6Prm8FikZDqfry/NbDz8Xw7T6e+/9Yf/q3YHIPEQlzv7IZMNcYb51ifkRzFejVvtphS7wwG2FaXIp4XS2obla14iKISR0X74ugB2vyb1AydIHE/zbBQ1ic5s3kgjMFlWpu/S3FQCnCrv+DPFGEt3ERGWxIl3Bl5X53IjPyVkz65oljz2TZESwz0GH/QFvyOOm8ci0q/gceaF3S7Dmafg3dwTKYwcA5xkcc+BLyrLRzB6Hn+oMAqSNSscnm4mTeT5zYibIhrzqyUTMWr32spFtI9dNR/RFSzfCw';
client.encryption.keyManager.clearInboundGroupSessions();
client.encryption!.keyManager.clearInboundGroupSessions();
var event = ToDeviceEvent(
sender: '@alice:example.com',
type: 'm.room_key',
@ -68,9 +67,9 @@ void main() {
encryptedContent: {
'sender_key': validSenderKey,
});
await client.encryption.keyManager.handleToDeviceEvent(event);
await client.encryption!.keyManager.handleToDeviceEvent(event);
expect(
client.encryption.keyManager.getInboundGroupSession(
client.encryption!.keyManager.getInboundGroupSession(
'!726s6s6q:example.com', validSessionId, validSenderKey) !=
null,
true);
@ -78,7 +77,7 @@ void main() {
// now test a few invalid scenarios
// not encrypted
client.encryption.keyManager.clearInboundGroupSessions();
client.encryption!.keyManager.clearInboundGroupSessions();
event = ToDeviceEvent(
sender: '@alice:example.com',
type: 'm.room_key',
@ -88,9 +87,9 @@ void main() {
'session_id': validSessionId,
'session_key': sessionKey,
});
await client.encryption.keyManager.handleToDeviceEvent(event);
await client.encryption!.keyManager.handleToDeviceEvent(event);
expect(
client.encryption.keyManager.getInboundGroupSession(
client.encryption!.keyManager.getInboundGroupSession(
'!726s6s6q:example.com', validSessionId, validSenderKey) !=
null,
false);
@ -100,99 +99,104 @@ void main() {
if (!olmEnabled) return;
final roomId = '!726s6s6q:example.com';
expect(
client.encryption.keyManager.getOutboundGroupSession(roomId) != null,
client.encryption!.keyManager.getOutboundGroupSession(roomId) != null,
false);
var sess =
await client.encryption.keyManager.createOutboundGroupSession(roomId);
var sess = await client.encryption!.keyManager
.createOutboundGroupSession(roomId);
expect(
client.encryption.keyManager.getOutboundGroupSession(roomId) != null,
client.encryption!.keyManager.getOutboundGroupSession(roomId) != null,
true);
await client.encryption.keyManager.clearOrUseOutboundGroupSession(roomId);
await client.encryption!.keyManager
.clearOrUseOutboundGroupSession(roomId);
expect(
client.encryption.keyManager.getOutboundGroupSession(roomId) != null,
client.encryption!.keyManager.getOutboundGroupSession(roomId) != null,
true);
var inbound = client.encryption.keyManager.getInboundGroupSession(
roomId, sess.outboundGroupSession.session_id(), client.identityKey);
var inbound = client.encryption!.keyManager.getInboundGroupSession(
roomId, sess.outboundGroupSession!.session_id(), client.identityKey);
expect(inbound != null, true);
expect(
inbound.allowedAtIndex['@alice:example.com']
['L+4+JCl8MD63dgo8z5Ta+9QAHXiANyOVSfgbHA5d3H8'],
inbound!.allowedAtIndex['@alice:example.com']
?['L+4+JCl8MD63dgo8z5Ta+9QAHXiANyOVSfgbHA5d3H8'],
0);
expect(
inbound.allowedAtIndex['@alice:example.com']
['wMIDhiQl5jEXQrTB03ePOSQfR8sA/KMrW0CIfFfXKEE'],
?['wMIDhiQl5jEXQrTB03ePOSQfR8sA/KMrW0CIfFfXKEE'],
0);
// rotate after too many messages
Iterable.generate(300).forEach((_) {
sess.outboundGroupSession.encrypt('some string');
sess.outboundGroupSession!.encrypt('some string');
});
await client.encryption.keyManager.clearOrUseOutboundGroupSession(roomId);
await client.encryption!.keyManager
.clearOrUseOutboundGroupSession(roomId);
expect(
client.encryption.keyManager.getOutboundGroupSession(roomId) != null,
client.encryption!.keyManager.getOutboundGroupSession(roomId) != null,
false);
// rotate if device is blocked
sess =
await client.encryption.keyManager.createOutboundGroupSession(roomId);
client.userDeviceKeys['@alice:example.com'].deviceKeys['JLAFKJWSCS']
sess = await client.encryption!.keyManager
.createOutboundGroupSession(roomId);
client.userDeviceKeys['@alice:example.com']!.deviceKeys['JLAFKJWSCS']!
.blocked = true;
await client.encryption.keyManager.clearOrUseOutboundGroupSession(roomId);
await client.encryption!.keyManager
.clearOrUseOutboundGroupSession(roomId);
expect(
client.encryption.keyManager.getOutboundGroupSession(roomId) != null,
client.encryption!.keyManager.getOutboundGroupSession(roomId) != null,
false);
client.userDeviceKeys['@alice:example.com'].deviceKeys['JLAFKJWSCS']
client.userDeviceKeys['@alice:example.com']!.deviceKeys['JLAFKJWSCS']!
.blocked = false;
// lazy-create if it would rotate
sess =
await client.encryption.keyManager.createOutboundGroupSession(roomId);
final oldSessKey = sess.outboundGroupSession.session_key();
client.userDeviceKeys['@alice:example.com'].deviceKeys['JLAFKJWSCS']
sess = await client.encryption!.keyManager
.createOutboundGroupSession(roomId);
final oldSessKey = sess.outboundGroupSession!.session_key();
client.userDeviceKeys['@alice:example.com']!.deviceKeys['JLAFKJWSCS']!
.blocked = true;
await client.encryption.keyManager.prepareOutboundGroupSession(roomId);
await client.encryption!.keyManager.prepareOutboundGroupSession(roomId);
expect(
client.encryption.keyManager.getOutboundGroupSession(roomId) != null,
client.encryption!.keyManager.getOutboundGroupSession(roomId) != null,
true);
expect(
client.encryption.keyManager
.getOutboundGroupSession(roomId)
.outboundGroupSession
client.encryption!.keyManager
.getOutboundGroupSession(roomId)!
.outboundGroupSession!
.session_key() !=
oldSessKey,
true);
client.userDeviceKeys['@alice:example.com'].deviceKeys['JLAFKJWSCS']
client.userDeviceKeys['@alice:example.com']!.deviceKeys['JLAFKJWSCS']!
.blocked = false;
// rotate if too far in the past
sess =
await client.encryption.keyManager.createOutboundGroupSession(roomId);
sess = await client.encryption!.keyManager
.createOutboundGroupSession(roomId);
sess.creationTime = DateTime.now().subtract(Duration(days: 30));
await client.encryption.keyManager.clearOrUseOutboundGroupSession(roomId);
await client.encryption!.keyManager
.clearOrUseOutboundGroupSession(roomId);
expect(
client.encryption.keyManager.getOutboundGroupSession(roomId) != null,
client.encryption!.keyManager.getOutboundGroupSession(roomId) != null,
false);
// rotate if user leaves
sess =
await client.encryption.keyManager.createOutboundGroupSession(roomId);
final room = client.getRoomById(roomId);
sess = await client.encryption!.keyManager
.createOutboundGroupSession(roomId);
final room = client.getRoomById(roomId)!;
final member = room.getState('m.room.member', '@alice:example.com');
member.content['membership'] = 'leave';
room.summary.mJoinedMemberCount--;
await client.encryption.keyManager.clearOrUseOutboundGroupSession(roomId);
member!.content['membership'] = 'leave';
room.summary.mJoinedMemberCount = room.summary.mJoinedMemberCount! - 1;
await client.encryption!.keyManager
.clearOrUseOutboundGroupSession(roomId);
expect(
client.encryption.keyManager.getOutboundGroupSession(roomId) != null,
client.encryption!.keyManager.getOutboundGroupSession(roomId) != null,
false);
member.content['membership'] = 'join';
room.summary.mJoinedMemberCount++;
room.summary.mJoinedMemberCount = room.summary.mJoinedMemberCount! + 1;
// do not rotate if new device is added
sess =
await client.encryption.keyManager.createOutboundGroupSession(roomId);
sess.outboundGroupSession.encrypt(
sess = await client.encryption!.keyManager
.createOutboundGroupSession(roomId);
sess.outboundGroupSession!.encrypt(
'foxies'); // so that the new device will have a different index
client.userDeviceKeys['@alice:example.com'].deviceKeys['NEWDEVICE'] =
client.userDeviceKeys['@alice:example.com']?.deviceKeys['NEWDEVICE'] =
DeviceKeys.fromJson({
'user_id': '@alice:example.com',
'device_id': 'NEWDEVICE',
@ -211,56 +215,58 @@ void main() {
}
}
}, client);
await client.encryption.keyManager.clearOrUseOutboundGroupSession(roomId);
await client.encryption!.keyManager
.clearOrUseOutboundGroupSession(roomId);
expect(
client.encryption.keyManager.getOutboundGroupSession(roomId) != null,
client.encryption!.keyManager.getOutboundGroupSession(roomId) != null,
true);
inbound = client.encryption.keyManager.getInboundGroupSession(
roomId, sess.outboundGroupSession.session_id(), client.identityKey);
inbound = client.encryption!.keyManager.getInboundGroupSession(
roomId, sess.outboundGroupSession!.session_id(), client.identityKey);
expect(
inbound.allowedAtIndex['@alice:example.com']
['L+4+JCl8MD63dgo8z5Ta+9QAHXiANyOVSfgbHA5d3H8'],
inbound!.allowedAtIndex['@alice:example.com']
?['L+4+JCl8MD63dgo8z5Ta+9QAHXiANyOVSfgbHA5d3H8'],
0);
expect(
inbound.allowedAtIndex['@alice:example.com']
['wMIDhiQl5jEXQrTB03ePOSQfR8sA/KMrW0CIfFfXKEE'],
?['wMIDhiQl5jEXQrTB03ePOSQfR8sA/KMrW0CIfFfXKEE'],
0);
expect(
inbound.allowedAtIndex['@alice:example.com']
['bnKQp6pPW0l9cGoIgHpBoK5OUi4h0gylJ7upc4asFV8'],
?['bnKQp6pPW0l9cGoIgHpBoK5OUi4h0gylJ7upc4asFV8'],
1);
// do not rotate if new user is added
member.content['membership'] = 'leave';
room.summary.mJoinedMemberCount--;
sess =
await client.encryption.keyManager.createOutboundGroupSession(roomId);
room.summary.mJoinedMemberCount = room.summary.mJoinedMemberCount! - 1;
sess = await client.encryption!.keyManager
.createOutboundGroupSession(roomId);
member.content['membership'] = 'join';
room.summary.mJoinedMemberCount++;
await client.encryption.keyManager.clearOrUseOutboundGroupSession(roomId);
room.summary.mJoinedMemberCount = room.summary.mJoinedMemberCount! + 1;
await client.encryption!.keyManager
.clearOrUseOutboundGroupSession(roomId);
expect(
client.encryption.keyManager.getOutboundGroupSession(roomId) != null,
client.encryption!.keyManager.getOutboundGroupSession(roomId) != null,
true);
// force wipe
sess =
await client.encryption.keyManager.createOutboundGroupSession(roomId);
await client.encryption.keyManager
sess = await client.encryption!.keyManager
.createOutboundGroupSession(roomId);
await client.encryption!.keyManager
.clearOrUseOutboundGroupSession(roomId, wipe: true);
expect(
client.encryption.keyManager.getOutboundGroupSession(roomId) != null,
client.encryption!.keyManager.getOutboundGroupSession(roomId) != null,
false);
// load from database
sess =
await client.encryption.keyManager.createOutboundGroupSession(roomId);
client.encryption.keyManager.clearOutboundGroupSessions();
sess = await client.encryption!.keyManager
.createOutboundGroupSession(roomId);
client.encryption!.keyManager.clearOutboundGroupSessions();
expect(
client.encryption.keyManager.getOutboundGroupSession(roomId) != null,
client.encryption!.keyManager.getOutboundGroupSession(roomId) != null,
false);
await client.encryption.keyManager.loadOutboundGroupSession(roomId);
await client.encryption!.keyManager.loadOutboundGroupSession(roomId);
expect(
client.encryption.keyManager.getOutboundGroupSession(roomId) != null,
client.encryption!.keyManager.getOutboundGroupSession(roomId) != null,
true);
});
@ -276,71 +282,71 @@ void main() {
'session_key':
'AgAAAAAQcQ6XrFJk6Prm8FikZDqfry/NbDz8Xw7T6e+/9Yf/q3YHIPEQlzv7IZMNcYb51ifkRzFejVvtphS7wwG2FaXIp4XS2obla14iKISR0X74ugB2vyb1AydIHE/zbBQ1ic5s3kgjMFlWpu/S3FQCnCrv+DPFGEt3ERGWxIl3Bl5X53IjPyVkz65oljz2TZESwz0GH/QFvyOOm8ci0q/gceaF3S7Dmafg3dwTKYwcA5xkcc+BLyrLRzB6Hn+oMAqSNSscnm4mTeT5zYibIhrzqyUTMWr32spFtI9dNR/RFSzfCw'
};
client.encryption.keyManager.clearInboundGroupSessions();
client.encryption!.keyManager.clearInboundGroupSessions();
expect(
client.encryption.keyManager
client.encryption!.keyManager
.getInboundGroupSession(roomId, sessionId, senderKey) !=
null,
false);
client.encryption.keyManager
client.encryption!.keyManager
.setInboundGroupSession(roomId, sessionId, senderKey, sessionContent);
await Future.delayed(Duration(milliseconds: 10));
expect(
client.encryption.keyManager
client.encryption!.keyManager
.getInboundGroupSession(roomId, sessionId, senderKey) !=
null,
true);
expect(
client.encryption.keyManager
client.encryption!.keyManager
.getInboundGroupSession(roomId, sessionId, 'invalid') !=
null,
false);
expect(
client.encryption.keyManager
client.encryption!.keyManager
.getInboundGroupSession(roomId, sessionId, senderKey) !=
null,
true);
expect(
client.encryption.keyManager
client.encryption!.keyManager
.getInboundGroupSession('otherroom', sessionId, senderKey) !=
null,
true);
expect(
client.encryption.keyManager
client.encryption!.keyManager
.getInboundGroupSession('otherroom', sessionId, 'invalid') !=
null,
false);
expect(
client.encryption.keyManager
client.encryption!.keyManager
.getInboundGroupSession('otherroom', 'invalid', senderKey) !=
null,
false);
client.encryption.keyManager.clearInboundGroupSessions();
client.encryption!.keyManager.clearInboundGroupSessions();
expect(
client.encryption.keyManager
client.encryption!.keyManager
.getInboundGroupSession(roomId, sessionId, senderKey) !=
null,
false);
await client.encryption.keyManager
await client.encryption!.keyManager
.loadInboundGroupSession(roomId, sessionId, senderKey);
expect(
client.encryption.keyManager
client.encryption!.keyManager
.getInboundGroupSession(roomId, sessionId, senderKey) !=
null,
true);
client.encryption.keyManager.clearInboundGroupSessions();
client.encryption!.keyManager.clearInboundGroupSessions();
expect(
client.encryption.keyManager
client.encryption!.keyManager
.getInboundGroupSession(roomId, sessionId, senderKey) !=
null,
false);
await client.encryption.keyManager
await client.encryption!.keyManager
.loadInboundGroupSession(roomId, sessionId, 'invalid');
expect(
client.encryption.keyManager
client.encryption!.keyManager
.getInboundGroupSession(roomId, sessionId, 'invalid') !=
null,
false);
@ -379,7 +385,7 @@ void main() {
stateKey: '',
),
);
expect(room.lastEvent.type, 'm.room.encrypted');
expect(room.lastEvent?.type, 'm.room.encrypted');
// set a payload...
var sessionPayload = <String, dynamic>{
'algorithm': AlgorithmTypes.megolmV1AesSha2,
@ -390,20 +396,20 @@ void main() {
'sender_key': senderKey,
'sender_claimed_ed25519_key': client.fingerprintKey,
};
client.encryption.keyManager.setInboundGroupSession(
client.encryption!.keyManager.setInboundGroupSession(
roomId, sessionId, senderKey, sessionPayload,
forwarded: true);
expect(
client.encryption.keyManager
client.encryption!.keyManager
.getInboundGroupSession(roomId, sessionId, senderKey)
.inboundGroupSession
.first_known_index(),
?.inboundGroupSession
?.first_known_index(),
1);
expect(
client.encryption.keyManager
client.encryption!.keyManager
.getInboundGroupSession(roomId, sessionId, senderKey)
.forwardingCurve25519KeyChain
.length,
?.forwardingCurve25519KeyChain
?.length,
1);
// not set one with a higher first known index
@ -416,20 +422,20 @@ void main() {
'sender_key': senderKey,
'sender_claimed_ed25519_key': client.fingerprintKey,
};
client.encryption.keyManager.setInboundGroupSession(
client.encryption!.keyManager.setInboundGroupSession(
roomId, sessionId, senderKey, sessionPayload,
forwarded: true);
expect(
client.encryption.keyManager
client.encryption!.keyManager
.getInboundGroupSession(roomId, sessionId, senderKey)
.inboundGroupSession
.first_known_index(),
?.inboundGroupSession
?.first_known_index(),
1);
expect(
client.encryption.keyManager
client.encryption!.keyManager
.getInboundGroupSession(roomId, sessionId, senderKey)
.forwardingCurve25519KeyChain
.length,
?.forwardingCurve25519KeyChain
?.length,
1);
// set one with a lower first known index
@ -442,20 +448,20 @@ void main() {
'sender_key': senderKey,
'sender_claimed_ed25519_key': client.fingerprintKey,
};
client.encryption.keyManager.setInboundGroupSession(
client.encryption!.keyManager.setInboundGroupSession(
roomId, sessionId, senderKey, sessionPayload,
forwarded: true);
expect(
client.encryption.keyManager
client.encryption!.keyManager
.getInboundGroupSession(roomId, sessionId, senderKey)
.inboundGroupSession
.first_known_index(),
?.inboundGroupSession
?.first_known_index(),
0);
expect(
client.encryption.keyManager
client.encryption!.keyManager
.getInboundGroupSession(roomId, sessionId, senderKey)
.forwardingCurve25519KeyChain
.length,
?.forwardingCurve25519KeyChain
?.length,
1);
// not set one with a longer forwarding chain
@ -468,20 +474,20 @@ void main() {
'sender_key': senderKey,
'sender_claimed_ed25519_key': client.fingerprintKey,
};
client.encryption.keyManager.setInboundGroupSession(
client.encryption!.keyManager.setInboundGroupSession(
roomId, sessionId, senderKey, sessionPayload,
forwarded: true);
expect(
client.encryption.keyManager
client.encryption!.keyManager
.getInboundGroupSession(roomId, sessionId, senderKey)
.inboundGroupSession
.first_known_index(),
?.inboundGroupSession
?.first_known_index(),
0);
expect(
client.encryption.keyManager
client.encryption!.keyManager
.getInboundGroupSession(roomId, sessionId, senderKey)
.forwardingCurve25519KeyChain
.length,
?.forwardingCurve25519KeyChain
?.length,
1);
// set one with a shorter forwarding chain
@ -494,25 +500,25 @@ void main() {
'sender_key': senderKey,
'sender_claimed_ed25519_key': client.fingerprintKey,
};
client.encryption.keyManager.setInboundGroupSession(
client.encryption!.keyManager.setInboundGroupSession(
roomId, sessionId, senderKey, sessionPayload,
forwarded: true);
expect(
client.encryption.keyManager
client.encryption!.keyManager
.getInboundGroupSession(roomId, sessionId, senderKey)
.inboundGroupSession
.first_known_index(),
?.inboundGroupSession
?.first_known_index(),
0);
expect(
client.encryption.keyManager
client.encryption!.keyManager
.getInboundGroupSession(roomId, sessionId, senderKey)
.forwardingCurve25519KeyChain
.length,
?.forwardingCurve25519KeyChain
?.length,
0);
// test that it decrypted the last event
expect(room.lastEvent.type, 'm.room.message');
expect(room.lastEvent.content['body'], 'foxies');
expect(room.lastEvent?.type, 'm.room.message');
expect(room.lastEvent?.content['body'], 'foxies');
inbound.free();
session.free();
@ -521,22 +527,21 @@ void main() {
test('Reused deviceID attack', () async {
if (!olmEnabled) return;
Logs().level = Level.warning;
client ??= await getClient();
// Ensure the device came from sync
expect(
client.userDeviceKeys['@alice:example.com']
.deviceKeys['JLAFKJWSCS'] !=
?.deviceKeys['JLAFKJWSCS'] !=
null,
true);
// Alice removes her device
client.userDeviceKeys['@alice:example.com'].deviceKeys
client.userDeviceKeys['@alice:example.com']?.deviceKeys
.remove('JLAFKJWSCS');
// Alice adds her device with same device ID but different keys
final oldResp = FakeMatrixApi.api['POST']['/client/r0/keys/query'](null);
FakeMatrixApi.api['POST']['/client/r0/keys/query'] = (_) {
final oldResp = FakeMatrixApi.api['POST']?['/client/r0/keys/query'](null);
FakeMatrixApi.api['POST']?['/client/r0/keys/query'] = (_) {
oldResp['device_keys']['@alice:example.com']['JLAFKJWSCS'] = {
'user_id': '@alice:example.com',
'device_id': 'JLAFKJWSCS',
@ -558,10 +563,10 @@ void main() {
};
return oldResp;
};
client.userDeviceKeys['@alice:example.com'].outdated = true;
client.userDeviceKeys['@alice:example.com']!.outdated = true;
await client.updateUserDeviceKeys();
expect(
client.userDeviceKeys['@alice:example.com'].deviceKeys['JLAFKJWSCS'],
client.userDeviceKeys['@alice:example.com']?.deviceKeys['JLAFKJWSCS'],
null);
});

View File

@ -1,4 +1,3 @@
// @dart=2.9
/*
* Famedly Matrix SDK
* Copyright (C) 2020 Famedly GmbH
@ -58,8 +57,8 @@ void main() {
if (!olmEnabled) return;
final matrix = await getClient();
final requestRoom = matrix.getRoomById('!726s6s6q:example.com');
await matrix.encryption.keyManager.request(
final requestRoom = matrix.getRoomById('!726s6s6q:example.com')!;
await matrix.encryption!.keyManager.request(
requestRoom, 'sessionId', validSenderKey,
tryOnlineBackup: false);
var foundEvent = false;
@ -89,12 +88,12 @@ void main() {
matrix.setUserId('@alice:example.com'); // we need to pretend to be alice
FakeMatrixApi.calledEndpoints.clear();
await matrix
.userDeviceKeys['@alice:example.com'].deviceKeys['OTHERDEVICE']
.userDeviceKeys['@alice:example.com']!.deviceKeys['OTHERDEVICE']!
.setBlocked(false);
await matrix
.userDeviceKeys['@alice:example.com'].deviceKeys['OTHERDEVICE']
.userDeviceKeys['@alice:example.com']!.deviceKeys['OTHERDEVICE']!
.setVerified(true);
final session = await matrix.encryption.keyManager
final session = await matrix.encryption!.keyManager
.loadInboundGroupSession(
'!726s6s6q:example.com', validSessionId, validSenderKey);
// test a successful share
@ -112,7 +111,7 @@ void main() {
'request_id': 'request_1',
'requesting_device_id': 'OTHERDEVICE',
});
await matrix.encryption.keyManager.handleToDeviceEvent(event);
await matrix.encryption!.keyManager.handleToDeviceEvent(event);
Logs().i(FakeMatrixApi.calledEndpoints.keys.toString());
expect(
FakeMatrixApi.calledEndpoints.keys.any(
@ -121,9 +120,9 @@ void main() {
// test a successful foreign share
FakeMatrixApi.calledEndpoints.clear();
session.allowedAtIndex['@test:fakeServer.notExisting'] = <String, int>{
matrix.userDeviceKeys['@test:fakeServer.notExisting']
.deviceKeys['OTHERDEVICE'].curve25519Key: 0,
session!.allowedAtIndex['@test:fakeServer.notExisting'] = <String, int>{
matrix.userDeviceKeys['@test:fakeServer.notExisting']!
.deviceKeys['OTHERDEVICE']!.curve25519Key!: 0,
};
event = ToDeviceEvent(
sender: '@test:fakeServer.notExisting',
@ -139,7 +138,7 @@ void main() {
'request_id': 'request_a1',
'requesting_device_id': 'OTHERDEVICE',
});
await matrix.encryption.keyManager.handleToDeviceEvent(event);
await matrix.encryption!.keyManager.handleToDeviceEvent(event);
Logs().i(FakeMatrixApi.calledEndpoints.keys.toString());
expect(
FakeMatrixApi.calledEndpoints.keys.any(
@ -165,7 +164,7 @@ void main() {
'request_id': 'request_a2',
'requesting_device_id': 'OTHERDEVICE',
});
await matrix.encryption.keyManager.handleToDeviceEvent(event);
await matrix.encryption!.keyManager.handleToDeviceEvent(event);
Logs().i(FakeMatrixApi.calledEndpoints.keys.toString());
expect(
FakeMatrixApi.calledEndpoints.keys.any(
@ -182,7 +181,7 @@ void main() {
'request_id': 'request_2',
'requesting_device_id': 'OTHERDEVICE',
});
await matrix.encryption.keyManager.handleToDeviceEvent(event);
await matrix.encryption!.keyManager.handleToDeviceEvent(event);
expect(
FakeMatrixApi.calledEndpoints.keys.any(
(k) => k.startsWith('/client/r0/sendToDevice/m.room.encrypted')),
@ -204,7 +203,7 @@ void main() {
'request_id': 'request_3',
'requesting_device_id': 'JLAFKJWSCS',
});
await matrix.encryption.keyManager.handleToDeviceEvent(event);
await matrix.encryption!.keyManager.handleToDeviceEvent(event);
expect(
FakeMatrixApi.calledEndpoints.keys.any(
(k) => k.startsWith('/client/r0/sendToDevice/m.room.encrypted')),
@ -226,7 +225,7 @@ void main() {
'request_id': 'request_4',
'requesting_device_id': 'blubb',
});
await matrix.encryption.keyManager.handleToDeviceEvent(event);
await matrix.encryption!.keyManager.handleToDeviceEvent(event);
expect(
FakeMatrixApi.calledEndpoints.keys.any(
(k) => k.startsWith('/client/r0/sendToDevice/m.room.encrypted')),
@ -248,7 +247,7 @@ void main() {
'request_id': 'request_5',
'requesting_device_id': 'OTHERDEVICE',
});
await matrix.encryption.keyManager.handleToDeviceEvent(event);
await matrix.encryption!.keyManager.handleToDeviceEvent(event);
expect(
FakeMatrixApi.calledEndpoints.keys.any(
(k) => k.startsWith('/client/r0/sendToDevice/m.room.encrypted')),
@ -270,7 +269,7 @@ void main() {
'request_id': 'request_6',
'requesting_device_id': 'OTHERDEVICE',
});
await matrix.encryption.keyManager.handleToDeviceEvent(event);
await matrix.encryption!.keyManager.handleToDeviceEvent(event);
expect(
FakeMatrixApi.calledEndpoints.keys.any(
(k) => k.startsWith('/client/r0/sendToDevice/m.room.encrypted')),
@ -282,17 +281,17 @@ void main() {
test('Receive shared keys', () async {
if (!olmEnabled) return;
final matrix = await getClient();
final requestRoom = matrix.getRoomById('!726s6s6q:example.com');
await matrix.encryption.keyManager.request(
final requestRoom = matrix.getRoomById('!726s6s6q:example.com')!;
await matrix.encryption!.keyManager.request(
requestRoom, validSessionId, validSenderKey,
tryOnlineBackup: false);
final session = await matrix.encryption.keyManager
final session = (await matrix.encryption!.keyManager
.loadInboundGroupSession(
requestRoom.id, validSessionId, validSenderKey);
final sessionKey = session.inboundGroupSession
.export_session(session.inboundGroupSession.first_known_index());
matrix.encryption.keyManager.clearInboundGroupSessions();
requestRoom.id, validSessionId, validSenderKey))!;
final sessionKey = session.inboundGroupSession!
.export_session(session.inboundGroupSession!.first_known_index());
matrix.encryption!.keyManager.clearInboundGroupSessions();
var event = ToDeviceEvent(
sender: '@alice:example.com',
type: 'm.forwarded_room_key',
@ -303,13 +302,15 @@ void main() {
'session_key': sessionKey,
'sender_key': validSenderKey,
'forwarding_curve25519_key_chain': [],
'sender_claimed_ed25519_key':
'L+4+JCl8MD63dgo8z5Ta+9QAHXiANyOVSfgbHA5d3H8',
},
encryptedContent: {
'sender_key': 'L+4+JCl8MD63dgo8z5Ta+9QAHXiANyOVSfgbHA5d3H8',
});
await matrix.encryption.keyManager.handleToDeviceEvent(event);
await matrix.encryption!.keyManager.handleToDeviceEvent(event);
expect(
matrix.encryption.keyManager.getInboundGroupSession(
matrix.encryption!.keyManager.getInboundGroupSession(
requestRoom.id, validSessionId, validSenderKey) !=
null,
true);
@ -317,7 +318,7 @@ void main() {
// now test a few invalid scenarios
// request not found
matrix.encryption.keyManager.clearInboundGroupSessions();
matrix.encryption!.keyManager.clearInboundGroupSessions();
event = ToDeviceEvent(
sender: '@alice:example.com',
type: 'm.forwarded_room_key',
@ -328,22 +329,24 @@ void main() {
'session_key': sessionKey,
'sender_key': validSenderKey,
'forwarding_curve25519_key_chain': [],
'sender_claimed_ed25519_key':
'L+4+JCl8MD63dgo8z5Ta+9QAHXiANyOVSfgbHA5d3H8',
},
encryptedContent: {
'sender_key': 'L+4+JCl8MD63dgo8z5Ta+9QAHXiANyOVSfgbHA5d3H8',
});
await matrix.encryption.keyManager.handleToDeviceEvent(event);
await matrix.encryption!.keyManager.handleToDeviceEvent(event);
expect(
matrix.encryption.keyManager.getInboundGroupSession(
matrix.encryption!.keyManager.getInboundGroupSession(
requestRoom.id, validSessionId, validSenderKey) !=
null,
false);
// unknown device
await matrix.encryption.keyManager.request(
await matrix.encryption!.keyManager.request(
requestRoom, validSessionId, validSenderKey,
tryOnlineBackup: false);
matrix.encryption.keyManager.clearInboundGroupSessions();
matrix.encryption!.keyManager.clearInboundGroupSessions();
event = ToDeviceEvent(
sender: '@alice:example.com',
type: 'm.forwarded_room_key',
@ -354,22 +357,24 @@ void main() {
'session_key': sessionKey,
'sender_key': validSenderKey,
'forwarding_curve25519_key_chain': [],
'sender_claimed_ed25519_key':
'L+4+JCl8MD63dgo8z5Ta+9QAHXiANyOVSfgbHA5d3H8',
},
encryptedContent: {
'sender_key': 'invalid',
});
await matrix.encryption.keyManager.handleToDeviceEvent(event);
await matrix.encryption!.keyManager.handleToDeviceEvent(event);
expect(
matrix.encryption.keyManager.getInboundGroupSession(
matrix.encryption!.keyManager.getInboundGroupSession(
requestRoom.id, validSessionId, validSenderKey) !=
null,
false);
// no encrypted content
await matrix.encryption.keyManager.request(
await matrix.encryption!.keyManager.request(
requestRoom, validSessionId, validSenderKey,
tryOnlineBackup: false);
matrix.encryption.keyManager.clearInboundGroupSessions();
matrix.encryption!.keyManager.clearInboundGroupSessions();
event = ToDeviceEvent(
sender: '@alice:example.com',
type: 'm.forwarded_room_key',
@ -380,10 +385,12 @@ void main() {
'session_key': sessionKey,
'sender_key': validSenderKey,
'forwarding_curve25519_key_chain': [],
'sender_claimed_ed25519_key':
'L+4+JCl8MD63dgo8z5Ta+9QAHXiANyOVSfgbHA5d3H8',
});
await matrix.encryption.keyManager.handleToDeviceEvent(event);
await matrix.encryption!.keyManager.handleToDeviceEvent(event);
expect(
matrix.encryption.keyManager.getInboundGroupSession(
matrix.encryption!.keyManager.getInboundGroupSession(
requestRoom.id, validSessionId, validSenderKey) !=
null,
false);

View File

@ -1,4 +1,3 @@
// @dart=2.9
/*
* Famedly Matrix SDK
* Copyright (C) 2020 Famedly GmbH
@ -34,7 +33,7 @@ class MockSSSS extends SSSS {
bool requestedSecrets = false;
@override
Future<void> maybeRequestAll([List<DeviceKeys> devices]) async {
Future<void> maybeRequestAll([List<DeviceKeys>? devices]) async {
requestedSecrets = true;
final handle = open();
await handle.unlock(recoveryKey: ssssKey);
@ -56,7 +55,7 @@ EventUpdate getLastSentEvent(KeyVerification req) {
'sender': req.client.userID,
},
type: EventUpdateType.timeline,
roomID: req.room.id,
roomID: req.room!.id,
);
}
@ -70,8 +69,8 @@ void main() {
const otherPickledOlmAccount =
'VWhVApbkcilKAEGppsPDf9nNVjaK8/IxT3asSR0sYg0S5KgbfE8vXEPwoiKBX2cEvwX3OessOBOkk+ZE7TTbjlrh/KEd31p8Wo+47qj0AP+Ky+pabnhi+/rTBvZy+gfzTqUfCxZrkzfXI9Op4JnP6gYmy7dVX2lMYIIs9WCO1jcmIXiXum5jnfXu1WLfc7PZtO2hH+k9CDKosOFaXRBmsu8k/BGXPSoWqUpvu6WpEG9t5STk4FeAzA';
Client client1;
Client client2;
late Client client1;
late Client client2;
test('setupClient', () async {
try {
@ -117,24 +116,25 @@ void main() {
// because then we can easily intercept the payloads and inject in the other client
FakeMatrixApi.calledEndpoints.clear();
// make sure our master key is *not* verified to not triger SSSS for now
client1.userDeviceKeys[client1.userID].masterKey.setDirectVerified(false);
client1.userDeviceKeys[client1.userID]!.masterKey!
.setDirectVerified(false);
final req1 =
await client1.userDeviceKeys[client2.userID].startVerification();
await client1.userDeviceKeys[client2.userID]!.startVerification();
var evt = getLastSentEvent(req1);
expect(req1.state, KeyVerificationState.waitingAccept);
KeyVerification req2;
late KeyVerification req2;
final sub = client2.onKeyVerificationRequest.stream.listen((req) {
req2 = req;
});
await client2.encryption.keyVerificationManager.handleEventUpdate(evt);
await client2.encryption!.keyVerificationManager.handleEventUpdate(evt);
await Future.delayed(Duration(milliseconds: 10));
await sub.cancel();
expect(req2 != null, true);
expect(
client2.encryption.keyVerificationManager
.getRequest(req2.transactionId),
client2.encryption!.keyVerificationManager
.getRequest(req2.transactionId!),
req2);
// send ready
@ -145,27 +145,27 @@ void main() {
// send start
FakeMatrixApi.calledEndpoints.clear();
await client1.encryption.keyVerificationManager.handleEventUpdate(evt);
await client1.encryption!.keyVerificationManager.handleEventUpdate(evt);
evt = getLastSentEvent(req1);
// send accept
FakeMatrixApi.calledEndpoints.clear();
await client2.encryption.keyVerificationManager.handleEventUpdate(evt);
await client2.encryption!.keyVerificationManager.handleEventUpdate(evt);
evt = getLastSentEvent(req2);
// send key
FakeMatrixApi.calledEndpoints.clear();
await client1.encryption.keyVerificationManager.handleEventUpdate(evt);
await client1.encryption!.keyVerificationManager.handleEventUpdate(evt);
evt = getLastSentEvent(req1);
// send key
FakeMatrixApi.calledEndpoints.clear();
await client2.encryption.keyVerificationManager.handleEventUpdate(evt);
await client2.encryption!.keyVerificationManager.handleEventUpdate(evt);
evt = getLastSentEvent(req2);
// receive last key
FakeMatrixApi.calledEndpoints.clear();
await client1.encryption.keyVerificationManager.handleEventUpdate(evt);
await client1.encryption!.keyVerificationManager.handleEventUpdate(evt);
// compare emoji
expect(req1.state, KeyVerificationState.askSas);
@ -194,61 +194,64 @@ void main() {
FakeMatrixApi.calledEndpoints.clear();
await req1.acceptSas();
evt = getLastSentEvent(req1);
await client2.encryption.keyVerificationManager.handleEventUpdate(evt);
await client2.encryption!.keyVerificationManager.handleEventUpdate(evt);
expect(req1.state, KeyVerificationState.waitingSas);
// send mac
FakeMatrixApi.calledEndpoints.clear();
await req2.acceptSas();
evt = getLastSentEvent(req2);
await client1.encryption.keyVerificationManager.handleEventUpdate(evt);
await client1.encryption!.keyVerificationManager.handleEventUpdate(evt);
expect(req1.state, KeyVerificationState.done);
expect(req2.state, KeyVerificationState.done);
expect(
client1.userDeviceKeys[client2.userID].deviceKeys[client2.deviceID]
.directVerified,
client1.userDeviceKeys[client2.userID]?.deviceKeys[client2.deviceID]
?.directVerified,
true);
expect(
client2.userDeviceKeys[client1.userID].deviceKeys[client1.deviceID]
.directVerified,
client2.userDeviceKeys[client1.userID]?.deviceKeys[client1.deviceID]
?.directVerified,
true);
await client1.encryption.keyVerificationManager.cleanup();
await client2.encryption.keyVerificationManager.cleanup();
await client1.encryption!.keyVerificationManager.cleanup();
await client2.encryption!.keyVerificationManager.cleanup();
});
test('ask SSSS start', () async {
if (!olmEnabled) return;
client1.userDeviceKeys[client1.userID].masterKey.setDirectVerified(true);
await client1.encryption.ssss.clearCache();
client1.userDeviceKeys[client1.userID]!.masterKey!
.setDirectVerified(true);
await client1.encryption!.ssss.clearCache();
final req1 =
await client1.userDeviceKeys[client2.userID].startVerification();
await client1.userDeviceKeys[client2.userID]!.startVerification();
expect(req1.state, KeyVerificationState.askSSSS);
await req1.openSSSS(recoveryKey: ssssKey);
await Future.delayed(Duration(seconds: 1));
expect(req1.state, KeyVerificationState.waitingAccept);
await req1.cancel();
await client1.encryption.keyVerificationManager.cleanup();
await client1.encryption!.keyVerificationManager.cleanup();
});
test('ask SSSS end', () async {
if (!olmEnabled) return;
FakeMatrixApi.calledEndpoints.clear();
// make sure our master key is *not* verified to not triger SSSS for now
client1.userDeviceKeys[client1.userID].masterKey.setDirectVerified(false);
client1.userDeviceKeys[client1.userID]!.masterKey!
.setDirectVerified(false);
// the other one has to have their master key verified to trigger asking for ssss
client2.userDeviceKeys[client2.userID].masterKey.setDirectVerified(true);
client2.userDeviceKeys[client2.userID]!.masterKey!
.setDirectVerified(true);
final req1 =
await client1.userDeviceKeys[client2.userID].startVerification();
await client1.userDeviceKeys[client2.userID]!.startVerification();
var evt = getLastSentEvent(req1);
expect(req1.state, KeyVerificationState.waitingAccept);
KeyVerification req2;
late KeyVerification req2;
final sub = client2.onKeyVerificationRequest.stream.listen((req) {
req2 = req;
});
await client2.encryption.keyVerificationManager.handleEventUpdate(evt);
await client2.encryption!.keyVerificationManager.handleEventUpdate(evt);
await Future.delayed(Duration(milliseconds: 10));
await sub.cancel();
expect(req2 != null, true);
@ -261,27 +264,27 @@ void main() {
// send start
FakeMatrixApi.calledEndpoints.clear();
await client1.encryption.keyVerificationManager.handleEventUpdate(evt);
await client1.encryption!.keyVerificationManager.handleEventUpdate(evt);
evt = getLastSentEvent(req1);
// send accept
FakeMatrixApi.calledEndpoints.clear();
await client2.encryption.keyVerificationManager.handleEventUpdate(evt);
await client2.encryption!.keyVerificationManager.handleEventUpdate(evt);
evt = getLastSentEvent(req2);
// send key
FakeMatrixApi.calledEndpoints.clear();
await client1.encryption.keyVerificationManager.handleEventUpdate(evt);
await client1.encryption!.keyVerificationManager.handleEventUpdate(evt);
evt = getLastSentEvent(req1);
// send key
FakeMatrixApi.calledEndpoints.clear();
await client2.encryption.keyVerificationManager.handleEventUpdate(evt);
await client2.encryption!.keyVerificationManager.handleEventUpdate(evt);
evt = getLastSentEvent(req2);
// receive last key
FakeMatrixApi.calledEndpoints.clear();
await client1.encryption.keyVerificationManager.handleEventUpdate(evt);
await client1.encryption!.keyVerificationManager.handleEventUpdate(evt);
// compare emoji
expect(req1.state, KeyVerificationState.askSas);
@ -301,21 +304,22 @@ void main() {
}
// alright, they match
client1.userDeviceKeys[client1.userID].masterKey.setDirectVerified(true);
await client1.encryption.ssss.clearCache();
client1.userDeviceKeys[client1.userID]!.masterKey!
.setDirectVerified(true);
await client1.encryption!.ssss.clearCache();
// send mac
FakeMatrixApi.calledEndpoints.clear();
await req1.acceptSas();
evt = getLastSentEvent(req1);
await client2.encryption.keyVerificationManager.handleEventUpdate(evt);
await client2.encryption!.keyVerificationManager.handleEventUpdate(evt);
expect(req1.state, KeyVerificationState.waitingSas);
// send mac
FakeMatrixApi.calledEndpoints.clear();
await req2.acceptSas();
evt = getLastSentEvent(req2);
await client1.encryption.keyVerificationManager.handleEventUpdate(evt);
await client1.encryption!.keyVerificationManager.handleEventUpdate(evt);
expect(req1.state, KeyVerificationState.askSSSS);
expect(req2.state, KeyVerificationState.done);
@ -324,63 +328,65 @@ void main() {
await Future.delayed(Duration(milliseconds: 10));
expect(req1.state, KeyVerificationState.done);
client1.encryption.ssss = MockSSSS(client1.encryption);
(client1.encryption.ssss as MockSSSS).requestedSecrets = false;
await client1.encryption.ssss.clearCache();
client1.encryption!.ssss = MockSSSS(client1.encryption!);
(client1.encryption!.ssss as MockSSSS).requestedSecrets = false;
await client1.encryption!.ssss.clearCache();
await req1.maybeRequestSSSSSecrets();
await Future.delayed(Duration(milliseconds: 10));
expect((client1.encryption.ssss as MockSSSS).requestedSecrets, true);
expect((client1.encryption!.ssss as MockSSSS).requestedSecrets, true);
// delay for 12 seconds to be sure no other tests clear the ssss cache
await Future.delayed(Duration(seconds: 12));
await client1.encryption.keyVerificationManager.cleanup();
await client2.encryption.keyVerificationManager.cleanup();
await client1.encryption!.keyVerificationManager.cleanup();
await client2.encryption!.keyVerificationManager.cleanup();
});
test('reject verification', () async {
if (!olmEnabled) return;
FakeMatrixApi.calledEndpoints.clear();
// make sure our master key is *not* verified to not triger SSSS for now
client1.userDeviceKeys[client1.userID].masterKey.setDirectVerified(false);
client1.userDeviceKeys[client1.userID]!.masterKey!
.setDirectVerified(false);
final req1 =
await client1.userDeviceKeys[client2.userID].startVerification();
await client1.userDeviceKeys[client2.userID]!.startVerification();
var evt = getLastSentEvent(req1);
expect(req1.state, KeyVerificationState.waitingAccept);
KeyVerification req2;
late KeyVerification req2;
final sub = client2.onKeyVerificationRequest.stream.listen((req) {
req2 = req;
});
await client2.encryption.keyVerificationManager.handleEventUpdate(evt);
await client2.encryption!.keyVerificationManager.handleEventUpdate(evt);
await Future.delayed(Duration(milliseconds: 10));
await sub.cancel();
FakeMatrixApi.calledEndpoints.clear();
await req2.rejectVerification();
evt = getLastSentEvent(req2);
await client1.encryption.keyVerificationManager.handleEventUpdate(evt);
await client1.encryption!.keyVerificationManager.handleEventUpdate(evt);
expect(req1.state, KeyVerificationState.error);
expect(req2.state, KeyVerificationState.error);
await client1.encryption.keyVerificationManager.cleanup();
await client2.encryption.keyVerificationManager.cleanup();
await client1.encryption!.keyVerificationManager.cleanup();
await client2.encryption!.keyVerificationManager.cleanup();
});
test('reject sas', () async {
if (!olmEnabled) return;
FakeMatrixApi.calledEndpoints.clear();
// make sure our master key is *not* verified to not triger SSSS for now
client1.userDeviceKeys[client1.userID].masterKey.setDirectVerified(false);
client1.userDeviceKeys[client1.userID]!.masterKey!
.setDirectVerified(false);
final req1 =
await client1.userDeviceKeys[client2.userID].startVerification();
await client1.userDeviceKeys[client2.userID]!.startVerification();
var evt = getLastSentEvent(req1);
expect(req1.state, KeyVerificationState.waitingAccept);
KeyVerification req2;
late KeyVerification req2;
final sub = client2.onKeyVerificationRequest.stream.listen((req) {
req2 = req;
});
await client2.encryption.keyVerificationManager.handleEventUpdate(evt);
await client2.encryption!.keyVerificationManager.handleEventUpdate(evt);
await Future.delayed(Duration(milliseconds: 10));
await sub.cancel();
expect(req2 != null, true);
@ -393,60 +399,61 @@ void main() {
// send start
FakeMatrixApi.calledEndpoints.clear();
await client1.encryption.keyVerificationManager.handleEventUpdate(evt);
await client1.encryption!.keyVerificationManager.handleEventUpdate(evt);
evt = getLastSentEvent(req1);
// send accept
FakeMatrixApi.calledEndpoints.clear();
await client2.encryption.keyVerificationManager.handleEventUpdate(evt);
await client2.encryption!.keyVerificationManager.handleEventUpdate(evt);
evt = getLastSentEvent(req2);
// send key
FakeMatrixApi.calledEndpoints.clear();
await client1.encryption.keyVerificationManager.handleEventUpdate(evt);
await client1.encryption!.keyVerificationManager.handleEventUpdate(evt);
evt = getLastSentEvent(req1);
// send key
FakeMatrixApi.calledEndpoints.clear();
await client2.encryption.keyVerificationManager.handleEventUpdate(evt);
await client2.encryption!.keyVerificationManager.handleEventUpdate(evt);
evt = getLastSentEvent(req2);
// receive last key
FakeMatrixApi.calledEndpoints.clear();
await client1.encryption.keyVerificationManager.handleEventUpdate(evt);
await client1.encryption!.keyVerificationManager.handleEventUpdate(evt);
await req1.acceptSas();
FakeMatrixApi.calledEndpoints.clear();
await req2.rejectSas();
evt = getLastSentEvent(req2);
await client1.encryption.keyVerificationManager.handleEventUpdate(evt);
await client1.encryption!.keyVerificationManager.handleEventUpdate(evt);
expect(req1.state, KeyVerificationState.error);
expect(req2.state, KeyVerificationState.error);
await client1.encryption.keyVerificationManager.cleanup();
await client2.encryption.keyVerificationManager.cleanup();
await client1.encryption!.keyVerificationManager.cleanup();
await client2.encryption!.keyVerificationManager.cleanup();
});
test('other device accepted', () async {
if (!olmEnabled) return;
FakeMatrixApi.calledEndpoints.clear();
// make sure our master key is *not* verified to not triger SSSS for now
client1.userDeviceKeys[client1.userID].masterKey.setDirectVerified(false);
client1.userDeviceKeys[client1.userID]!.masterKey!
.setDirectVerified(false);
final req1 =
await client1.userDeviceKeys[client2.userID].startVerification();
await client1.userDeviceKeys[client2.userID]!.startVerification();
final evt = getLastSentEvent(req1);
expect(req1.state, KeyVerificationState.waitingAccept);
KeyVerification req2;
late KeyVerification req2;
final sub = client2.onKeyVerificationRequest.stream.listen((req) {
req2 = req;
});
await client2.encryption.keyVerificationManager.handleEventUpdate(evt);
await client2.encryption!.keyVerificationManager.handleEventUpdate(evt);
await Future.delayed(Duration(milliseconds: 10));
await sub.cancel();
expect(req2 != null, true);
await client2.encryption.keyVerificationManager
await client2.encryption!.keyVerificationManager
.handleEventUpdate(EventUpdate(
content: {
'event_id': req2.transactionId,
@ -463,13 +470,13 @@ void main() {
'sender': client2.userID,
},
type: EventUpdateType.timeline,
roomID: req2.room.id,
roomID: req2.room!.id,
));
expect(req2.state, KeyVerificationState.error);
await req2.cancel();
await client1.encryption.keyVerificationManager.cleanup();
await client2.encryption.keyVerificationManager.cleanup();
await client1.encryption!.keyVerificationManager.cleanup();
await client2.encryption!.keyVerificationManager.cleanup();
});
test('dispose client', () async {

View File

@ -1,4 +1,3 @@
// @dart=2.9
/*
* Famedly Matrix SDK
* Copyright (C) 2020, 2021 Famedly GmbH
@ -32,7 +31,7 @@ void main() {
Logs().level = Level.error;
var olmEnabled = true;
Client client;
late Client client;
test('setupClient', () async {
try {
@ -53,37 +52,37 @@ void main() {
final payload = <String, dynamic>{
'fox': 'floof',
};
final signedPayload = client.encryption.olmManager.signJson(payload);
final signedPayload = client.encryption!.olmManager.signJson(payload);
expect(
signedPayload.checkJsonSignature(
client.fingerprintKey, client.userID, client.deviceID),
client.fingerprintKey, client.userID!, client.deviceID!),
true);
});
test('uploadKeys', () async {
if (!olmEnabled) return;
FakeMatrixApi.calledEndpoints.clear();
final res =
await client.encryption.olmManager.uploadKeys(uploadDeviceKeys: true);
final res = await client.encryption!.olmManager
.uploadKeys(uploadDeviceKeys: true);
expect(res, true);
var sent = json.decode(
FakeMatrixApi.calledEndpoints['/client/r0/keys/upload'].first);
FakeMatrixApi.calledEndpoints['/client/r0/keys/upload']!.first);
expect(sent['device_keys'] != null, true);
expect(sent['one_time_keys'] != null, true);
expect(sent['one_time_keys'].keys.length, 66);
expect(sent['fallback_keys'] != null, true);
expect(sent['fallback_keys'].keys.length, 1);
FakeMatrixApi.calledEndpoints.clear();
await client.encryption.olmManager.uploadKeys();
await client.encryption!.olmManager.uploadKeys();
sent = json.decode(
FakeMatrixApi.calledEndpoints['/client/r0/keys/upload'].first);
FakeMatrixApi.calledEndpoints['/client/r0/keys/upload']!.first);
expect(sent['device_keys'] != null, false);
expect(sent['fallback_keys'].keys.length, 1);
FakeMatrixApi.calledEndpoints.clear();
await client.encryption.olmManager
await client.encryption!.olmManager
.uploadKeys(oldKeyCount: 20, unusedFallbackKey: true);
sent = json.decode(
FakeMatrixApi.calledEndpoints['/client/r0/keys/upload'].first);
FakeMatrixApi.calledEndpoints['/client/r0/keys/upload']!.first);
expect(sent['one_time_keys'].keys.length, 46);
expect(sent['fallback_keys'].keys.length, 0);
});
@ -91,7 +90,7 @@ void main() {
test('handleDeviceOneTimeKeysCount', () async {
if (!olmEnabled) return;
FakeMatrixApi.calledEndpoints.clear();
client.encryption.olmManager
client.encryption!.olmManager
.handleDeviceOneTimeKeysCount({'signed_curve25519': 20}, null);
await Future.delayed(Duration(milliseconds: 50));
expect(
@ -99,7 +98,7 @@ void main() {
true);
FakeMatrixApi.calledEndpoints.clear();
client.encryption.olmManager
client.encryption!.olmManager
.handleDeviceOneTimeKeysCount({'signed_curve25519': 70}, null);
await Future.delayed(Duration(milliseconds: 50));
expect(
@ -107,7 +106,7 @@ void main() {
false);
FakeMatrixApi.calledEndpoints.clear();
client.encryption.olmManager.handleDeviceOneTimeKeysCount(null, []);
client.encryption!.olmManager.handleDeviceOneTimeKeysCount(null, []);
await Future.delayed(Duration(milliseconds: 50));
expect(
FakeMatrixApi.calledEndpoints.containsKey('/client/r0/keys/upload'),
@ -115,7 +114,7 @@ void main() {
// this will upload keys because we assume the key count is 0, if the server doesn't send one
FakeMatrixApi.calledEndpoints.clear();
client.encryption.olmManager
client.encryption!.olmManager
.handleDeviceOneTimeKeysCount(null, ['signed_curve25519']);
await Future.delayed(Duration(milliseconds: 50));
expect(
@ -125,30 +124,31 @@ void main() {
test('restoreOlmSession', () async {
if (!olmEnabled) return;
client.encryption.olmManager.olmSessions.clear();
await client.encryption.olmManager
.restoreOlmSession(client.userID, client.identityKey);
expect(client.encryption.olmManager.olmSessions.length, 1);
client.encryption!.olmManager.olmSessions.clear();
await client.encryption!.olmManager
.restoreOlmSession(client.userID!, client.identityKey);
expect(client.encryption!.olmManager.olmSessions.length, 1);
client.encryption.olmManager.olmSessions.clear();
await client.encryption.olmManager
.restoreOlmSession(client.userID, 'invalid');
expect(client.encryption.olmManager.olmSessions.length, 0);
client.encryption!.olmManager.olmSessions.clear();
await client.encryption!.olmManager
.restoreOlmSession(client.userID!, 'invalid');
expect(client.encryption!.olmManager.olmSessions.length, 0);
client.encryption.olmManager.olmSessions.clear();
await client.encryption.olmManager
client.encryption!.olmManager.olmSessions.clear();
await client.encryption!.olmManager
.restoreOlmSession('invalid', client.identityKey);
expect(client.encryption.olmManager.olmSessions.length, 0);
expect(client.encryption!.olmManager.olmSessions.length, 0);
});
test('startOutgoingOlmSessions', () async {
if (!olmEnabled) return;
// start an olm session.....with ourself!
client.encryption.olmManager.olmSessions.clear();
await client.encryption.olmManager.startOutgoingOlmSessions(
[client.userDeviceKeys[client.userID].deviceKeys[client.deviceID]]);
client.encryption!.olmManager.olmSessions.clear();
await client.encryption!.olmManager.startOutgoingOlmSessions([
client.userDeviceKeys[client.userID!]!.deviceKeys[client.deviceID]!
]);
expect(
client.encryption.olmManager.olmSessions
client.encryption!.olmManager.olmSessions
.containsKey(client.identityKey),
true);
});
@ -159,7 +159,7 @@ void main() {
final deviceId = 'JLAFKJWSCS';
final senderKey = 'L+4+JCl8MD63dgo8z5Ta+9QAHXiANyOVSfgbHA5d3H8';
FakeMatrixApi.calledEndpoints.clear();
await client.database.setLastSentMessageUserDeviceKey(
await client.database!.setLastSentMessageUserDeviceKey(
json.encode({
'type': 'm.foxies',
'content': {
@ -176,7 +176,7 @@ void main() {
'sender_key': senderKey,
},
);
await client.encryption.olmManager.handleToDeviceEvent(event);
await client.encryption!.olmManager.handleToDeviceEvent(event);
expect(
FakeMatrixApi.calledEndpoints.keys.any(
(k) => k.startsWith('/client/r0/sendToDevice/m.room.encrypted')),
@ -186,7 +186,7 @@ void main() {
// not encrypted
FakeMatrixApi.calledEndpoints.clear();
await client.database.setLastSentMessageUserDeviceKey(
await client.database!.setLastSentMessageUserDeviceKey(
json.encode({
'type': 'm.foxies',
'content': {
@ -201,7 +201,7 @@ void main() {
content: {},
encryptedContent: null,
);
await client.encryption.olmManager.handleToDeviceEvent(event);
await client.encryption!.olmManager.handleToDeviceEvent(event);
expect(
FakeMatrixApi.calledEndpoints.keys.any(
(k) => k.startsWith('/client/r0/sendToDevice/m.room.encrypted')),
@ -209,7 +209,7 @@ void main() {
// device not found
FakeMatrixApi.calledEndpoints.clear();
await client.database.setLastSentMessageUserDeviceKey(
await client.database!.setLastSentMessageUserDeviceKey(
json.encode({
'type': 'm.foxies',
'content': {
@ -226,7 +226,7 @@ void main() {
'sender_key': 'invalid',
},
);
await client.encryption.olmManager.handleToDeviceEvent(event);
await client.encryption!.olmManager.handleToDeviceEvent(event);
expect(
FakeMatrixApi.calledEndpoints.keys.any(
(k) => k.startsWith('/client/r0/sendToDevice/m.room.encrypted')),
@ -234,7 +234,7 @@ void main() {
// don't replay if the last event is m.dummy itself
FakeMatrixApi.calledEndpoints.clear();
await client.database.setLastSentMessageUserDeviceKey(
await client.database!.setLastSentMessageUserDeviceKey(
json.encode({
'type': 'm.dummy',
'content': {},
@ -249,7 +249,7 @@ void main() {
'sender_key': senderKey,
},
);
await client.encryption.olmManager.handleToDeviceEvent(event);
await client.encryption!.olmManager.handleToDeviceEvent(event);
expect(
FakeMatrixApi.calledEndpoints.keys.any(
(k) => k.startsWith('/client/r0/sendToDevice/m.room.encrypted')),

View File

@ -1,4 +1,3 @@
// @dart=2.9
/*
* Famedly Matrix SDK
* Copyright (C) 2020 Famedly GmbH
@ -32,7 +31,7 @@ void main() {
Logs().level = Level.error;
var olmEnabled = true;
Client client;
late Client client;
final roomId = '!726s6s6q:example.com';
final sessionId = 'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU';
@ -54,21 +53,21 @@ void main() {
test('basic things', () async {
if (!olmEnabled) return;
expect(client.encryption.keyManager.enabled, true);
expect(await client.encryption.keyManager.isCached(), false);
final handle = client.encryption.ssss.open();
expect(client.encryption!.keyManager.enabled, true);
expect(await client.encryption!.keyManager.isCached(), false);
final handle = client.encryption!.ssss.open();
await handle.unlock(recoveryKey: ssssKey);
await handle.maybeCacheAll();
expect(await client.encryption.keyManager.isCached(), true);
expect(await client.encryption!.keyManager.isCached(), true);
});
test('load key', () async {
if (!olmEnabled) return;
client.encryption.keyManager.clearInboundGroupSessions();
await client.encryption.keyManager
.request(client.getRoomById(roomId), sessionId, senderKey);
client.encryption!.keyManager.clearInboundGroupSessions();
await client.encryption!.keyManager
.request(client.getRoomById(roomId)!, sessionId, senderKey);
expect(
client.encryption.keyManager
client.encryption!.keyManager
.getInboundGroupSession(roomId, sessionId, senderKey) !=
null,
true);
@ -94,25 +93,25 @@ void main() {
'sender_claimed_ed25519_key': client.fingerprintKey,
};
FakeMatrixApi.calledEndpoints.clear();
client.encryption.keyManager.setInboundGroupSession(
client.encryption!.keyManager.setInboundGroupSession(
roomId, sessionId, senderKey, sessionPayload,
forwarded: true);
await Future.delayed(Duration(milliseconds: 500));
var dbSessions = await client.database.getInboundGroupSessionsToUpload();
var dbSessions = await client.database!.getInboundGroupSessionsToUpload();
expect(dbSessions.isNotEmpty, true);
await client.encryption.keyManager.backgroundTasks();
await client.encryption!.keyManager.backgroundTasks();
final payload = FakeMatrixApi
.calledEndpoints['/client/unstable/room_keys/keys?version=5'].first;
dbSessions = await client.database.getInboundGroupSessionsToUpload();
.calledEndpoints['/client/unstable/room_keys/keys?version=5']!.first;
dbSessions = await client.database!.getInboundGroupSessionsToUpload();
expect(dbSessions.isEmpty, true);
final onlineKeys = RoomKeys.fromJson(json.decode(payload));
client.encryption.keyManager.clearInboundGroupSessions();
var ret = client.encryption.keyManager
client.encryption!.keyManager.clearInboundGroupSessions();
var ret = client.encryption!.keyManager
.getInboundGroupSession(roomId, sessionId, senderKey);
expect(ret, null);
await client.encryption.keyManager.loadFromResponse(onlineKeys);
ret = client.encryption.keyManager
await client.encryption!.keyManager.loadFromResponse(onlineKeys);
ret = client.encryption!.keyManager
.getInboundGroupSession(roomId, sessionId, senderKey);
expect(ret != null, true);
});

View File

@ -1,4 +1,3 @@
// @dart=2.9
/*
* Famedly Matrix SDK
* Copyright (C) 2020 Famedly GmbH
@ -42,7 +41,7 @@ class MockSSSS extends SSSS {
bool requestedSecrets = false;
@override
Future<void> maybeRequestAll([List<DeviceKeys> devices]) async {
Future<void> maybeRequestAll([List<DeviceKeys>? devices]) async {
requestedSecrets = true;
final handle = open();
await handle.unlock(recoveryKey: ssssKey);
@ -55,7 +54,7 @@ void main() {
Logs().level = Level.error;
var olmEnabled = true;
Client client;
late Client client;
test('setupClient', () async {
try {
@ -73,7 +72,7 @@ void main() {
test('basic things', () async {
if (!olmEnabled) return;
expect(client.encryption.ssss.defaultKeyId,
expect(client.encryption!.ssss.defaultKeyId,
'0FajDWYaM6wQ4O60OZnLvwZfsBNu4Bu3');
});
@ -88,7 +87,7 @@ void main() {
test('store', () async {
if (!olmEnabled) return;
final handle = client.encryption.ssss.open();
final handle = client.encryption!.ssss.open();
var failed = false;
try {
await handle.unlock(passphrase: 'invalid');
@ -114,7 +113,7 @@ void main() {
// account_data for this test
final content = FakeMatrixApi
.calledEndpoints[
'/client/r0/user/%40test%3AfakeServer.notExisting/account_data/best%20animal']
'/client/r0/user/%40test%3AfakeServer.notExisting/account_data/best%20animal']!
.first;
client.accountData['best animal'] = BasicEvent.fromJson({
'type': 'best animal',
@ -130,77 +129,78 @@ void main() {
final decoded = SSSS.decodeRecoveryKey(encoded);
expect(key, decoded);
final handle = client.encryption.ssss.open();
final handle = client.encryption!.ssss.open();
await handle.unlock(recoveryKey: ssssKey);
expect(handle.recoveryKey, ssssKey);
});
test('cache', () async {
if (!olmEnabled) return;
await client.encryption.ssss.clearCache();
await client.encryption!.ssss.clearCache();
final handle =
client.encryption.ssss.open(EventTypes.CrossSigningSelfSigning);
client.encryption!.ssss.open(EventTypes.CrossSigningSelfSigning);
await handle.unlock(recoveryKey: ssssKey, postUnlock: false);
expect(
(await client.encryption.ssss
(await client.encryption!.ssss
.getCached(EventTypes.CrossSigningSelfSigning)) !=
null,
false);
expect(
(await client.encryption.ssss
(await client.encryption!.ssss
.getCached(EventTypes.CrossSigningUserSigning)) !=
null,
false);
await handle.getStored(EventTypes.CrossSigningSelfSigning);
expect(
(await client.encryption.ssss
(await client.encryption!.ssss
.getCached(EventTypes.CrossSigningSelfSigning)) !=
null,
true);
await handle.maybeCacheAll();
expect(
(await client.encryption.ssss
(await client.encryption!.ssss
.getCached(EventTypes.CrossSigningUserSigning)) !=
null,
true);
expect(
(await client.encryption.ssss.getCached(EventTypes.MegolmBackup)) !=
(await client.encryption!.ssss.getCached(EventTypes.MegolmBackup)) !=
null,
true);
});
test('postUnlock', () async {
if (!olmEnabled) return;
await client.encryption.ssss.clearCache();
client.userDeviceKeys[client.userID].masterKey.setDirectVerified(false);
await client.encryption!.ssss.clearCache();
client.userDeviceKeys[client.userID!]!.masterKey!
.setDirectVerified(false);
final handle =
client.encryption.ssss.open(EventTypes.CrossSigningSelfSigning);
client.encryption!.ssss.open(EventTypes.CrossSigningSelfSigning);
await handle.unlock(recoveryKey: ssssKey);
expect(
(await client.encryption.ssss
(await client.encryption!.ssss
.getCached(EventTypes.CrossSigningSelfSigning)) !=
null,
true);
expect(
(await client.encryption.ssss
(await client.encryption!.ssss
.getCached(EventTypes.CrossSigningUserSigning)) !=
null,
true);
expect(
(await client.encryption.ssss.getCached(EventTypes.MegolmBackup)) !=
(await client.encryption!.ssss.getCached(EventTypes.MegolmBackup)) !=
null,
true);
expect(
client.userDeviceKeys[client.userID].masterKey.directVerified, true);
expect(client.userDeviceKeys[client.userID!]!.masterKey!.directVerified,
true);
});
test('make share requests', () async {
if (!olmEnabled) return;
final key =
client.userDeviceKeys[client.userID].deviceKeys['OTHERDEVICE'];
client.userDeviceKeys[client.userID!]!.deviceKeys['OTHERDEVICE']!;
key.setDirectVerified(true);
FakeMatrixApi.calledEndpoints.clear();
await client.encryption.ssss.request('some.type', [key]);
await client.encryption!.ssss.request('some.type', [key]);
expect(
FakeMatrixApi.calledEndpoints.keys.any(
(k) => k.startsWith('/client/r0/sendToDevice/m.room.encrypted')),
@ -210,7 +210,7 @@ void main() {
test('answer to share requests', () async {
if (!olmEnabled) return;
var event = ToDeviceEvent(
sender: client.userID,
sender: client.userID!,
type: 'm.secret.request',
content: {
'action': 'request',
@ -220,7 +220,7 @@ void main() {
},
);
FakeMatrixApi.calledEndpoints.clear();
await client.encryption.ssss.handleToDeviceEvent(event);
await client.encryption!.ssss.handleToDeviceEvent(event);
expect(
FakeMatrixApi.calledEndpoints.keys.any(
(k) => k.startsWith('/client/r0/sendToDevice/m.room.encrypted')),
@ -240,7 +240,7 @@ void main() {
},
);
FakeMatrixApi.calledEndpoints.clear();
await client.encryption.ssss.handleToDeviceEvent(event);
await client.encryption!.ssss.handleToDeviceEvent(event);
expect(
FakeMatrixApi.calledEndpoints.keys.any(
(k) => k.startsWith('/client/r0/sendToDevice/m.room.encrypted')),
@ -248,7 +248,7 @@ void main() {
// secret not cached
event = ToDeviceEvent(
sender: client.userID,
sender: client.userID!,
type: 'm.secret.request',
content: {
'action': 'request',
@ -258,7 +258,7 @@ void main() {
},
);
FakeMatrixApi.calledEndpoints.clear();
await client.encryption.ssss.handleToDeviceEvent(event);
await client.encryption!.ssss.handleToDeviceEvent(event);
expect(
FakeMatrixApi.calledEndpoints.keys.any(
(k) => k.startsWith('/client/r0/sendToDevice/m.room.encrypted')),
@ -266,7 +266,7 @@ void main() {
// is a cancelation
event = ToDeviceEvent(
sender: client.userID,
sender: client.userID!,
type: 'm.secret.request',
content: {
'action': 'request_cancellation',
@ -276,7 +276,7 @@ void main() {
},
);
FakeMatrixApi.calledEndpoints.clear();
await client.encryption.ssss.handleToDeviceEvent(event);
await client.encryption!.ssss.handleToDeviceEvent(event);
expect(
FakeMatrixApi.calledEndpoints.keys.any(
(k) => k.startsWith('/client/r0/sendToDevice/m.room.encrypted')),
@ -284,11 +284,12 @@ void main() {
// device not verified
final key =
client.userDeviceKeys[client.userID].deviceKeys['OTHERDEVICE'];
client.userDeviceKeys[client.userID!]!.deviceKeys['OTHERDEVICE']!;
key.setDirectVerified(false);
client.userDeviceKeys[client.userID].masterKey.setDirectVerified(false);
client.userDeviceKeys[client.userID!]!.masterKey!
.setDirectVerified(false);
event = ToDeviceEvent(
sender: client.userID,
sender: client.userID!,
type: 'm.secret.request',
content: {
'action': 'request',
@ -298,7 +299,7 @@ void main() {
},
);
FakeMatrixApi.calledEndpoints.clear();
await client.encryption.ssss.handleToDeviceEvent(event);
await client.encryption!.ssss.handleToDeviceEvent(event);
expect(
FakeMatrixApi.calledEndpoints.keys.any(
(k) => k.startsWith('/client/r0/sendToDevice/m.room.encrypted')),
@ -309,28 +310,28 @@ void main() {
test('receive share requests', () async {
if (!olmEnabled) return;
final key =
client.userDeviceKeys[client.userID].deviceKeys['OTHERDEVICE'];
client.userDeviceKeys[client.userID!]!.deviceKeys['OTHERDEVICE']!;
key.setDirectVerified(true);
final handle =
client.encryption.ssss.open(EventTypes.CrossSigningSelfSigning);
client.encryption!.ssss.open(EventTypes.CrossSigningSelfSigning);
await handle.unlock(recoveryKey: ssssKey);
await client.encryption.ssss.clearCache();
client.encryption.ssss.pendingShareRequests.clear();
await client.encryption.ssss.request('best animal', [key]);
await client.encryption!.ssss.clearCache();
client.encryption!.ssss.pendingShareRequests.clear();
await client.encryption!.ssss.request('best animal', [key]);
var event = ToDeviceEvent(
sender: client.userID,
sender: client.userID!,
type: 'm.secret.send',
content: {
'request_id': client.encryption.ssss.pendingShareRequests.keys.first,
'request_id': client.encryption!.ssss.pendingShareRequests.keys.first,
'secret': 'foxies!',
},
encryptedContent: {
'sender_key': key.curve25519Key,
},
);
await client.encryption.ssss.handleToDeviceEvent(event);
expect(await client.encryption.ssss.getCached('best animal'), 'foxies!');
await client.encryption!.ssss.handleToDeviceEvent(event);
expect(await client.encryption!.ssss.getCached('best animal'), 'foxies!');
// test the different validators
for (final type in [
@ -339,48 +340,48 @@ void main() {
EventTypes.MegolmBackup
]) {
final secret = await handle.getStored(type);
await client.encryption.ssss.clearCache();
client.encryption.ssss.pendingShareRequests.clear();
await client.encryption.ssss.request(type, [key]);
await client.encryption!.ssss.clearCache();
client.encryption!.ssss.pendingShareRequests.clear();
await client.encryption!.ssss.request(type, [key]);
event = ToDeviceEvent(
sender: client.userID,
sender: client.userID!,
type: 'm.secret.send',
content: {
'request_id':
client.encryption.ssss.pendingShareRequests.keys.first,
client.encryption!.ssss.pendingShareRequests.keys.first,
'secret': secret,
},
encryptedContent: {
'sender_key': key.curve25519Key,
},
);
await client.encryption.ssss.handleToDeviceEvent(event);
expect(await client.encryption.ssss.getCached(type), secret);
await client.encryption!.ssss.handleToDeviceEvent(event);
expect(await client.encryption!.ssss.getCached(type), secret);
}
// test different fail scenarios
// not encrypted
await client.encryption.ssss.clearCache();
client.encryption.ssss.pendingShareRequests.clear();
await client.encryption.ssss.request('best animal', [key]);
await client.encryption!.ssss.clearCache();
client.encryption!.ssss.pendingShareRequests.clear();
await client.encryption!.ssss.request('best animal', [key]);
event = ToDeviceEvent(
sender: client.userID,
sender: client.userID!,
type: 'm.secret.send',
content: {
'request_id': client.encryption.ssss.pendingShareRequests.keys.first,
'request_id': client.encryption!.ssss.pendingShareRequests.keys.first,
'secret': 'foxies!',
},
);
await client.encryption.ssss.handleToDeviceEvent(event);
expect(await client.encryption.ssss.getCached('best animal'), null);
await client.encryption!.ssss.handleToDeviceEvent(event);
expect(await client.encryption!.ssss.getCached('best animal'), null);
// unknown request id
await client.encryption.ssss.clearCache();
client.encryption.ssss.pendingShareRequests.clear();
await client.encryption.ssss.request('best animal', [key]);
await client.encryption!.ssss.clearCache();
client.encryption!.ssss.pendingShareRequests.clear();
await client.encryption!.ssss.request('best animal', [key]);
event = ToDeviceEvent(
sender: client.userID,
sender: client.userID!,
type: 'm.secret.send',
content: {
'request_id': 'invalid',
@ -390,103 +391,103 @@ void main() {
'sender_key': key.curve25519Key,
},
);
await client.encryption.ssss.handleToDeviceEvent(event);
expect(await client.encryption.ssss.getCached('best animal'), null);
await client.encryption!.ssss.handleToDeviceEvent(event);
expect(await client.encryption!.ssss.getCached('best animal'), null);
// not from a device we sent the request to
await client.encryption.ssss.clearCache();
client.encryption.ssss.pendingShareRequests.clear();
await client.encryption.ssss.request('best animal', [key]);
await client.encryption!.ssss.clearCache();
client.encryption!.ssss.pendingShareRequests.clear();
await client.encryption!.ssss.request('best animal', [key]);
event = ToDeviceEvent(
sender: client.userID,
sender: client.userID!,
type: 'm.secret.send',
content: {
'request_id': client.encryption.ssss.pendingShareRequests.keys.first,
'request_id': client.encryption!.ssss.pendingShareRequests.keys.first,
'secret': 'foxies!',
},
encryptedContent: {
'sender_key': 'invalid',
},
);
await client.encryption.ssss.handleToDeviceEvent(event);
expect(await client.encryption.ssss.getCached('best animal'), null);
await client.encryption!.ssss.handleToDeviceEvent(event);
expect(await client.encryption!.ssss.getCached('best animal'), null);
// secret not a string
await client.encryption.ssss.clearCache();
client.encryption.ssss.pendingShareRequests.clear();
await client.encryption.ssss.request('best animal', [key]);
await client.encryption!.ssss.clearCache();
client.encryption!.ssss.pendingShareRequests.clear();
await client.encryption!.ssss.request('best animal', [key]);
event = ToDeviceEvent(
sender: client.userID,
sender: client.userID!,
type: 'm.secret.send',
content: {
'request_id': client.encryption.ssss.pendingShareRequests.keys.first,
'request_id': client.encryption!.ssss.pendingShareRequests.keys.first,
'secret': 42,
},
encryptedContent: {
'sender_key': key.curve25519Key,
},
);
await client.encryption.ssss.handleToDeviceEvent(event);
expect(await client.encryption.ssss.getCached('best animal'), null);
await client.encryption!.ssss.handleToDeviceEvent(event);
expect(await client.encryption!.ssss.getCached('best animal'), null);
// validator doesn't check out
await client.encryption.ssss.clearCache();
client.encryption.ssss.pendingShareRequests.clear();
await client.encryption.ssss.request(EventTypes.MegolmBackup, [key]);
await client.encryption!.ssss.clearCache();
client.encryption!.ssss.pendingShareRequests.clear();
await client.encryption!.ssss.request(EventTypes.MegolmBackup, [key]);
event = ToDeviceEvent(
sender: client.userID,
sender: client.userID!,
type: 'm.secret.send',
content: {
'request_id': client.encryption.ssss.pendingShareRequests.keys.first,
'request_id': client.encryption!.ssss.pendingShareRequests.keys.first,
'secret': 'foxies!',
},
encryptedContent: {
'sender_key': key.curve25519Key,
},
);
await client.encryption.ssss.handleToDeviceEvent(event);
expect(await client.encryption.ssss.getCached(EventTypes.MegolmBackup),
await client.encryption!.ssss.handleToDeviceEvent(event);
expect(await client.encryption!.ssss.getCached(EventTypes.MegolmBackup),
null);
});
test('request all', () async {
if (!olmEnabled) return;
final key =
client.userDeviceKeys[client.userID].deviceKeys['OTHERDEVICE'];
client.userDeviceKeys[client.userID!]!.deviceKeys['OTHERDEVICE']!;
key.setDirectVerified(true);
await client.encryption.ssss.clearCache();
client.encryption.ssss.pendingShareRequests.clear();
await client.encryption.ssss.maybeRequestAll([key]);
expect(client.encryption.ssss.pendingShareRequests.length, 3);
await client.encryption!.ssss.clearCache();
client.encryption!.ssss.pendingShareRequests.clear();
await client.encryption!.ssss.maybeRequestAll([key]);
expect(client.encryption!.ssss.pendingShareRequests.length, 3);
});
test('periodicallyRequestMissingCache', () async {
if (!olmEnabled) return;
client.userDeviceKeys[client.userID].masterKey.setDirectVerified(true);
client.encryption.ssss = MockSSSS(client.encryption);
(client.encryption.ssss as MockSSSS).requestedSecrets = false;
await client.encryption.ssss.periodicallyRequestMissingCache();
expect((client.encryption.ssss as MockSSSS).requestedSecrets, true);
client.userDeviceKeys[client.userID!]!.masterKey!.setDirectVerified(true);
client.encryption!.ssss = MockSSSS(client.encryption!);
(client.encryption!.ssss as MockSSSS).requestedSecrets = false;
await client.encryption!.ssss.periodicallyRequestMissingCache();
expect((client.encryption!.ssss as MockSSSS).requestedSecrets, true);
// it should only retry once every 15 min
(client.encryption.ssss as MockSSSS).requestedSecrets = false;
await client.encryption.ssss.periodicallyRequestMissingCache();
expect((client.encryption.ssss as MockSSSS).requestedSecrets, false);
(client.encryption!.ssss as MockSSSS).requestedSecrets = false;
await client.encryption!.ssss.periodicallyRequestMissingCache();
expect((client.encryption!.ssss as MockSSSS).requestedSecrets, false);
});
test('createKey', () async {
if (!olmEnabled) return;
// with passphrase
var newKey = await client.encryption.ssss.createKey('test');
expect(client.encryption.ssss.isKeyValid(newKey.keyId), true);
var testKey = client.encryption.ssss.open(newKey.keyId);
var newKey = await client.encryption!.ssss.createKey('test');
expect(client.encryption!.ssss.isKeyValid(newKey.keyId), true);
var testKey = client.encryption!.ssss.open(newKey.keyId);
await testKey.unlock(passphrase: 'test');
await testKey.setPrivateKey(newKey.privateKey);
await testKey.setPrivateKey(newKey.privateKey!);
// without passphrase
newKey = await client.encryption.ssss.createKey();
expect(client.encryption.ssss.isKeyValid(newKey.keyId), true);
testKey = client.encryption.ssss.open(newKey.keyId);
await testKey.setPrivateKey(newKey.privateKey);
newKey = await client.encryption!.ssss.createKey();
expect(client.encryption!.ssss.isKeyValid(newKey.keyId), true);
testKey = client.encryption!.ssss.open(newKey.keyId);
await testKey.setPrivateKey(newKey.privateKey!);
});
test('dispose client', () async {