This commit is contained in:
Sorunome 2020-06-04 20:16:18 +02:00
parent 8748545f67
commit 05c799e6a5
No known key found for this signature in database
GPG key ID: B19471D07FC9BE9C
5 changed files with 61 additions and 28 deletions

View file

@ -123,7 +123,8 @@ class OlmManager {
} }
/// Generates new one time keys, signs everything and upload it to the server. /// Generates new one time keys, signs everything and upload it to the server.
Future<bool> uploadKeys({bool uploadDeviceKeys = false, int oldKeyCount = 0}) async { Future<bool> uploadKeys(
{bool uploadDeviceKeys = false, int oldKeyCount = 0}) async {
if (!enabled) { if (!enabled) {
return true; return true;
} }
@ -131,7 +132,9 @@ class OlmManager {
// generate one-time keys // generate one-time keys
// we generate 2/3rds of max, so that other keys people may still have can // we generate 2/3rds of max, so that other keys people may still have can
// still be used // still be used
final oneTimeKeysCount = (_olmAccount.max_number_of_one_time_keys() * 2 / 3).floor() - oldKeyCount; final oneTimeKeysCount =
(_olmAccount.max_number_of_one_time_keys() * 2 / 3).floor() -
oldKeyCount;
_olmAccount.generate_one_time_keys(oneTimeKeysCount); _olmAccount.generate_one_time_keys(oneTimeKeysCount);
final Map<String, dynamic> oneTimeKeys = final Map<String, dynamic> oneTimeKeys =
json.decode(_olmAccount.one_time_keys()); json.decode(_olmAccount.one_time_keys());
@ -301,8 +304,8 @@ class OlmManager {
if (client.database == null) { if (client.database == null) {
return false; return false;
} }
final sessions = await client.database.getSingleOlmSessions( final sessions = await client.database
client.id, senderKey, client.userID); .getSingleOlmSessions(client.id, senderKey, client.userID);
if (sessions.isEmpty) { if (sessions.isEmpty) {
return false; // okay, can't do anything return false; // okay, can't do anything
} }
@ -341,7 +344,8 @@ class OlmManager {
final identityKey = final identityKey =
client.userDeviceKeys[userId].deviceKeys[deviceId].curve25519Key; client.userDeviceKeys[userId].deviceKeys[deviceId].curve25519Key;
for (Map<String, dynamic> deviceKey in deviceKeysEntry.value.values) { for (Map<String, dynamic> deviceKey in deviceKeysEntry.value.values) {
if (!checkJsonSignature(fingerprintKey, deviceKey, userId, deviceId)) { if (!checkJsonSignature(
fingerprintKey, deviceKey, userId, deviceId)) {
continue; continue;
} }
try { try {

View file

@ -71,7 +71,8 @@ void main() {
originServerTs: now, originServerTs: now,
eventId: '\$event', eventId: '\$event',
); );
final decryptedEvent = await client.encryption.decryptRoomEvent(roomId, encryptedEvent); final decryptedEvent =
await client.encryption.decryptRoomEvent(roomId, encryptedEvent);
expect(decryptedEvent.type, 'm.room.message'); expect(decryptedEvent.type, 'm.room.message');
expect(decryptedEvent.content['msgtype'], 'm.text'); expect(decryptedEvent.content['msgtype'], 'm.text');
expect(decryptedEvent.content['text'], 'Hello foxies!'); expect(decryptedEvent.content['text'], 'Hello foxies!');
@ -87,7 +88,8 @@ void main() {
originServerTs: now, originServerTs: now,
eventId: '\$event', eventId: '\$event',
); );
final decryptedEvent = await client.encryption.decryptRoomEvent(roomId, encryptedEvent); final decryptedEvent =
await client.encryption.decryptRoomEvent(roomId, encryptedEvent);
expect(decryptedEvent.type, 'm.room.message'); expect(decryptedEvent.type, 'm.room.message');
expect(decryptedEvent.content['msgtype'], 'm.text'); expect(decryptedEvent.content['msgtype'], 'm.text');
expect(decryptedEvent.content['text'], 'Hello foxies!'); expect(decryptedEvent.content['text'], 'Hello foxies!');

View file

@ -28,7 +28,8 @@ void main() {
const pickledOlmAccount = const pickledOlmAccount =
'N2v1MkIFGcl0mQpo2OCwSopxPQJ0wnl7oe7PKiT4141AijfdTIhRu+ceXzXKy3Kr00nLqXtRv7kid6hU4a+V0rfJWLL0Y51+3Rp/ORDVnQy+SSeo6Fn4FHcXrxifJEJ0djla5u98fBcJ8BSkhIDmtXRPi5/oJAvpiYn+8zMjFHobOeZUAxYR0VfQ9JzSYBsSovoQ7uFkNks1M4EDUvHtu/BjDjz0C3ioDgrrFdoSrn+GSeF5FGKsNu8OLkQ9Lq5+BrUutK5QSJI19uoZj2sj/OixvIpnun8XxYpXo7cfh9MEtKI8ob7lLM2OpZ8BogU70ORgkwthsPSOtxQGPhx8+y5Sg7B6KGlU'; 'N2v1MkIFGcl0mQpo2OCwSopxPQJ0wnl7oe7PKiT4141AijfdTIhRu+ceXzXKy3Kr00nLqXtRv7kid6hU4a+V0rfJWLL0Y51+3Rp/ORDVnQy+SSeo6Fn4FHcXrxifJEJ0djla5u98fBcJ8BSkhIDmtXRPi5/oJAvpiYn+8zMjFHobOeZUAxYR0VfQ9JzSYBsSovoQ7uFkNks1M4EDUvHtu/BjDjz0C3ioDgrrFdoSrn+GSeF5FGKsNu8OLkQ9Lq5+BrUutK5QSJI19uoZj2sj/OixvIpnun8XxYpXo7cfh9MEtKI8ob7lLM2OpZ8BogU70ORgkwthsPSOtxQGPhx8+y5Sg7B6KGlU';
const otherPickledOlmAccount = 'VWhVApbkcilKAEGppsPDf9nNVjaK8/IxT3asSR0sYg0S5KgbfE8vXEPwoiKBX2cEvwX3OessOBOkk+ZE7TTbjlrh/KEd31p8Wo+47qj0AP+Ky+pabnhi+/rTBvZy+gfzTqUfCxZrkzfXI9Op4JnP6gYmy7dVX2lMYIIs9WCO1jcmIXiXum5jnfXu1WLfc7PZtO2hH+k9CDKosOFaXRBmsu8k/BGXPSoWqUpvu6WpEG9t5STk4FeAzA'; const otherPickledOlmAccount =
'VWhVApbkcilKAEGppsPDf9nNVjaK8/IxT3asSR0sYg0S5KgbfE8vXEPwoiKBX2cEvwX3OessOBOkk+ZE7TTbjlrh/KEd31p8Wo+47qj0AP+Ky+pabnhi+/rTBvZy+gfzTqUfCxZrkzfXI9Op4JnP6gYmy7dVX2lMYIIs9WCO1jcmIXiXum5jnfXu1WLfc7PZtO2hH+k9CDKosOFaXRBmsu8k/BGXPSoWqUpvu6WpEG9t5STk4FeAzA';
group('Encrypt/Decrypt to-device messages', () { group('Encrypt/Decrypt to-device messages', () {
var olmEnabled = true; var olmEnabled = true;
@ -44,7 +45,8 @@ void main() {
if (!olmEnabled) return; if (!olmEnabled) return;
var client = Client('testclient', debug: true, httpClient: FakeMatrixApi()); var client = Client('testclient', debug: true, httpClient: FakeMatrixApi());
var otherClient = Client('othertestclient', debug: true, httpClient: FakeMatrixApi()); var otherClient =
Client('othertestclient', debug: true, httpClient: FakeMatrixApi());
final roomId = '!726s6s6q:example.com'; final roomId = '!726s6s6q:example.com';
DeviceKeys device; DeviceKeys device;
Map<String, dynamic> payload; Map<String, dynamic> payload;
@ -92,12 +94,14 @@ void main() {
}); });
test('encryptToDeviceMessage', () async { test('encryptToDeviceMessage', () async {
payload = await otherClient.encryption.encryptToDeviceMessage([device], 'm.to_device', {'hello': 'foxies'}); payload = await otherClient.encryption
.encryptToDeviceMessage([device], 'm.to_device', {'hello': 'foxies'});
}); });
test('encryptToDeviceMessagePayload', () async { test('encryptToDeviceMessagePayload', () async {
// just a hard test if nothing errors // just a hard test if nothing errors
await otherClient.encryption.encryptToDeviceMessagePayload(device, 'm.to_device', {'hello': 'foxies'}); await otherClient.encryption.encryptToDeviceMessagePayload(
device, 'm.to_device', {'hello': 'foxies'});
}); });
test('decryptToDeviceEvent', () async { test('decryptToDeviceEvent', () async {
@ -106,20 +110,23 @@ void main() {
type: EventTypes.Encrypted, type: EventTypes.Encrypted,
content: payload[client.userID][client.deviceID], content: payload[client.userID][client.deviceID],
); );
final decryptedEvent = await client.encryption.decryptToDeviceEvent(encryptedEvent); final decryptedEvent =
await client.encryption.decryptToDeviceEvent(encryptedEvent);
expect(decryptedEvent.type, 'm.to_device'); expect(decryptedEvent.type, 'm.to_device');
expect(decryptedEvent.content['hello'], 'foxies'); expect(decryptedEvent.content['hello'], 'foxies');
}); });
test('decryptToDeviceEvent nocache', () async { test('decryptToDeviceEvent nocache', () async {
client.encryption.olmManager.olmSessions.clear(); client.encryption.olmManager.olmSessions.clear();
payload = await otherClient.encryption.encryptToDeviceMessage([device], 'm.to_device', {'hello': 'superfoxies'}); payload = await otherClient.encryption.encryptToDeviceMessage(
[device], 'm.to_device', {'hello': 'superfoxies'});
final encryptedEvent = ToDeviceEvent( final encryptedEvent = ToDeviceEvent(
sender: '@othertest:fakeServer.notExisting', sender: '@othertest:fakeServer.notExisting',
type: EventTypes.Encrypted, type: EventTypes.Encrypted,
content: payload[client.userID][client.deviceID], content: payload[client.userID][client.deviceID],
); );
final decryptedEvent = await client.encryption.decryptToDeviceEvent(encryptedEvent); final decryptedEvent =
await client.encryption.decryptToDeviceEvent(encryptedEvent);
expect(decryptedEvent.type, 'm.to_device'); expect(decryptedEvent.type, 'm.to_device');
expect(decryptedEvent.content['hello'], 'superfoxies'); expect(decryptedEvent.content['hello'], 'superfoxies');
}); });

View file

@ -51,38 +51,54 @@ void main() {
'fox': 'floof', 'fox': 'floof',
}; };
final signedPayload = client.encryption.olmManager.signJson(payload); final signedPayload = client.encryption.olmManager.signJson(payload);
expect(client.encryption.olmManager.checkJsonSignature(client.fingerprintKey, signedPayload, client.userID, client.deviceID), true); expect(
expect(client.encryption.olmManager.checkJsonSignature(client.fingerprintKey, payload, client.userID, client.deviceID), false); client.encryption.olmManager.checkJsonSignature(client.fingerprintKey,
signedPayload, client.userID, client.deviceID),
true);
expect(
client.encryption.olmManager.checkJsonSignature(
client.fingerprintKey, payload, client.userID, client.deviceID),
false);
}); });
test('uploadKeys', () async { test('uploadKeys', () async {
FakeMatrixApi.calledEndpoints.clear(); FakeMatrixApi.calledEndpoints.clear();
final res = await client.encryption.olmManager.uploadKeys(uploadDeviceKeys: true); final res =
await client.encryption.olmManager.uploadKeys(uploadDeviceKeys: true);
expect(res, true); expect(res, true);
var sent = json.decode(FakeMatrixApi.calledEndpoints['/client/r0/keys/upload'].first); var sent = json.decode(
FakeMatrixApi.calledEndpoints['/client/r0/keys/upload'].first);
expect(sent['device_keys'] != null, true); expect(sent['device_keys'] != null, true);
expect(sent['one_time_keys'] != null, true); expect(sent['one_time_keys'] != null, true);
expect(sent['one_time_keys'].keys.length, 66); expect(sent['one_time_keys'].keys.length, 66);
FakeMatrixApi.calledEndpoints.clear(); FakeMatrixApi.calledEndpoints.clear();
await client.encryption.olmManager.uploadKeys(); await client.encryption.olmManager.uploadKeys();
sent = json.decode(FakeMatrixApi.calledEndpoints['/client/r0/keys/upload'].first); sent = json.decode(
FakeMatrixApi.calledEndpoints['/client/r0/keys/upload'].first);
expect(sent['device_keys'] != null, false); expect(sent['device_keys'] != null, false);
FakeMatrixApi.calledEndpoints.clear(); FakeMatrixApi.calledEndpoints.clear();
await client.encryption.olmManager.uploadKeys(oldKeyCount: 20); await client.encryption.olmManager.uploadKeys(oldKeyCount: 20);
sent = json.decode(FakeMatrixApi.calledEndpoints['/client/r0/keys/upload'].first); sent = json.decode(
FakeMatrixApi.calledEndpoints['/client/r0/keys/upload'].first);
expect(sent['one_time_keys'].keys.length, 46); expect(sent['one_time_keys'].keys.length, 46);
}); });
test('handleDeviceOneTimeKeysCount', () async { test('handleDeviceOneTimeKeysCount', () async {
FakeMatrixApi.calledEndpoints.clear(); FakeMatrixApi.calledEndpoints.clear();
client.encryption.olmManager.handleDeviceOneTimeKeysCount({'signed_curve25519': 20}); client.encryption.olmManager
.handleDeviceOneTimeKeysCount({'signed_curve25519': 20});
await Future.delayed(Duration(milliseconds: 50)); await Future.delayed(Duration(milliseconds: 50));
expect(FakeMatrixApi.calledEndpoints.containsKey('/client/r0/keys/upload'), true); expect(
FakeMatrixApi.calledEndpoints.containsKey('/client/r0/keys/upload'),
true);
FakeMatrixApi.calledEndpoints.clear(); FakeMatrixApi.calledEndpoints.clear();
client.encryption.olmManager.handleDeviceOneTimeKeysCount({'signed_curve25519': 70}); client.encryption.olmManager
.handleDeviceOneTimeKeysCount({'signed_curve25519': 70});
await Future.delayed(Duration(milliseconds: 50)); await Future.delayed(Duration(milliseconds: 50));
expect(FakeMatrixApi.calledEndpoints.containsKey('/client/r0/keys/upload'), false); expect(
FakeMatrixApi.calledEndpoints.containsKey('/client/r0/keys/upload'),
false);
}); });
}); });
} }

