From c233d57f9fc81367904453378271155887996f4c Mon Sep 17 00:00:00 2001 From: Sorunome Date: Sat, 13 Jun 2020 19:48:38 +0200 Subject: [PATCH] add online key backup test --- lib/encryption/key_manager.dart | 31 +++++---- test/encryption/key_request_test.dart | 20 +++--- test/encryption/online_key_backup_test.dart | 73 +++++++++++++++++++++ test/fake_matrix_api.dart | 15 ++++- 4 files changed, 116 insertions(+), 23 deletions(-) create mode 100644 test/encryption/online_key_backup_test.dart diff --git a/lib/encryption/key_manager.dart b/lib/encryption/key_manager.dart index eeeb08d..9621112 100644 --- a/lib/encryption/key_manager.dart +++ b/lib/encryption/key_manager.dart @@ -398,20 +398,23 @@ class KeyManager { } /// Request a certain key from another device - Future request(Room room, String sessionId, String senderKey) async { - // let's first check our online key backup store thingy... - var hadPreviously = - getInboundGroupSession(room.id, sessionId, senderKey) != null; - try { - await loadSingleKey(room.id, sessionId); - } catch (err, stacktrace) { - print( - '[KeyManager] Failed to access online key backup: ' + err.toString()); - print(stacktrace); - } - if (!hadPreviously && - getInboundGroupSession(room.id, sessionId, senderKey) != null) { - return; // we managed to load the session from online backup, no need to care about it now + Future request(Room room, String sessionId, String senderKey, + {bool tryOnlineBackup = true}) async { + if (tryOnlineBackup) { + // let's first check our online key backup store thingy... + var hadPreviously = + getInboundGroupSession(room.id, sessionId, senderKey) != null; + try { + await loadSingleKey(room.id, sessionId); + } catch (err, stacktrace) { + print('[KeyManager] Failed to access online key backup: ' + + err.toString()); + print(stacktrace); + } + if (!hadPreviously && + getInboundGroupSession(room.id, sessionId, senderKey) != null) { + return; // we managed to load the session from online backup, no need to care about it now + } } // while we just send the to-device event to '*', we still need to save the // devices themself to know where to send the cancel to after receiving a reply diff --git a/test/encryption/key_request_test.dart b/test/encryption/key_request_test.dart index 168a167..c7dbb9f 100644 --- a/test/encryption/key_request_test.dart +++ b/test/encryption/key_request_test.dart @@ -56,8 +56,9 @@ void main() { test('Create Request', () async { var matrix = await getClient(); final requestRoom = matrix.getRoomById('!726s6s6q:example.com'); - await matrix.encryption.keyManager - .request(requestRoom, 'sessionId', validSenderKey); + await matrix.encryption.keyManager.request( + requestRoom, 'sessionId', validSenderKey, + tryOnlineBackup: false); var foundEvent = false; for (var entry in FakeMatrixApi.calledEndpoints.entries) { final payload = jsonDecode(entry.value.first); @@ -223,8 +224,9 @@ void main() { test('Receive shared keys', () async { var matrix = await getClient(); final requestRoom = matrix.getRoomById('!726s6s6q:example.com'); - await matrix.encryption.keyManager - .request(requestRoom, validSessionId, validSenderKey); + await matrix.encryption.keyManager.request( + requestRoom, validSessionId, validSenderKey, + tryOnlineBackup: false); final session = await matrix.encryption.keyManager .loadInboundGroupSession( @@ -279,8 +281,9 @@ void main() { false); // unknown device - await matrix.encryption.keyManager - .request(requestRoom, validSessionId, validSenderKey); + await matrix.encryption.keyManager.request( + requestRoom, validSessionId, validSenderKey, + tryOnlineBackup: false); matrix.encryption.keyManager.clearInboundGroupSessions(); event = ToDeviceEvent( sender: '@alice:example.com', @@ -304,8 +307,9 @@ void main() { false); // no encrypted content - await matrix.encryption.keyManager - .request(requestRoom, validSessionId, validSenderKey); + await matrix.encryption.keyManager.request( + requestRoom, validSessionId, validSenderKey, + tryOnlineBackup: false); matrix.encryption.keyManager.clearInboundGroupSessions(); event = ToDeviceEvent( sender: '@alice:example.com', diff --git a/test/encryption/online_key_backup_test.dart b/test/encryption/online_key_backup_test.dart new file mode 100644 index 0000000..0a3b842 --- /dev/null +++ b/test/encryption/online_key_backup_test.dart @@ -0,0 +1,73 @@ +/* + * Ansible inventory script used at Famedly GmbH for managing many hosts + * Copyright (C) 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import 'package:famedlysdk/famedlysdk.dart'; +import 'package:test/test.dart'; +import 'package:olm/olm.dart' as olm; + +import '../fake_client.dart'; + +void main() { + group('Online Key Backup', () { + var olmEnabled = true; + try { + olm.init(); + olm.Account(); + } catch (_) { + olmEnabled = false; + print('[LibOlm] Failed to load LibOlm: ' + _.toString()); + } + print('[LibOlm] Enabled: $olmEnabled'); + + if (!olmEnabled) return; + + Client client; + + final roomId = '!726s6s6q:example.com'; + final sessionId = 'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU'; + final senderKey = 'JBG7ZaPn54OBC7TuIEiylW3BZ+7WcGQhFBPB9pogbAg'; + + test('setupClient', () async { + client = await getClient(); + }); + + test('basic things', () async { + expect(client.encryption.keyManager.enabled, true); + expect(await client.encryption.keyManager.isCached(), false); + final handle = client.encryption.ssss.open(); + handle.unlock(recoveryKey: SSSS_KEY); + await handle.maybeCacheAll(); + expect(await client.encryption.keyManager.isCached(), true); + }); + + test('load key', () async { + client.encryption.keyManager.clearInboundGroupSessions(); + await client.encryption.keyManager + .request(client.getRoomById(roomId), sessionId, senderKey); + expect( + client.encryption.keyManager + .getInboundGroupSession(roomId, sessionId, senderKey) != + null, + true); + }); + + test('dispose client', () async { + await client.dispose(closeDatabase: true); + }); + }); +} diff --git a/test/fake_matrix_api.dart b/test/fake_matrix_api.dart index e69538c..4fb17cf 100644 --- a/test/fake_matrix_api.dart +++ b/test/fake_matrix_api.dart @@ -1533,12 +1533,25 @@ class FakeMatrixApi extends MockClient { '/client/unstable/room_keys/version': (var req) => { 'algorithm': 'm.megolm_backup.v1.curve25519-aes-sha2', 'auth_data': { - 'public_key': 'GXYaxqhNhUK28zUdxOmEsFRguz+PzBsDlTLlF0O0RkM' + 'public_key': 'GXYaxqhNhUK28zUdxOmEsFRguz+PzBsDlTLlF0O0RkM', + 'signatures': {}, }, 'count': 0, 'etag': '0', 'version': '5', }, + '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5': + (var req) => { + 'first_message_index': 0, + 'forwarded_count': 0, + 'is_verified': true, + 'session_data': { + 'ephemeral': 'fwRxYh+seqLykz5mQCLypJ4/59URdcFJ2s69OU1dGRc', + 'ciphertext': + '19jkQYlbgdP+VL9DH3qY/Dvpk6onJZgf+6frZFl1TinPCm9OMK9AZZLuM1haS9XLAUK1YsREgjBqfl6T+Tq8JlJ5ONZGg2Wttt24sGYc0iTMZJ8rXcNDeKMZhM96ETyjufJSeYoXLqifiVLDw9rrVBmNStF7PskYp040em+0OZ4pF85Cwsdf7l9V7MMynzh9BoXqVUCBiwT03PNYH9AEmNUxXX+6ZwCpe/saONv8MgGt5uGXMZIK29phA3D8jD6uV/WOHsB8NjHNq9FrfSEAsl+dAcS4uiYie4BKSSeQN+zGAQqu1MMW4OAdxGOuf8WpIINx7n+7cKQfxlmc/Cgg5+MmIm2H0oDwQ+Xu7aSxp1OCUzbxQRdjz6+tnbYmZBuH0Ov2RbEvC5tDb261LRqKXpub0llg5fqKHl01D0ahv4OAQgRs5oU+4mq+H2QGTwIFGFqP9tCRo0I+aICawpxYOfoLJpFW6KvEPnM2Lr3sl6Nq2fmkz6RL5F7nUtzxN8OKazLQpv8DOYzXbi7+ayEsqS0/EINetq7RfCqgjrEUgfNWYuFXWqvUT8lnxLdNu+8cyrJqh1UquFjXWTw1kWcJ0pkokVeBtK9YysCnF1UYh/Iv3rl2ZoYSSLNtuvMSYlYHggZ8xV8bz9S3X2/NwBycBiWIy5Ou/OuSX7trIKgkkmda0xjBWEM1a2acVuqu2OFbMn2zFxm2a3YwKP//OlIgMg', + 'mac': 'QzKV/fgAs4U', + }, + }, }, 'POST': { '/client/r0/delete_devices': (var req) => {},