diff --git a/commet/lib/client/matrix/components/voip_room/matrix_livekit_backend.dart b/commet/lib/client/matrix/components/voip_room/matrix_livekit_backend.dart index c4da607a9..8724201ba 100644 --- a/commet/lib/client/matrix/components/voip_room/matrix_livekit_backend.dart +++ b/commet/lib/client/matrix/components/voip_room/matrix_livekit_backend.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'package:commet/client/components/voip/voip_session.dart'; import 'package:commet/client/components/voip/webrtc_default_devices.dart'; +import 'package:commet/client/matrix/components/voip_room/matrix_livekit_encryption_key_provider.dart'; import 'package:commet/client/matrix/components/voip_room/matrix_livekit_voip_session.dart'; import 'package:commet/client/matrix/components/voip_room/matrix_voip_room_component.dart'; import 'package:commet/client/matrix/matrix_room.dart'; @@ -142,13 +143,24 @@ class MatrixLivekitBackend { final sfuUrl = data["url"]; Log.d("Got sfu: ${sfuUrl}"); final jwt = data["jwt"]; + lk.E2EEOptions? e2eeOptions; + + var provider = + await MatrixLivekitEncryptionKeyProvider.create(room.matrixRoom); + if (room.isE2EE) { + e2eeOptions = lk.E2EEOptions(keyProvider: provider); + } final roomOptions = lk.RoomOptions( adaptiveStream: true, dynacast: true, + e2eeOptions: e2eeOptions, ); final lkRoom = lk.Room(roomOptions: roomOptions); + + provider.lkRoom = lkRoom; + await lkRoom.prepareConnection(sfuUrl, jwt); final stateKey = "_${room.client.self!.identifier}_${room.matrixRoom.client.deviceID!}_m.call"; diff --git a/commet/lib/client/matrix/components/voip_room/matrix_livekit_encryption_key_provider.dart b/commet/lib/client/matrix/components/voip_room/matrix_livekit_encryption_key_provider.dart new file mode 100644 index 000000000..33e389751 --- /dev/null +++ b/commet/lib/client/matrix/components/voip_room/matrix_livekit_encryption_key_provider.dart @@ -0,0 +1,111 @@ +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:commet/debug/log.dart'; +import 'package:livekit_client/livekit_client.dart' hide KeyProvider; +import 'package:webrtc_interface/src/frame_cryptor.dart'; + +import 'package:matrix/matrix.dart' as mx; + +class MatrixLivekitEncryptionKeyProvider implements BaseKeyProvider { + mx.Room room; + Room? lkRoom; + + BaseKeyProvider _keyProvider; + + MatrixLivekitEncryptionKeyProvider(this._keyProvider, this.room) { + room.client.onToDeviceEvent.stream.listen(onToDeviceEvent); + } + + static Future create(mx.Room room) async { + var provider = await BaseKeyProvider.create( + sharedKey: false, + ratchetWindowSize: 10, + keyRingSize: 255, + failureTolerance: -1, + ); + + Log.i("Created livekit encryption key provider"); + + return MatrixLivekitEncryptionKeyProvider(provider, room); + } + + @override + Future exportKey(String participantId, int? keyIndex) { + return _keyProvider.exportKey(participantId, keyIndex); + } + + @override + Future exportSharedKey({int? keyIndex}) { + return _keyProvider.exportSharedKey(keyIndex: keyIndex); + } + + @override + int getLatestIndex(String participantId) { + return _keyProvider.getLatestIndex(participantId); + } + + @override + KeyProvider get keyProvider => _keyProvider.keyProvider; + + @override + KeyProviderOptions get options => _keyProvider.options; + + @override + Future ratchetKey(String participantId, int? keyIndex) { + return _keyProvider.ratchetKey(participantId, keyIndex); + } + + @override + Future ratchetSharedKey({int? keyIndex}) { + return _keyProvider.ratchetSharedKey(keyIndex: keyIndex); + } + + @override + Future setKey(String key, {String? participantId, int? keyIndex}) { + return _keyProvider.setKey(key, + participantId: participantId, keyIndex: keyIndex); + } + + @override + Future setRawKey(Uint8List key, + {String? participantId, int? keyIndex}) { + return _keyProvider.setRawKey(key, + participantId: participantId, keyIndex: keyIndex); + } + + @override + Future setSharedKey(String key, {int? keyIndex}) { + return _keyProvider.setSharedKey(key, keyIndex: keyIndex); + } + + @override + Future setSifTrailer(Uint8List trailer) { + return _keyProvider.setSifTrailer(trailer); + } + + @override + Uint8List? get sharedKey => _keyProvider.sharedKey; + + void onToDeviceEvent(mx.ToDeviceEvent event) { + Log.i( + "Received to device event: ${event.toJson()}", + ); + + if (event.type == "io.element.call.encryption_keys") { + var data = event.content["keys"] as Map; + + var index = data["index"]; + var key = data["key"] as String; + + var b = base64Decode(key); + + var deviceId = (event.content["member"] + as Map)["claimed_device_id"] as String; + + var participantId = event.senderId + ":" + deviceId; + + setRawKey(b, keyIndex: index, participantId: participantId); + } + } +} diff --git a/commet/lib/debug/log.dart b/commet/lib/debug/log.dart index e022dd4bd..7c9c08223 100644 --- a/commet/lib/debug/log.dart +++ b/commet/lib/debug/log.dart @@ -61,7 +61,6 @@ class Log { } }, errorCallback: (self, parent, zone, error, stackTrace) { - parent.print(zone, "ERROR CALLBACK"); parent.print(zone, error.toString()); parent.print(zone, stackTrace?.toString() ?? ""); String? info = diff --git a/commet/lib/main.dart b/commet/lib/main.dart index 6e735b9f1..7ab392aef 100644 --- a/commet/lib/main.dart +++ b/commet/lib/main.dart @@ -36,6 +36,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:intl/date_symbol_data_local.dart'; import 'package:intl/intl.dart'; +import 'package:logging/logging.dart'; import 'package:media_kit/media_kit.dart'; import 'package:provider/provider.dart'; import 'package:receive_intent/receive_intent.dart'; @@ -126,6 +127,12 @@ void main(List args) async { return; } + final format = DateFormat('HH:mm:ss'); + Logger.root.level = Level.FINEST; + Logger.root.onRecord.listen((record) { + print('${format.format(record.time)} ${record.level} : ${record.message}'); + }); + if (BuildConfig.RELEASE) { runZonedGuarded(appMain, Log.onError, zoneSpecification: Log.spec); } else { diff --git a/commet/lib/ui/pages/settings/categories/room/emoji_packs/bulk_import_view.dart b/commet/lib/ui/pages/settings/categories/room/emoji_packs/bulk_import_view.dart index ae82268cb..acd550668 100644 --- a/commet/lib/ui/pages/settings/categories/room/emoji_packs/bulk_import_view.dart +++ b/commet/lib/ui/pages/settings/categories/room/emoji_packs/bulk_import_view.dart @@ -8,7 +8,7 @@ import 'package:file_picker/file_picker.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; -import 'package:signal_sticker_api/signal_sticker_api.dart'; + import 'package:tiamat/atoms/panel.dart'; import 'package:path/path.dart' as p; @@ -131,8 +131,7 @@ class _EmoticonBulkImportDialogState extends State { } Future loadSignalPack(Uri uri) async { - var client = SignalStickerClient( - host: preferences.proxyUrl, rootPath: "/proxy/signal", useHttps: false); + dynamic client = null; var packInfo = client.getPackFromUri(uri); var pack = await client.getPack(packInfo!); _packNameEditor.text = pack!.name; diff --git a/commet/pubspec.yaml b/commet/pubspec.yaml index a013bef93..609caddb8 100644 --- a/commet/pubspec.yaml +++ b/commet/pubspec.yaml @@ -16,7 +16,7 @@ dependencies: crypto: ^3.0.2 desktop_drop: ^0.4.1 desktop_notifications: ^0.6.3 - device_info_plus: ^11.3.0 + device_info_plus: ^12.2.0 flutter_background_service: ^5.0.5 flutter_blurhash: ^0.8.2 flutter_markdown: ^0.6.9+1 @@ -75,10 +75,6 @@ dependencies: url: https://github.com/commetchat/matrix-dart-sdk-drift-db.git ref: upstream-v1.1.1+patch.3 - signal_sticker_api: - git: - url: https://github.com/commetchat/signal-sticker-api.git - ref: f3295318c27d420f195e00164f104ead9aaa6209 starfield: git: https://github.com/lagmachine-com/starfield.git sqlite3_flutter_libs: ^0.5.23 @@ -87,8 +83,11 @@ dependencies: archive: ^3.6.1 exif: ^3.3.0 image: ^4.2.0 - livekit_client: ^2.5.1 - flutter_webrtc: ^1.2.0 + livekit_client: + git: + url: https://github.com/commetchat/livekit-client-sdk-flutter.git + ref: hkdf + flutter_webrtc: 1.2.1 file_picker: ^10.2.0 flutter_web_auth_2: ^4.1.0 receive_intent: @@ -121,6 +120,7 @@ dependencies: canonical_json: ^1.1.2 cryptography: ^2.9.0 crop_image: ^1.0.17 + logging: ^1.3.0 dependency_overrides: analyzer: ^7.3.0 diff --git a/pubspec.lock b/pubspec.lock index baef929ed..00f2d5354 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -17,6 +17,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.7.1" + adaptive_number: + dependency: transitive + description: + name: adaptive_number + sha256: "3a567544e9b5c9c803006f51140ad544aedc79604fd4f3f2c1380003f97c1d77" + url: "https://pub.dev" + source: hosted + version: "1.0.0" analyzer: dependency: "direct overridden" description: @@ -230,10 +238,10 @@ packages: dependency: transitive description: name: connectivity_plus - sha256: b5e72753cf63becce2c61fd04dfe0f1c430cc5278b53a1342dc5ad839eab29ec + sha256: "33bae12a398f841c6cda09d1064212957265869104c478e5ad51e2fb26c3973c" url: "https://pub.dev" source: hosted - version: "6.1.5" + version: "7.0.0" connectivity_plus_platform_interface: dependency: transitive description: @@ -314,6 +322,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.8" + dart_jsonwebtoken: + dependency: transitive + description: + name: dart_jsonwebtoken + sha256: "0de65691c1d736e9459f22f654ddd6fd8368a271d4e41aa07e53e6301eff5075" + url: "https://pub.dev" + source: hosted + version: "3.3.1" dart_style: dependency: transitive description: @@ -375,10 +391,10 @@ packages: dependency: transitive description: name: device_info_plus - sha256: "98f28b42168cc509abc92f88518882fd58061ea372d7999aecc424345c7bff6a" + sha256: "4df8babf73058181227e18b08e6ea3520cf5fc5d796888d33b7cb0f33f984b7c" url: "https://pub.dev" source: hosted - version: "11.5.0" + version: "12.3.0" device_info_plus_platform_interface: dependency: transitive description: @@ -420,6 +436,14 @@ packages: url: "https://github.com/Airyzz/material-flutter-packages.git" source: git version: "1.7.0" + ed25519_edwards: + dependency: transitive + description: + name: ed25519_edwards + sha256: "6ce0112d131327ec6d42beede1e5dfd526069b18ad45dcf654f15074ad9276cd" + url: "https://pub.dev" + source: hosted + version: "0.3.1" enhanced_enum: dependency: transitive description: @@ -741,10 +765,10 @@ packages: dependency: transitive description: name: flutter_webrtc - sha256: "16ca9e30d428bae3dd32933e875c9f67c5843d1fa726c37cf1fc479eb9294549" + sha256: "71a38363a5b50603e405c275f30de2eb90f980b0cc94b0e1e9d8b9d6a6b03bf0" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.2.1" frontend_server_client: dependency: transitive description: @@ -1078,11 +1102,12 @@ packages: livekit_client: dependency: transitive description: - name: livekit_client - sha256: ddb4467d306be472898b2459c87768121aba030173b3664ef367f7f7f4c96897 - url: "https://pub.dev" - source: hosted - version: "2.5.3" + path: "." + ref: hkdf + resolved-ref: f05718ecb7f44adb568954e8f18a24bd6beed246 + url: "https://github.com/commetchat/livekit-client-sdk-flutter.git" + source: git + version: "2.6.1" logger: dependency: transitive description: @@ -1430,6 +1455,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.8" + pointycastle: + dependency: transitive + description: + name: pointycastle + sha256: "92aa3841d083cc4b0f4709b5c74fd6409a3e6ba833ffc7dc6a8fee096366acf5" + url: "https://pub.dev" + source: hosted + version: "4.0.0" pool: dependency: transitive description: @@ -1450,10 +1483,10 @@ packages: dependency: transitive description: name: protobuf - sha256: de9c9eb2c33f8e933a42932fe1dc504800ca45ebc3d673e6ed7f39754ee4053e + sha256: "75ec242d22e950bdcc79ee38dd520ce4ee0bc491d7fadc4ea47694604d22bf06" url: "https://pub.dev" source: hosted - version: "4.2.0" + version: "6.0.0" provider: dependency: transitive description: @@ -1703,15 +1736,6 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.0" - signal_sticker_api: - dependency: transitive - description: - path: "." - ref: f3295318c27d420f195e00164f104ead9aaa6209 - resolved-ref: f3295318c27d420f195e00164f104ead9aaa6209 - url: "https://github.com/commetchat/signal-sticker-api.git" - source: git - version: "1.0.0" sky_engine: dependency: transitive description: flutter