View file

@ -1576,7 +1576,8 @@ class FakeMatrixApi extends MockClient {
'key': 'qc72ve94cA28iuE0fXa98QO3uls39DHWdQlYyvvhGh0', 'key': 'qc72ve94cA28iuE0fXa98QO3uls39DHWdQlYyvvhGh0',
'signatures': { 'signatures': {
'@test:fakeServer.notExisting': { '@test:fakeServer.notExisting': {
'ed25519:GHTYAJCE': 'dFwffr5kTKefO7sjnWLMhTzw7oV31nkPIDRxFy5OQT2OP5++Ao0KRbaBZ6qfuT7lW1owKK0Xk3s7QTBvc/eNDA', 'ed25519:GHTYAJCE':
'dFwffr5kTKefO7sjnWLMhTzw7oV31nkPIDRxFy5OQT2OP5++Ao0KRbaBZ6qfuT7lW1owKK0Xk3s7QTBvc/eNDA',
}, },
}, },
}, },
@ -1598,7 +1599,8 @@ class FakeMatrixApi extends MockClient {
'/client/r0/keys/upload': (var req) => { '/client/r0/keys/upload': (var req) => {
'one_time_key_counts': { 'one_time_key_counts': {
'curve25519': 10, 'curve25519': 10,
'signed_curve25519': json.decode(req)['one_time_keys']?.keys?.length ?? 0, 'signed_curve25519':
json.decode(req)['one_time_keys']?.keys?.length ?? 0,
} }
}, },
'/client/r0/keys/query': (var req) => { '/client/r0/keys/query': (var req) => {
@ -1666,8 +1668,10 @@ class FakeMatrixApi extends MockClient {
'm.megolm.v1.aes-sha2' 'm.megolm.v1.aes-sha2'
], ],
'keys': { 'keys': {
'curve25519:FOXDEVICE': 'JBG7ZaPn54OBC7TuIEiylW3BZ+7WcGQhFBPB9pogbAg', 'curve25519:FOXDEVICE':
'ed25519:FOXDEVICE': 'R5/p04tticvdlNIxiiBIP0j9OQWv8ep6eEU6/lWKDxw', 'JBG7ZaPn54OBC7TuIEiylW3BZ+7WcGQhFBPB9pogbAg',
'ed25519:FOXDEVICE':
'R5/p04tticvdlNIxiiBIP0j9OQWv8ep6eEU6/lWKDxw',
}, },
'signatures': {}, 'signatures': {},
}, },