diff --git a/lib/encryption/encryption.dart b/lib/encryption/encryption.dart index 54a63ddd..13c81b63 100644 --- a/lib/encryption/encryption.dart +++ b/lib/encryption/encryption.dart @@ -19,7 +19,7 @@ import 'dart:async'; import 'dart:convert'; -import 'package:olm/olm.dart' as olm; +import 'package:vodozemac/vodozemac.dart' as vod; import 'package:matrix/encryption/cross_signing.dart'; import 'package:matrix/encryption/key_manager.dart'; @@ -87,18 +87,6 @@ class Encryption { if (!isDehydratedDevice) keyManager.startAutoUploadKeys(); } - bool isMinOlmVersion(int major, int minor, int patch) { - try { - final version = olm.get_library_version(); - return version[0] > major || - (version[0] == major && - (version[1] > minor || - (version[1] == minor && version[2] >= patch))); - } catch (_) { - return false; - } - } - Bootstrap bootstrap({void Function(Bootstrap)? onUpdate}) => Bootstrap( encryption: this, onUpdate: onUpdate, diff --git a/lib/encryption/olm_manager.dart b/lib/encryption/olm_manager.dart index d1958152..c445755c 100644 --- a/lib/encryption/olm_manager.dart +++ b/lib/encryption/olm_manager.dart @@ -21,11 +21,12 @@ import 'dart:convert'; import 'package:async/async.dart'; import 'package:canonical_json/canonical_json.dart'; import 'package:collection/collection.dart'; -import 'package:olm/olm.dart' as olm; +import 'package:vodozemac/vodozemac.dart' as vod; import 'package:matrix/encryption/encryption.dart'; import 'package:matrix/encryption/utils/json_signature_check_extension.dart'; import 'package:matrix/encryption/utils/olm_session.dart'; +import 'package:matrix/encryption/utils/pickle_key.dart'; import 'package:matrix/matrix.dart'; import 'package:matrix/msc_extensions/msc_3814_dehydrated_devices/api.dart'; import 'package:matrix/src/utils/run_benchmarked.dart'; @@ -34,20 +35,24 @@ import 'package:matrix/src/utils/run_in_root.dart'; class OlmManager { final Encryption encryption; Client get client => encryption.client; - olm.Account? _olmAccount; + vod.Account? _olmAccount; String? ourDeviceId; /// Returns the base64 encoded keys to store them in a store. /// This String should **never** leave the device! - String? get pickledOlmAccount => - enabled ? _olmAccount!.pickle(client.userID!) : null; + String? get pickledOlmAccount { + return enabled + ? _olmAccount!.toPickleEncrypted(client.userID!.toPickleKey()) + : null; + } + String? get fingerprintKey => - enabled ? json.decode(_olmAccount!.identity_keys())['ed25519'] : null; + enabled ? _olmAccount!.identityKeys.ed25519.toBase64() : null; String? get identityKey => - enabled ? json.decode(_olmAccount!.identity_keys())['curve25519'] : null; + enabled ? _olmAccount!.identityKeys.curve25519.toBase64() : null; String? pickleOlmAccountWithKey(String key) => - enabled ? _olmAccount!.pickle(key) : null; + enabled ? _olmAccount!.toPickleEncrypted(key.toPickleKey()) : null; bool get enabled => _olmAccount != null; @@ -66,33 +71,31 @@ class OlmManager { }) async { ourDeviceId = deviceId; if (olmAccount == null) { - try { - await olm.init(); - _olmAccount = olm.Account(); - _olmAccount!.create(); - if (!await uploadKeys( - uploadDeviceKeys: true, - updateDatabase: false, - dehydratedDeviceAlgorithm: dehydratedDeviceAlgorithm, - dehydratedDevicePickleKey: - dehydratedDeviceAlgorithm != null ? pickleKey : null, - )) { - throw ('Upload key failed'); - } - } catch (_) { - _olmAccount?.free(); - _olmAccount = null; - rethrow; + _olmAccount = vod.Account(); + if (!await uploadKeys( + uploadDeviceKeys: true, + updateDatabase: false, + dehydratedDeviceAlgorithm: dehydratedDeviceAlgorithm, + dehydratedDevicePickleKey: + dehydratedDeviceAlgorithm != null ? pickleKey : null, + )) { + throw ('Upload key failed'); } } else { try { - await olm.init(); - _olmAccount = olm.Account(); - _olmAccount!.unpickle(pickleKey ?? client.userID!, olmAccount); - } catch (_) { - _olmAccount?.free(); - _olmAccount = null; - rethrow; + _olmAccount = vod.Account.fromPickleEncrypted( + pickle: olmAccount, + pickleKey: (pickleKey ?? client.userID!).toPickleKey(), + ); + } catch (e) { + Logs().d( + 'Unable to unpickle account in vodozemac format. Trying Olm format...', + e, + ); + _olmAccount = vod.Account.fromOlmPickleEncrypted( + pickle: olmAccount, + pickleKey: utf8.encode(pickleKey ?? client.userID!), + ); } } } @@ -115,7 +118,8 @@ class OlmManager { if (!payload['signatures'].containsKey(client.userID)) { payload['signatures'][client.userID] = {}; } - payload['signatures'][client.userID]['ed25519:$ourDeviceId'] = signature; + payload['signatures'][client.userID]['ed25519:$ourDeviceId'] = + signature.toBase64(); if (unsigned != null) { payload['unsigned'] = unsigned; } @@ -123,13 +127,13 @@ class OlmManager { } String signString(String s) { - return _olmAccount!.sign(s); + return _olmAccount!.sign(s).toBase64(); } bool _uploadKeysLock = false; CancelableOperation>? currentUpload; - int? get maxNumberOfOneTimeKeys => _olmAccount?.max_number_of_one_time_keys(); + int? get maxNumberOfOneTimeKeys => _olmAccount?.maxNumberOfOneTimeKeys; /// Generates new one time keys, signs everything and upload it to the server. /// If `retry` is > 0, the request will be retried with new OTKs on upload failure. @@ -158,26 +162,24 @@ class OlmManager { if (oldKeyCount != null) { // check if we have OTKs that still need uploading. If we do, we don't try to generate new ones, // instead we try to upload the old ones first - final oldOTKsNeedingUpload = json - .decode(olmAccount.one_time_keys())['curve25519'] - .entries - .length as int; + final oldOTKsNeedingUpload = olmAccount.oneTimeKeys.length; + // generate one-time keys // we generate 2/3rds of max, so that other keys people may still have can // still be used final oneTimeKeysCount = - (olmAccount.max_number_of_one_time_keys() * 2 / 3).floor() - + (olmAccount.maxNumberOfOneTimeKeys * 2 / 3).floor() - oldKeyCount - oldOTKsNeedingUpload; if (oneTimeKeysCount > 0) { - olmAccount.generate_one_time_keys(oneTimeKeysCount); + olmAccount.generateOneTimeKeys(oneTimeKeysCount); } uploadedOneTimeKeysCount = oneTimeKeysCount + oldOTKsNeedingUpload; } - if (encryption.isMinOlmVersion(3, 2, 7) && unusedFallbackKey == false) { + if (unusedFallbackKey == false) { // we don't have an unused fallback key uploaded....so let's change that! - olmAccount.generate_fallback_key(); + olmAccount.generateFallbackKey(); } // we save the generated OTKs into the database. @@ -199,38 +201,32 @@ class OlmManager { }; if (uploadDeviceKeys) { - final Map keys = - json.decode(olmAccount.identity_keys()); - for (final entry in keys.entries) { - final algorithm = entry.key; - final value = entry.value; - deviceKeys['keys']['$algorithm:$ourDeviceId'] = value; - } + final keys = olmAccount.identityKeys; + deviceKeys['keys']['curve25519:$ourDeviceId'] = + keys.curve25519.toBase64(); + deviceKeys['keys']['ed25519:$ourDeviceId'] = keys.ed25519.toBase64(); deviceKeys = signJson(deviceKeys); } // now sign all the one-time keys - for (final entry - in json.decode(olmAccount.one_time_keys())['curve25519'].entries) { + for (final entry in olmAccount.oneTimeKeys.entries) { final key = entry.key; - final value = entry.value; + final value = entry.value.toBase64(); signedOneTimeKeys['signed_curve25519:$key'] = signJson({ 'key': value, }); } final signedFallbackKeys = {}; - if (encryption.isMinOlmVersion(3, 2, 7)) { - final fallbackKey = json.decode(olmAccount.unpublished_fallback_key()); - // now sign all the fallback keys - for (final entry in fallbackKey['curve25519'].entries) { - final key = entry.key; - final value = entry.value; - signedFallbackKeys['signed_curve25519:$key'] = signJson({ - 'key': value, - 'fallback': true, - }); - } + final fallbackKey = olmAccount.fallbackKey; + // now sign all the fallback keys + for (final entry in fallbackKey.entries) { + final key = entry.key; + final value = entry.value.toBase64(); + signedFallbackKeys['signed_curve25519:$key'] = signJson({ + 'key': value, + 'fallback': true, + }); } if (signedFallbackKeys.isEmpty && @@ -281,7 +277,7 @@ class OlmManager { } // mark the OTKs as published and save that to datbase - olmAccount.mark_keys_as_published(); + olmAccount.markKeysAsPublished(); if (updateDatabase) { await encryption.olmDatabase?.updateClientKeys(pickledOlmAccount!); } @@ -301,17 +297,14 @@ class OlmManager { Logs().w('Rotating otks because upload failed', exception); for (final otk in signedOneTimeKeys.values) { // Keys can only be removed by creating a session... - final session = olm.Session(); - try { - final String identity = - json.decode(olmAccount.identity_keys())['curve25519']; - final key = otk.tryGet('key'); - if (key != null) { - session.create_outbound(_olmAccount!, identity, key); - olmAccount.remove_one_time_keys(session); - } - } finally { - session.free(); + + final identity = olmAccount.identityKeys.curve25519.toBase64(); + final key = otk.tryGet('key'); + if (key != null) { + olmAccount.createOutboundSession( + identityKey: vod.Curve25519PublicKey.fromBase64(identity), + oneTimeKey: vod.Curve25519PublicKey.fromBase64(key), + ); } } @@ -342,7 +335,6 @@ class OlmManager { await _otkUpdateDedup.fetch( () => runBenchmarked('handleOtkUpdate', () async { - final haveFallbackKeys = encryption.isMinOlmVersion(3, 2, 0); // Check if there are at least half of max_number_of_one_time_keys left on the server // and generate and upload more if not. @@ -357,7 +349,7 @@ class OlmManager { } // fixup accidental too many uploads. We delete only one of them so that the server has time to update the counts and because we will get rate limited anyway. - if (keyCount > _olmAccount!.max_number_of_one_time_keys()) { + if (keyCount > _olmAccount!.maxNumberOfOneTimeKeys) { final requestingKeysFrom = { client.userID!: {ourDeviceId!: 'signed_curve25519'}, }; @@ -365,14 +357,13 @@ class OlmManager { } // Only upload keys if they are less than half of the max or we have no unused fallback key - if (keyCount < (_olmAccount!.max_number_of_one_time_keys() / 2) || + if (keyCount < (_olmAccount!.maxNumberOfOneTimeKeys / 2) || !unusedFallbackKey) { await uploadKeys( - oldKeyCount: - keyCount < (_olmAccount!.max_number_of_one_time_keys() / 2) - ? keyCount - : null, - unusedFallbackKey: haveFallbackKeys ? unusedFallbackKey : null, + oldKeyCount: keyCount < (_olmAccount!.maxNumberOfOneTimeKeys / 2) + ? keyCount + : null, + unusedFallbackKey: unusedFallbackKey, ); } }), @@ -449,9 +440,12 @@ class OlmManager { if (session.session == null) { continue; } - if (type == 0 && session.session!.matches_inbound(body)) { + if (type == 0) { try { - plaintext = session.session!.decrypt(type, body); + plaintext = session.session!.decrypt( + messageType: type, + ciphertext: body, + ); } catch (e) { // The message was encrypted during this session, but is unable to decrypt throw DecryptException( @@ -463,7 +457,10 @@ class OlmManager { break; } else if (type == 1) { try { - plaintext = session.session!.decrypt(type, body); + plaintext = session.session!.decrypt( + messageType: type, + ciphertext: body, + ); await updateSessionUsage(session); break; } catch (_) { @@ -477,26 +474,27 @@ class OlmManager { } if (plaintext == null) { - final newSession = olm.Session(); try { - newSession.create_inbound_from(_olmAccount!, senderKey, body); - _olmAccount!.remove_one_time_keys(newSession); - await encryption.olmDatabase?.updateClientKeys(pickledOlmAccount!); + final result = _olmAccount!.createInboundSession( + theirIdentityKey: vod.Curve25519PublicKey.fromBase64(senderKey), + preKeyMessageBase64: body, + ); + plaintext = result.plaintext; + final newSession = result.session; - plaintext = newSession.decrypt(type, body); + await encryption.olmDatabase?.updateClientKeys(pickledOlmAccount!); await storeOlmSession( OlmSession( key: client.userID!, identityKey: senderKey, - sessionId: newSession.session_id(), + sessionId: newSession.sessionId, session: newSession, lastReceived: DateTime.now(), ), ); await updateSessionUsage(); } catch (e) { - newSession.free(); throw DecryptException(DecryptException.decryptionFailed, e.toString()); } } @@ -660,25 +658,25 @@ class OlmManager { continue; } Logs().v('[OlmManager] Starting session with $userId:$deviceId'); - final session = olm.Session(); try { - session.create_outbound( - _olmAccount!, - identityKey, - deviceKey.tryGet('key')!, + final session = _olmAccount!.createOutboundSession( + identityKey: vod.Curve25519PublicKey.fromBase64(identityKey), + oneTimeKey: vod.Curve25519PublicKey.fromBase64( + deviceKey.tryGet('key')!, + ), ); + await storeOlmSession( OlmSession( key: client.userID!, identityKey: identityKey, - sessionId: session.session_id(), + sessionId: session.sessionId, session: session, lastReceived: DateTime.now(), // we want to use a newly created session ), ); } catch (e, s) { - session.free(); Logs() .e('[LibOlm] Could not create new outbound olm session', e, s); } @@ -733,8 +731,8 @@ class OlmManager { 'ciphertext': {}, }; encryptedBody['ciphertext'][device.curve25519Key] = { - 'type': encryptResult.type, - 'body': encryptResult.body, + 'type': encryptResult.messageType, + 'body': encryptResult.ciphertext, }; return encryptedBody; } @@ -820,13 +818,6 @@ class OlmManager { Future dispose() async { await currentUpload?.cancel(); - for (final sessions in olmSessions.values) { - for (final sess in sessions) { - sess.dispose(); - } - } - _olmAccount?.free(); - _olmAccount = null; } } diff --git a/lib/encryption/utils/olm_session.dart b/lib/encryption/utils/olm_session.dart index 513699ae..6f44b606 100644 --- a/lib/encryption/utils/olm_session.dart +++ b/lib/encryption/utils/olm_session.dart @@ -16,17 +16,20 @@ * along with this program. If not, see . */ -import 'package:olm/olm.dart' as olm; +import 'dart:convert'; +import 'package:vodozemac/vodozemac.dart' as vod; + +import 'package:matrix/encryption/utils/pickle_key.dart'; import 'package:matrix/matrix.dart'; class OlmSession { String identityKey; String? sessionId; - olm.Session? session; + vod.Session? session; DateTime? lastReceived; final String key; - String? get pickledSession => session?.pickle(key); + String? get pickledSession => session?.toPickleEncrypted(key.toPickleKey()); bool get isValid => session != null; @@ -40,21 +43,24 @@ class OlmSession { OlmSession.fromJson(Map dbEntry, this.key) : identityKey = dbEntry['identity_key'] ?? '' { - session = olm.Session(); try { - session!.unpickle(key, dbEntry['pickle']); + try { + session = vod.Session.fromPickleEncrypted( + pickleKey: key.toPickleKey(), + pickle: dbEntry['pickle'], + ); + } catch (_) { + session = vod.Session.fromOlmPickleEncrypted( + pickleKey: utf8.encode(key), + pickle: dbEntry['pickle'], + ); + } sessionId = dbEntry['session_id']; lastReceived = DateTime.fromMillisecondsSinceEpoch(dbEntry['last_received'] ?? 0); - assert(sessionId == session!.session_id()); + assert(sessionId == session!.sessionId); } catch (e, s) { Logs().e('[LibOlm] Could not unpickle olm session', e, s); - dispose(); } } - - void dispose() { - session?.free(); - session = null; - } } diff --git a/lib/matrix_api_lite/generated/api.dart b/lib/matrix_api_lite/generated/api.dart index c571cf34..bcf02678 100644 --- a/lib/matrix_api_lite/generated/api.dart +++ b/lib/matrix_api_lite/generated/api.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'dart:developer'; import 'dart:typed_data'; import 'package:http/http.dart'; diff --git a/lib/src/client.dart b/lib/src/client.dart index bdb788a6..af32a013 100644 --- a/lib/src/client.dart +++ b/lib/src/client.dart @@ -26,7 +26,6 @@ import 'package:async/async.dart'; import 'package:collection/collection.dart' show IterableExtension; import 'package:http/http.dart' as http; import 'package:mime/mime.dart'; -import 'package:olm/olm.dart' as olm; import 'package:random_string/random_string.dart'; import 'package:matrix/encryption.dart'; @@ -2102,9 +2101,6 @@ class Client extends MatrixApi { await encryption?.dispose(); try { - // make sure to throw an exception if libolm doesn't exist - await olm.init(); - olm.get_library_version(); _encryption = Encryption(client: this); } catch (e) { Logs().e('Error initializing encryption $e'); diff --git a/test/client_test.dart b/test/client_test.dart index 98ceea80..628343a7 100644 --- a/test/client_test.dart +++ b/test/client_test.dart @@ -26,7 +26,6 @@ import 'package:collection/collection.dart'; import 'package:olm/olm.dart' as olm; import 'package:path/path.dart' show join; import 'package:test/test.dart'; -import 'package:vodozemac/vodozemac.dart' as vod; import 'package:matrix/matrix.dart'; import 'package:matrix/src/utils/client_init_exception.dart'; @@ -36,7 +35,7 @@ import 'fake_database.dart'; void main() { // key @test:fakeServer.notExisting const pickledOlmAccount = - 'N2v1MkIFGcl0mQpo2OCwSopxPQJ0wnl7oe7PKiT4141AijfdTIhRu+ceXzXKy3Kr00nLqXtRv7kid6hU4a+V0rfJWLL0Y51+3Rp/ORDVnQy+SSeo6Fn4FHcXrxifJEJ0djla5u98fBcJ8BSkhIDmtXRPi5/oJAvpiYn+8zMjFHobOeZUAxYR0VfQ9JzSYBsSovoQ7uFkNks1M4EDUvHtuyg3RxViwdNxs3718fyAqQ/VSwbXsY0Nl+qQbF+nlVGHenGqk5SuNl1P6e1PzZxcR0IfXA94Xij1Ob5gDv5YH4UCn9wRMG0abZsQP0YzpDM0FLaHSCyo9i5JD/vMlhH+nZWrgAzPPCTNGYewNV8/h3c+VyJh8ZTx/fVi6Yq46Fv+27Ga2ETRZ3Qn+Oyx6dLBjnBZ9iUvIhqpe2XqaGA1PopOz8iDnaZitw'; + 'huxcPifHlyiQsX7cZeMMITbka3hLeUT3ss6DLL6dV7knaD4wgAYK6gcWknkixnX8C5KMIyxzytxiNqAOhDFRE5NsET8hr2dQ8OvXX7M95eQ7/3dPi7FkPUIbvneTSGgJYNDxJdHsDJ8OBHZ3BoqUJFDbTzFfVJjEzN4G9XQwPDafZ2p5WyerOK8Twj/rvk5N+ERmkt1XgVLQl66we/BO1ugTeM3YpDHm5lTzFUitJGTIuuONsKG9mmzdAmVUJ9YIrSxwmOBdegbGA+LAl5acg5VOol3KxRgZUMJQRQ58zpBAs72oauHizv1QVoQ7uIUiCUeb9lym+TEjmApvhru/1CPHU90K5jHNZ57wb/4V9VsqBWuoNibzDWG35YTFLcx0o+1lrCIjm1QjuC0777G+L1HNw5wnppV3z/k0YujjuPS3wvOA30TjHg'; const identityKey = '7rvl3jORJkBiK4XX1e5TnGnqz068XfYJ0W++Ml63rgk'; const fingerprintKey = 'gjL//fyaFHADt9KBADGag8g7F8Up78B/K1zXeiEPLJo'; @@ -1752,7 +1751,10 @@ void main() { expect(error.homeserver, Uri.parse('https://test.server')); expect(error.olmAccount, 'abcd'); expect(error.userId, '@user:server'); - expect(error.toString(), 'Exception: BAD_ACCOUNT_KEY'); + expect( + error.originalException.runtimeType.toString(), + 'AnyhowException', + ); } await customClient.dispose(closeDatabase: true); }, diff --git a/test/encryption/encrypt_decrypt_to_device_test.dart b/test/encryption/encrypt_decrypt_to_device_test.dart index 649b87c7..1ba5ce6d 100644 --- a/test/encryption/encrypt_decrypt_to_device_test.dart +++ b/test/encryption/encrypt_decrypt_to_device_test.dart @@ -25,10 +25,8 @@ import '../fake_client.dart'; import '../fake_database.dart'; void main() async { - // key @othertest:fakeServer.notExisting - const otherPickledOlmAccount = - 'VWhVApbkcilKAEGppsPDf9nNVjaK8/IxT3asSR0sYg0S5KgbfE8vXEPwoiKBX2cEvwX3OessOBOkk+ZE7TTbjlrh/KEd31p8Wo+47qj0AP+Ky+pabnhi+/rTBvZy+gfzTqUfCxZrkzfXI9Op4JnP6gYmy7dVX2lMYIIs9WCO1jcmIXiXum5jnfXu1WLfc7PZtO2hH+k9CDKosOFaXRBmsu8k/BGXPSoWqUpvu6WpEG9t5STk4FeAzA'; final database = await getDatabase(); + group('Encrypt/Decrypt to-device messages', tags: 'olm', () { Logs().level = Level.error; @@ -64,7 +62,6 @@ void main() async { newHomeserver: otherClient.homeserver, newDeviceName: 'Text Matrix Client', newDeviceID: 'FOXDEVICE', - newOlmAccount: otherPickledOlmAccount, ); await otherClient.abortSync(); diff --git a/test/encryption/key_verification_test.dart b/test/encryption/key_verification_test.dart index 35b08ea4..aa191488 100644 --- a/test/encryption/key_verification_test.dart +++ b/test/encryption/key_verification_test.dart @@ -53,7 +53,7 @@ void main() async { // key @othertest:fakeServer.notExisting const otherPickledOlmAccount = - 'VWhVApbkcilKAEGppsPDf9nNVjaK8/IxT3asSR0sYg0S5KgbfE8vXEPwoiKBX2cEvwX3OessOBOkk+ZE7TTbjlrh/KEd31p8Wo+47qj0AP+Ky+pabnhi+/rTBvZy+gfzTqUfCxZrkzfXI9Op4JnP6gYmy7dVX2lMYIIs9WCO1jcmIXiXum5jnfXu1WLfc7PZtO2hH+k9CDKosOFaXRBmsu8k/BGXPSoWqUpvu6WpEG9t5STk4FeAzA'; + '0aFMkSgJhj0kVLxVnactRpl3L2kgIR8bAqICFtDkvp/mkinITZjr1Vh6Jy9FmJzvhLfFUtjU2j/2bqrFn61CSrvRbRaLP6rCFegGJHNGpVfw+c24NthCwGF/SN10aPjPo6yQ3er9bc42I6AmJz5HgyfU6C4bE+LdWrML93C0iEnmQN/SYHnS1KHPXNl6NpFGITggbZQ9jwHOFILWo8wzJ4iqlJtMrNaOOLAAB7By7Fbxl4xoNz2K+w'; late Client client1; late Client client2; diff --git a/test/encryption/olm_manager_test.dart b/test/encryption/olm_manager_test.dart index e3a8a9fa..2d0e4004 100644 --- a/test/encryption/olm_manager_test.dart +++ b/test/encryption/olm_manager_test.dart @@ -67,7 +67,7 @@ void main() { ); expect(sent['device_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, 33); expect(sent['fallback_keys'] != null, true); expect(sent['fallback_keys'].keys.length, 1); FakeMatrixApi.calledEndpoints.clear(); @@ -83,7 +83,7 @@ void main() { sent = json.decode( FakeMatrixApi.calledEndpoints['/client/v3/keys/upload']!.first, ); - expect(sent['one_time_keys'].keys.length, 46); + expect(sent['one_time_keys'].keys.length, 13); expect(sent['fallback_keys'].keys.length, 0); }); diff --git a/test/event_test.dart b/test/event_test.dart index d95114bd..7f244095 100644 --- a/test/event_test.dart +++ b/test/event_test.dart @@ -20,6 +20,7 @@ import 'dart:convert'; import 'dart:typed_data'; import 'package:test/test.dart'; +import 'package:vodozemac/vodozemac.dart' as vod; import 'package:matrix/encryption.dart'; import 'package:matrix/matrix.dart'; @@ -276,6 +277,15 @@ void main() async { }); test('sendAgain', () async { + try { + vodInit ??= vod.init( + wasmPath: './pkg/', + libraryPath: './rust/target/debug/', + ); + await vodInit; + } catch (_) { + Logs().d('Encryption via Vodozemac not enabled'); + } final matrix = Client( 'testclient', httpClient: FakeMatrixApi(), diff --git a/test/fake_client.dart b/test/fake_client.dart index 139c805c..b7a94277 100644 --- a/test/fake_client.dart +++ b/test/fake_client.dart @@ -16,8 +16,9 @@ * along with this program. If not, see . */ -import 'package:matrix/matrix.dart'; import 'package:vodozemac/vodozemac.dart' as vod; + +import 'package:matrix/matrix.dart'; import 'fake_database.dart'; const ssssPassphrase = 'nae7ahDiequ7ohniufah3ieS2je1thohX4xeeka7aixohsho9O'; @@ -25,7 +26,7 @@ const ssssKey = 'EsT9 RzbW VhPW yqNp cC7j ViiW 5TZB LuY4 ryyv 9guN Ysmr WDPH'; // key @test:fakeServer.notExisting const pickledOlmAccount = - 'N2v1MkIFGcl0mQpo2OCwSopxPQJ0wnl7oe7PKiT4141AijfdTIhRu+ceXzXKy3Kr00nLqXtRv7kid6hU4a+V0rfJWLL0Y51+3Rp/ORDVnQy+SSeo6Fn4FHcXrxifJEJ0djla5u98fBcJ8BSkhIDmtXRPi5/oJAvpiYn+8zMjFHobOeZUAxYR0VfQ9JzSYBsSovoQ7uFkNks1M4EDUvHtuyg3RxViwdNxs3718fyAqQ/VSwbXsY0Nl+qQbF+nlVGHenGqk5SuNl1P6e1PzZxcR0IfXA94Xij1Ob5gDv5YH4UCn9wRMG0abZsQP0YzpDM0FLaHSCyo9i5JD/vMlhH+nZWrgAzPPCTNGYewNV8/h3c+VyJh8ZTx/fVi6Yq46Fv+27Ga2ETRZ3Qn+Oyx6dLBjnBZ9iUvIhqpe2XqaGA1PopOz8iDnaZitw'; + 'huxcPifHlyiQsX7cZeMMITbka3hLeUT3ss6DLL6dV7knaD4wgAYK6gcWknkixnX8C5KMIyxzytxiNqAOhDFRE5NsET8hr2dQ8OvXX7M95eQ7/3dPi7FkPUIbvneTSGgJYNDxJdHsDJ8OBHZ3BoqUJFDbTzFfVJjEzN4G9XQwPDafZ2p5WyerOK8Twj/rvk5N+ERmkt1XgVLQl66we/BO1ugTeM3YpDHm5lTzFUitJGTIuuONsKG9mmzdAmVUJ9YIrSxwmOBdegbGA+LAl5acg5VOol3KxRgZUMJQRQ58zpBAs72oauHizv1QVoQ7uIUiCUeb9lym+TEjmApvhru/1CPHU90K5jHNZ57wb/4V9VsqBWuoNibzDWG35YTFLcx0o+1lrCIjm1QjuC0777G+L1HNw5wnppV3z/k0YujjuPS3wvOA30TjHg'; Future? vodInit; diff --git a/test/room_test.dart b/test/room_test.dart index eb5a2b25..0739afd0 100644 --- a/test/room_test.dart +++ b/test/room_test.dart @@ -22,7 +22,6 @@ import 'dart:math'; import 'dart:typed_data'; import 'package:test/test.dart'; -import 'package:vodozemac/vodozemac.dart' as vod; import 'package:matrix/matrix.dart'; import 'fake_client.dart'; diff --git a/test/user_test.dart b/test/user_test.dart index 8f778606..f732013f 100644 --- a/test/user_test.dart +++ b/test/user_test.dart @@ -17,6 +17,7 @@ */ import 'package:test/test.dart'; +import 'package:vodozemac/vodozemac.dart' as vod; import 'package:matrix/matrix.dart'; import 'fake_database.dart'; @@ -27,7 +28,17 @@ void main() async { late Client client; late Room room; late User user1, user2; + Future? vodInit; setUp(() async { + try { + vodInit ??= vod.init( + wasmPath: './pkg/', + libraryPath: './rust/target/debug/', + ); + await vodInit; + } catch (_) { + Logs().d('Encryption via Vodozemac not enabled'); + } client = Client( 'testclient', httpClient: FakeMatrixApi(),