From 46bb6f9895b5862a3036afb7bd22955287325611 Mon Sep 17 00:00:00 2001 From: kauzu Date: Sun, 26 Jun 2022 13:34:45 +0200 Subject: [PATCH 1/9] apk buildfix / update share_plus dependency --- openhaystack-mobile/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openhaystack-mobile/pubspec.yaml b/openhaystack-mobile/pubspec.yaml index 7caadf5..2b1779a 100644 --- a/openhaystack-mobile/pubspec.yaml +++ b/openhaystack-mobile/pubspec.yaml @@ -57,7 +57,7 @@ dependencies: # Sharing receive_sharing_intent: ^1.4.5 - share_plus: ^3.0.4 + share_plus: ^4.0.4 url_launcher: ^6.0.17 path_provider: ^2.0.8 maps_launcher: ^2.0.1 From 7d095322396d33aa088a28dec4dfa3092670f192 Mon Sep 17 00:00:00 2001 From: kauzu Date: Sun, 26 Jun 2022 13:40:56 +0200 Subject: [PATCH 2/9] apk buildfix / update pubspec --- openhaystack-mobile/pubspec.lock | 120 +++++++++++++++---------------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/openhaystack-mobile/pubspec.lock b/openhaystack-mobile/pubspec.lock index 1b7d8a6..237b3e7 100644 --- a/openhaystack-mobile/pubspec.lock +++ b/openhaystack-mobile/pubspec.lock @@ -7,14 +7,14 @@ packages: name: archive url: "https://pub.dartlang.org" source: hosted - version: "3.2.1" + version: "3.3.0" args: dependency: transitive description: name: args url: "https://pub.dartlang.org" source: hosted - version: "2.3.0" + version: "2.3.1" async: dependency: transitive description: @@ -56,35 +56,35 @@ packages: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.15.0" + version: "1.16.0" convert: dependency: transitive description: name: convert url: "https://pub.dartlang.org" source: hosted - version: "3.0.1" + version: "3.0.2" crypto: dependency: transitive description: name: crypto url: "https://pub.dartlang.org" source: hosted - version: "3.0.1" + version: "3.0.2" fake_async: dependency: transitive description: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.0" ffi: dependency: transitive description: name: ffi url: "https://pub.dartlang.org" source: hosted - version: "1.1.2" + version: "1.2.1" file: dependency: transitive description: @@ -98,7 +98,7 @@ packages: name: file_picker url: "https://pub.dartlang.org" source: hosted - version: "4.4.0" + version: "4.6.1" flutter: dependency: "direct main" description: flutter @@ -117,7 +117,7 @@ packages: name: flutter_launcher_icons url: "https://pub.dartlang.org" source: hosted - version: "0.9.2" + version: "0.9.3" flutter_lints: dependency: "direct dev" description: @@ -138,7 +138,7 @@ packages: name: flutter_plugin_android_lifecycle url: "https://pub.dartlang.org" source: hosted - version: "2.0.5" + version: "2.0.6" flutter_secure_storage: dependency: "direct main" description: @@ -187,7 +187,7 @@ packages: name: flutter_slidable url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.0" flutter_test: dependency: "direct dev" description: flutter @@ -204,7 +204,7 @@ packages: name: geocoding url: "https://pub.dartlang.org" source: hosted - version: "2.0.2" + version: "2.0.4" geocoding_platform_interface: dependency: transitive description: @@ -225,14 +225,14 @@ packages: name: http_parser url: "https://pub.dartlang.org" source: hosted - version: "4.0.0" + version: "4.0.1" image: dependency: transitive description: name: image url: "https://pub.dartlang.org" source: hosted - version: "3.1.3" + version: "3.2.0" intl: dependency: transitive description: @@ -246,7 +246,7 @@ packages: name: js url: "https://pub.dartlang.org" source: hosted - version: "0.6.3" + version: "0.6.4" latlong2: dependency: transitive description: @@ -274,7 +274,7 @@ packages: name: location url: "https://pub.dartlang.org" source: hosted - version: "4.3.0" + version: "4.4.0" location_platform_interface: dependency: transitive description: @@ -309,7 +309,7 @@ packages: name: material_color_utilities url: "https://pub.dartlang.org" source: hosted - version: "0.1.3" + version: "0.1.4" meta: dependency: transitive description: @@ -330,7 +330,7 @@ packages: name: mime url: "https://pub.dartlang.org" source: hosted - version: "1.0.1" + version: "1.0.2" nested: dependency: transitive description: @@ -344,63 +344,63 @@ packages: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.8.0" + version: "1.8.1" path_provider: dependency: "direct main" description: name: path_provider url: "https://pub.dartlang.org" source: hosted - version: "2.0.9" + version: "2.0.11" path_provider_android: dependency: transitive description: name: path_provider_android url: "https://pub.dartlang.org" source: hosted - version: "2.0.11" + version: "2.0.15" path_provider_ios: dependency: transitive description: name: path_provider_ios url: "https://pub.dartlang.org" source: hosted - version: "2.0.7" + version: "2.0.10" path_provider_linux: dependency: transitive description: name: path_provider_linux url: "https://pub.dartlang.org" source: hosted - version: "2.1.5" + version: "2.1.7" path_provider_macos: dependency: transitive description: name: path_provider_macos url: "https://pub.dartlang.org" source: hosted - version: "2.0.5" + version: "2.0.6" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.0.3" + version: "2.0.4" path_provider_windows: dependency: transitive description: name: path_provider_windows url: "https://pub.dartlang.org" source: hosted - version: "2.0.5" + version: "2.0.7" petitparser: dependency: transitive description: name: petitparser url: "https://pub.dartlang.org" source: hosted - version: "4.4.0" + version: "5.0.0" platform: dependency: transitive description: @@ -421,7 +421,7 @@ packages: name: pointycastle url: "https://pub.dartlang.org" source: hosted - version: "3.5.1" + version: "3.6.0" positioned_tap_detector_2: dependency: transitive description: @@ -449,14 +449,14 @@ packages: name: provider url: "https://pub.dartlang.org" source: hosted - version: "6.0.2" + version: "6.0.3" quiver: dependency: transitive description: name: quiver url: "https://pub.dartlang.org" source: hosted - version: "3.0.1+1" + version: "3.1.0" receive_sharing_intent: dependency: "direct main" description: @@ -470,77 +470,77 @@ packages: name: share_plus url: "https://pub.dartlang.org" source: hosted - version: "3.1.0" + version: "4.0.9" share_plus_linux: dependency: transitive description: name: share_plus_linux url: "https://pub.dartlang.org" source: hosted - version: "2.0.4" + version: "3.0.0" share_plus_macos: dependency: transitive description: name: share_plus_macos url: "https://pub.dartlang.org" source: hosted - version: "2.0.2" + version: "3.0.1" share_plus_platform_interface: dependency: transitive description: name: share_plus_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.0.1" + version: "3.0.3" share_plus_web: dependency: transitive description: name: share_plus_web url: "https://pub.dartlang.org" source: hosted - version: "2.0.4" + version: "3.0.1" share_plus_windows: dependency: transitive description: name: share_plus_windows url: "https://pub.dartlang.org" source: hosted - version: "2.0.3" + version: "3.0.1" shared_preferences: dependency: "direct main" description: name: shared_preferences url: "https://pub.dartlang.org" source: hosted - version: "2.0.13" + version: "2.0.15" shared_preferences_android: dependency: transitive description: name: shared_preferences_android url: "https://pub.dartlang.org" source: hosted - version: "2.0.10" + version: "2.0.12" shared_preferences_ios: dependency: transitive description: name: shared_preferences_ios url: "https://pub.dartlang.org" source: hosted - version: "2.0.9" + version: "2.1.1" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.1.1" shared_preferences_macos: dependency: transitive description: name: shared_preferences_macos url: "https://pub.dartlang.org" source: hosted - version: "2.0.3" + version: "2.0.4" shared_preferences_platform_interface: dependency: transitive description: @@ -554,14 +554,14 @@ packages: name: shared_preferences_web url: "https://pub.dartlang.org" source: hosted - version: "2.0.3" + version: "2.0.4" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.1.1" sky_engine: dependency: transitive description: flutter @@ -573,7 +573,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.1" + version: "1.8.2" stack_trace: dependency: transitive description: @@ -608,7 +608,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.4.8" + version: "0.4.9" transparent_image: dependency: transitive description: @@ -629,7 +629,7 @@ packages: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.3.0" + version: "1.3.1" unicode: dependency: transitive description: @@ -643,70 +643,70 @@ packages: name: url_launcher url: "https://pub.dartlang.org" source: hosted - version: "6.0.20" + version: "6.1.4" url_launcher_android: dependency: transitive description: name: url_launcher_android url: "https://pub.dartlang.org" source: hosted - version: "6.0.14" + version: "6.0.17" url_launcher_ios: dependency: transitive description: name: url_launcher_ios url: "https://pub.dartlang.org" source: hosted - version: "6.0.14" + version: "6.0.17" url_launcher_linux: dependency: transitive description: name: url_launcher_linux url: "https://pub.dartlang.org" source: hosted - version: "3.0.0" + version: "3.0.1" url_launcher_macos: dependency: transitive description: name: url_launcher_macos url: "https://pub.dartlang.org" source: hosted - version: "3.0.0" + version: "3.0.1" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.0.5" + version: "2.1.0" url_launcher_web: dependency: transitive description: name: url_launcher_web url: "https://pub.dartlang.org" source: hosted - version: "2.0.7" + version: "2.0.12" url_launcher_windows: dependency: transitive description: name: url_launcher_windows url: "https://pub.dartlang.org" source: hosted - version: "3.0.0" + version: "3.0.1" vector_math: dependency: transitive description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.1.2" win32: dependency: transitive description: name: win32 url: "https://pub.dartlang.org" source: hosted - version: "2.3.6" + version: "2.6.1" wkt_parser: dependency: transitive description: @@ -727,14 +727,14 @@ packages: name: xml url: "https://pub.dartlang.org" source: hosted - version: "5.3.1" + version: "6.1.0" yaml: dependency: transitive description: name: yaml url: "https://pub.dartlang.org" source: hosted - version: "3.1.0" + version: "3.1.1" sdks: - dart: ">=2.14.0 <3.0.0" - flutter: ">=2.5.0" + dart: ">=2.17.0 <3.0.0" + flutter: ">=3.0.0" From 05a634fd1e0b29f828aff845a65cdc101f931acf Mon Sep 17 00:00:00 2001 From: kauzu Date: Sun, 26 Jun 2022 13:42:23 +0200 Subject: [PATCH 3/9] reports_fetcher url add semilolon --- openhaystack-mobile/lib/findMy/reports_fetcher.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openhaystack-mobile/lib/findMy/reports_fetcher.dart b/openhaystack-mobile/lib/findMy/reports_fetcher.dart index 8bffff8..f0a7b10 100644 --- a/openhaystack-mobile/lib/findMy/reports_fetcher.dart +++ b/openhaystack-mobile/lib/findMy/reports_fetcher.dart @@ -3,7 +3,7 @@ import 'dart:convert'; import 'package:http/http.dart' as http; class ReportsFetcher { - static const _seemooEndpoint = "https://add-your-proxy-server-here/getLocationReports" + static const _seemooEndpoint = "https://add-your-proxy-server-here/getLocationReports"; /// Fetches the location reports corresponding to the given hashed advertisement /// key. From f2f9adcf280d40d36baaaa462aaba70d65e67e00 Mon Sep 17 00:00:00 2001 From: kauzu Date: Tue, 28 Jun 2022 23:38:01 +0200 Subject: [PATCH 4/9] Silence linux beacon --- Firmware/Linux_HCI/HCI.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Firmware/Linux_HCI/HCI.py b/Firmware/Linux_HCI/HCI.py index d38878f..888d075 100755 --- a/Firmware/Linux_HCI/HCI.py +++ b/Firmware/Linux_HCI/HCI.py @@ -32,7 +32,7 @@ def bytes_to_strarray(bytes_, with_prefix=False): def run_hci_cmd(cmd, hci="hci0", wait=1): cmd_ = ["hcitool", "-i", hci, "cmd"] cmd_ += cmd - print(cmd_) + #print(cmd_) subprocess.run(cmd_) if wait > 0: time.sleep(wait) @@ -46,9 +46,9 @@ def start_advertising(key, interval_ms=2000): adv[7:29] = key[6:28] adv[29] = key[0] >> 6 - print(f"key ({len(key):2}) {key.hex()}") - print(f"address ({len(addr):2}) {addr.hex()}") - print(f"payload ({len(adv):2}) {adv.hex()}") + #print(f"key ({len(key):2}) {key.hex()}") + #print(f"address ({len(addr):2}) {addr.hex()}") + #print(f"payload ({len(adv):2}) {adv.hex()}") # Set BLE address run_hci_cmd(["0x3f", "0x001"] + bytes_to_strarray(addr, with_prefix=True)[::-1]) From fb209e8930a19e91180a08fb113b71204c81e941 Mon Sep 17 00:00:00 2001 From: kauzu Date: Tue, 28 Jun 2022 23:55:03 +0200 Subject: [PATCH 5/9] Permanent advertising --- Firmware/Linux_HCI/HCI.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Firmware/Linux_HCI/HCI.py b/Firmware/Linux_HCI/HCI.py index 888d075..e50c62f 100755 --- a/Firmware/Linux_HCI/HCI.py +++ b/Firmware/Linux_HCI/HCI.py @@ -37,6 +37,10 @@ def run_hci_cmd(cmd, hci="hci0", wait=1): if wait > 0: time.sleep(wait) +def run_hciconf_leadv_3(hci="hci0"): + #EDIT: the above command makes the advertised service connectable. If you don't want to allow connections, change it to $ sudo hciconfig hci0 leadv 3 + cmd_ = ["hciconfig", hci, "leadv", "3"] + subprocess.run(cmd_) def start_advertising(key, interval_ms=2000): addr = bytearray(key[:6]) @@ -53,7 +57,7 @@ def start_advertising(key, interval_ms=2000): # Set BLE address run_hci_cmd(["0x3f", "0x001"] + bytes_to_strarray(addr, with_prefix=True)[::-1]) subprocess.run(["systemctl", "restart", "bluetooth"]) - time.sleep(1) + time.sleep(3) # Set BLE advertisement payload run_hci_cmd(["0x08", "0x0008"] + [format(len(adv), "x")] + bytes_to_strarray(adv)) @@ -70,6 +74,8 @@ def start_advertising(key, interval_ms=2000): # Start BLE advertising run_hci_cmd(["0x08", "0x000a"] + ["01"], wait=0) + run_hciconf_leadv_3() + def main(args): parser = argparse.ArgumentParser() From 482aad8d394c532dbc3d31393b9d9c8e06cb89f2 Mon Sep 17 00:00:00 2001 From: kauzu Date: Wed, 29 Jun 2022 17:34:56 +0200 Subject: [PATCH 6/9] remove isolate --- .../lib/findMy/decrypt_reports.dart | 31 ++++---- .../lib/findMy/find_my_controller.dart | 72 ++++++++++--------- 2 files changed, 56 insertions(+), 47 deletions(-) diff --git a/openhaystack-mobile/lib/findMy/decrypt_reports.dart b/openhaystack-mobile/lib/findMy/decrypt_reports.dart index f8fefa4..f1a0276 100644 --- a/openhaystack-mobile/lib/findMy/decrypt_reports.dart +++ b/openhaystack-mobile/lib/findMy/decrypt_reports.dart @@ -1,5 +1,4 @@ import 'dart:convert'; -import 'dart:isolate'; import 'dart:typed_data'; import 'package:pointycastle/export.dart'; @@ -19,9 +18,8 @@ class DecryptReports { _decodeTimeAndConfidence(payloadData, report); - final privateKey = ECPrivateKey( - pc_utils.decodeBigIntWithSign(1, key), - curveDomainParam); + final privateKey = + ECPrivateKey(pc_utils.decodeBigIntWithSign(1, key), curveDomainParam); final decodePoint = curveDomainParam.curve.decodePoint(ephemeralKeyBytes); final ephemeralPublicKey = ECPublicKey(decodePoint, curveDomainParam); @@ -36,9 +34,10 @@ class DecryptReports { } /// Decodes the unencrypted timestamp and confidence - static void _decodeTimeAndConfidence(Uint8List payloadData, FindMyReport report) { - final seenTimeStamp = payloadData.sublist(0, 4).buffer.asByteData() - .getInt32(0, Endian.big); + static void _decodeTimeAndConfidence( + Uint8List payloadData, FindMyReport report) { + final seenTimeStamp = + payloadData.sublist(0, 4).buffer.asByteData().getInt32(0, Endian.big); final timestamp = DateTime(2001).add(Duration(seconds: seenTimeStamp)); final confidence = payloadData.elementAt(4); report.timestamp = timestamp; @@ -47,11 +46,12 @@ class DecryptReports { /// Performs an Elliptic Curve Diffie-Hellman with the given keys. /// Returns the derived raw key data. - static Uint8List _ecdh(ECPublicKey ephemeralPublicKey, ECPrivateKey privateKey) { + static Uint8List _ecdh( + ECPublicKey ephemeralPublicKey, ECPrivateKey privateKey) { final sharedKey = ephemeralPublicKey.Q! * privateKey.d; - final sharedKeyBytes = pc_utils.encodeBigIntAsUnsigned( - sharedKey!.x!.toBigInteger()!); - print("Isolate:${Isolate.current.hashCode}: Shared Key (shared secret): ${base64Encode(sharedKeyBytes)}"); + final sharedKeyBytes = + pc_utils.encodeBigIntAsUnsigned(sharedKey!.x!.toBigInteger()!); + print("Shared Key (shared secret): ${base64Encode(sharedKeyBytes)}"); return sharedKeyBytes; } @@ -60,7 +60,6 @@ class DecryptReports { /// the resulting [FindMyLocationReport]. static FindMyLocationReport _decodePayload( Uint8List payload, FindMyReport report) { - final latitude = payload.buffer.asByteData(0, 4).getUint32(0, Endian.big); final longitude = payload.buffer.asByteData(4, 4).getUint32(0, Endian.big); final accuracy = payload.buffer.asByteData(8, 1).getUint8(0); @@ -80,8 +79,10 @@ class DecryptReports { final iv = symmetricKey.sublist(16, symmetricKey.length); final aesGcm = GCMBlockCipher(AESEngine()) - ..init(false, AEADParameters(KeyParameter(decryptionKey), - tag.lengthInBytes * 8, iv, tag)); + ..init( + false, + AEADParameters( + KeyParameter(decryptionKey), tag.lengthInBytes * 8, iv, tag)); final plainText = Uint8List(cipherText.length); var offset = 0; @@ -109,7 +110,7 @@ class DecryptReports { Uint8List out = Uint8List(shaDigest.digestSize); shaDigest.doFinal(out, 0); - print("Isolate:${Isolate.current.hashCode}: Derived key: ${base64Encode(out)}"); + print("Derived key: ${base64Encode(out)}"); return out; } } diff --git a/openhaystack-mobile/lib/findMy/find_my_controller.dart b/openhaystack-mobile/lib/findMy/find_my_controller.dart index 1b1abe4..13e03d9 100644 --- a/openhaystack-mobile/lib/findMy/find_my_controller.dart +++ b/openhaystack-mobile/lib/findMy/find_my_controller.dart @@ -1,6 +1,5 @@ import 'dart:collection'; import 'dart:convert'; -import 'dart:isolate'; import 'dart:typed_data'; import 'package:flutter/foundation.dart'; @@ -14,13 +13,14 @@ import 'package:openhaystack_mobile/findMy/reports_fetcher.dart'; class FindMyController { static const _storage = FlutterSecureStorage(); - static final ECCurve_secp224r1 _curveParams = ECCurve_secp224r1(); + static final ECCurve_secp224r1 _curveParams = ECCurve_secp224r1(); static HashMap _keyCache = HashMap(); /// Starts a new [Isolate], fetches and decrypts all location reports /// for the given [FindMyKeyPair]. /// Returns a list of [FindMyLocationReport]'s. - static Future> computeResults(FindMyKeyPair keyPair) async{ + static Future> computeResults( + FindMyKeyPair keyPair) async { await _loadPrivateKey(keyPair); return compute(_getListedReportResults, keyPair); } @@ -28,11 +28,14 @@ class FindMyController { /// Fetches and decrypts the location reports for the given /// [FindMyKeyPair] from apples FindMy Network. /// Returns a list of [FindMyLocationReport]. - static Future> _getListedReportResults(FindMyKeyPair keyPair) async{ + static Future> _getListedReportResults( + FindMyKeyPair keyPair) async { List results = []; - final jsonResults = await ReportsFetcher.fetchLocationReports(keyPair.getHashedAdvertisementKey()); + final jsonResults = await ReportsFetcher.fetchLocationReports( + keyPair.getHashedAdvertisementKey()); for (var result in jsonResults) { - results.add(await _decryptResult(result, keyPair, keyPair.privateKeyBase64!)); + results.add( + await _decryptResult(result, keyPair, keyPair.privateKeyBase64!)); } return results; } @@ -43,7 +46,8 @@ class FindMyController { String? privateKey; if (!_keyCache.containsKey(keyPair.hashedPublicKey)) { privateKey = await _storage.read(key: keyPair.hashedPublicKey); - final newKey = _keyCache.putIfAbsent(keyPair.hashedPublicKey, () => privateKey); + final newKey = + _keyCache.putIfAbsent(keyPair.hashedPublicKey, () => privateKey); assert(newKey == privateKey); } else { privateKey = _keyCache[keyPair.hashedPublicKey]; @@ -55,27 +59,29 @@ class FindMyController { static ECPublicKey _derivePublicKey(ECPrivateKey privateKey) { final pk = _curveParams.G * privateKey.d; final publicKey = ECPublicKey(pk, _curveParams); - print("Isolate:${Isolate.current.hashCode}: Point Data: ${base64Encode(publicKey.Q!.getEncoded(false))}"); + print("Point Data: ${base64Encode(publicKey.Q!.getEncoded(false))}"); return publicKey; } /// Decrypts the encrypted reports with the given [FindMyKeyPair] and private key. /// Returns the decrypted report as a [FindMyLocationReport]. - static Future _decryptResult(dynamic result, FindMyKeyPair keyPair, String privateKey) async { - assert (result["id"]! == keyPair.getHashedAdvertisementKey(), - "Returned FindMyReport hashed key != requested hashed key"); - - final unixTimestampInMillis = result["datePublished"]; - final datePublished = DateTime.fromMillisecondsSinceEpoch(unixTimestampInMillis); + static Future _decryptResult( + dynamic result, FindMyKeyPair keyPair, String privateKey) async { + assert(result["id"]! == keyPair.getHashedAdvertisementKey(), + "Returned FindMyReport hashed key != requested hashed key"); + + final unixTimestampInMillis = result["datePublished"]; + final datePublished = + DateTime.fromMillisecondsSinceEpoch(unixTimestampInMillis); FindMyReport report = FindMyReport( datePublished, base64Decode(result["payload"]), keyPair.getHashedAdvertisementKey(), result["statusCode"]); - FindMyLocationReport decryptedReport = await DecryptReports - .decryptReport(report, base64Decode(privateKey)); + FindMyLocationReport decryptedReport = + await DecryptReports.decryptReport(report, base64Decode(privateKey)); return decryptedReport; } @@ -86,10 +92,12 @@ class FindMyController { final privateKeyBase64 = await _storage.read(key: base64HashedPublicKey); ECPrivateKey privateKey = ECPrivateKey( - pc_utils.decodeBigIntWithSign(1, base64Decode(privateKeyBase64!)), _curveParams); + pc_utils.decodeBigIntWithSign(1, base64Decode(privateKeyBase64!)), + _curveParams); ECPublicKey publicKey = _derivePublicKey(privateKey); - return FindMyKeyPair(publicKey, base64HashedPublicKey, privateKey, DateTime.now(), -1); + return FindMyKeyPair( + publicKey, base64HashedPublicKey, privateKey, DateTime.now(), -1); } /// Imports a base64 encoded private key to the local [FlutterSecureStorage]. @@ -101,14 +109,11 @@ class FindMyController { final ECPublicKey publicKey = _derivePublicKey(privateKey); final hashedPublicKey = getHashedPublicKey(publicKey: publicKey); final keyPair = FindMyKeyPair( - publicKey, - hashedPublicKey, - privateKey, - DateTime.now(), - -1); - - await _storage.write(key: hashedPublicKey, value: keyPair.getBase64PrivateKey()); - + publicKey, hashedPublicKey, privateKey, DateTime.now(), -1); + + await _storage.write( + key: hashedPublicKey, value: keyPair.getBase64PrivateKey()); + return keyPair; } @@ -117,16 +122,18 @@ class FindMyController { static Future generateKeyPair() async { final ecCurve = ECCurve_secp224r1(); final secureRandom = SecureRandom('Fortuna') - ..seed(KeyParameter( - Platform.instance.platformEntropySource().getBytes(32))); + ..seed( + KeyParameter(Platform.instance.platformEntropySource().getBytes(32))); ECKeyGenerator keyGen = ECKeyGenerator() - ..init(ParametersWithRandom(ECKeyGeneratorParameters(ecCurve), secureRandom)); + ..init(ParametersWithRandom( + ECKeyGeneratorParameters(ecCurve), secureRandom)); final newKeyPair = keyGen.generateKeyPair(); final ECPublicKey publicKey = newKeyPair.publicKey as ECPublicKey; final ECPrivateKey privateKey = newKeyPair.privateKey as ECPrivateKey; final hashedKey = getHashedPublicKey(publicKey: publicKey); - final keyPair = FindMyKeyPair(publicKey, hashedKey, privateKey, DateTime.now(), -1); + final keyPair = + FindMyKeyPair(publicKey, hashedKey, privateKey, DateTime.now(), -1); await _storage.write(key: hashedKey, value: keyPair.getBase64PrivateKey()); return keyPair; @@ -135,7 +142,8 @@ class FindMyController { /// Returns hashed, base64 encoded public key for given [publicKeyBytes] /// or for an [ECPublicKey] object [publicKey], if [publicKeyBytes] equals null. /// Returns the base64 encoded hashed public key as a [String]. - static String getHashedPublicKey({Uint8List? publicKeyBytes, ECPublicKey? publicKey}) { + static String getHashedPublicKey( + {Uint8List? publicKeyBytes, ECPublicKey? publicKey}) { var pkBytes = publicKeyBytes ?? publicKey!.Q!.getEncoded(false); final shaDigest = SHA256Digest(); shaDigest.update(pkBytes, 0, pkBytes.lengthInBytes); @@ -143,4 +151,4 @@ class FindMyController { shaDigest.doFinal(out, 0); return base64Encode(out); } -} \ No newline at end of file +} From 955022fde610a2a30574e62be0f943ee2944016b Mon Sep 17 00:00:00 2001 From: kauzu Date: Wed, 29 Jun 2022 17:55:27 +0200 Subject: [PATCH 7/9] ReceiveSharingIntent only on Android/IOS --- openhaystack-mobile/lib/main.dart | 32 ++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/openhaystack-mobile/lib/main.dart b/openhaystack-mobile/lib/main.dart index 196275b..7f458b8 100644 --- a/openhaystack-mobile/lib/main.dart +++ b/openhaystack-mobile/lib/main.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'dart:io'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:receive_sharing_intent/receive_sharing_intent.dart'; @@ -33,7 +34,7 @@ class MyApp extends StatelessWidget { primarySwatch: Colors.blue, ), darkTheme: ThemeData.dark(), - home: const AppLayout(), + home: const AppLayout(), ), ); } @@ -53,16 +54,20 @@ class _AppLayoutState extends State { initState() { super.initState(); - _intentDataStreamSubscription = ReceiveSharingIntent.getMediaStream() - .listen(handleFileSharingIntent, onError: print); - ReceiveSharingIntent.getInitialMedia() - .then(handleFileSharingIntent); + if (!kIsWeb && (Platform.isAndroid || Platform.isIOS)) { + //Only supported on this platforms according to + //https://pub.dev/packages/receive_sharing_intent + _intentDataStreamSubscription = ReceiveSharingIntent.getMediaStream() + .listen(handleFileSharingIntent, onError: print); + ReceiveSharingIntent.getInitialMedia().then(handleFileSharingIntent); + } - var accessoryRegistry = Provider.of(context, listen: false); + var accessoryRegistry = + Provider.of(context, listen: false); accessoryRegistry.loadAccessories(); } - Future handleFileSharingIntent(List files) async { + Future handleFileSharingIntent(List files) async { // Received a sharing intent with a number of files. // Import the accessories for each device in sequence. // If no files are shared do nothing @@ -70,11 +75,13 @@ class _AppLayoutState extends State { if (file.type == SharedMediaType.FILE) { // On iOS the file:// prefix has to be stripped to access the file path String path = Platform.isIOS - ? Uri.decodeComponent(file.path.replaceFirst('file://', '')) - : file.path; - Navigator.push(context, MaterialPageRoute( - builder: (context) => ItemFileImport(filePath: path), - )); + ? Uri.decodeComponent(file.path.replaceFirst('file://', '')) + : file.path; + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => ItemFileImport(filePath: path), + )); } } } @@ -92,7 +99,6 @@ class _AppLayoutState extends State { super.didChangeDependencies(); } - @override Widget build(BuildContext context) { bool isInitialized = context.watch().initialized; From b8139e6b762e7de3a77b0088d994731ab1539fd8 Mon Sep 17 00:00:00 2001 From: kauzu Date: Wed, 29 Jun 2022 20:13:44 +0200 Subject: [PATCH 8/9] Use web compatible crypto library --- .../lib/findMy/decrypt_reports.dart | 21 ++++++++++++++++--- openhaystack-mobile/pubspec.yaml | 3 ++- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/openhaystack-mobile/lib/findMy/decrypt_reports.dart b/openhaystack-mobile/lib/findMy/decrypt_reports.dart index f1a0276..13a7acb 100644 --- a/openhaystack-mobile/lib/findMy/decrypt_reports.dart +++ b/openhaystack-mobile/lib/findMy/decrypt_reports.dart @@ -1,10 +1,13 @@ import 'dart:convert'; import 'dart:typed_data'; +import 'package:flutter/foundation.dart'; import 'package:pointycastle/export.dart'; import 'package:pointycastle/src/utils.dart' as pc_utils; import 'package:openhaystack_mobile/findMy/models.dart'; +import 'package:cryptography/cryptography.dart' as nice_crypto; + class DecryptReports { /// Decrypts a given [FindMyReport] with the given private key. static Future decryptReport( @@ -27,7 +30,7 @@ class DecryptReports { final Uint8List sharedKeyBytes = _ecdh(ephemeralPublicKey, privateKey); final Uint8List derivedKey = _kdf(sharedKeyBytes, ephemeralKeyBytes); - final decryptedPayload = _decryptPayload(encData, derivedKey, tag); + final decryptedPayload = await _decryptPayload(encData, derivedKey, tag); final locationReport = _decodePayload(decryptedPayload, report); return locationReport; @@ -73,10 +76,22 @@ class DecryptReports { /// Decrypts the given cipher text with the key data using an AES-GCM block cipher. /// Returns the decrypted raw data. - static Uint8List _decryptPayload( - Uint8List cipherText, Uint8List symmetricKey, Uint8List tag) { + static Future _decryptPayload( + Uint8List cipherText, Uint8List symmetricKey, Uint8List tag) async { final decryptionKey = symmetricKey.sublist(0, 16); final iv = symmetricKey.sublist(16, symmetricKey.length); + if (kIsWeb) { + nice_crypto.SecretKey secretKey = + new nice_crypto.SecretKey(decryptionKey); + + nice_crypto.SecretBox secretBox = new nice_crypto.SecretBox(cipherText, + nonce: iv, mac: nice_crypto.Mac(tag)); + + List decrypted = await nice_crypto.AesGcm.with128bits() + .decrypt(secretBox, secretKey: secretKey); + print(decrypted); + return Uint8List.fromList(decrypted); + } final aesGcm = GCMBlockCipher(AESEngine()) ..init( diff --git a/openhaystack-mobile/pubspec.yaml b/openhaystack-mobile/pubspec.yaml index 2b1779a..11671a0 100644 --- a/openhaystack-mobile/pubspec.yaml +++ b/openhaystack-mobile/pubspec.yaml @@ -40,7 +40,8 @@ dependencies: # Cryptography # latest version of pointy castle for crypto functions - pointycastle: ^3.4.0 + pointycastle: ^3.6.0 + cryptography: ^2.0.5 # State Management provider: ^6.0.1 From 3bdaf724f37ff30c14c27dc1401ad3ed79dc9194 Mon Sep 17 00:00:00 2001 From: kauzu Date: Wed, 29 Jun 2022 21:17:10 +0200 Subject: [PATCH 9/9] Some exception we can ignore i guess --- openhaystack-mobile/lib/findMy/decrypt_reports.dart | 2 +- openhaystack-mobile/lib/findMy/find_my_controller.dart | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/openhaystack-mobile/lib/findMy/decrypt_reports.dart b/openhaystack-mobile/lib/findMy/decrypt_reports.dart index 13a7acb..1ab0486 100644 --- a/openhaystack-mobile/lib/findMy/decrypt_reports.dart +++ b/openhaystack-mobile/lib/findMy/decrypt_reports.dart @@ -89,7 +89,7 @@ class DecryptReports { List decrypted = await nice_crypto.AesGcm.with128bits() .decrypt(secretBox, secretKey: secretKey); - print(decrypted); + return Uint8List.fromList(decrypted); } diff --git a/openhaystack-mobile/lib/findMy/find_my_controller.dart b/openhaystack-mobile/lib/findMy/find_my_controller.dart index 13e03d9..bc52e90 100644 --- a/openhaystack-mobile/lib/findMy/find_my_controller.dart +++ b/openhaystack-mobile/lib/findMy/find_my_controller.dart @@ -34,8 +34,12 @@ class FindMyController { final jsonResults = await ReportsFetcher.fetchLocationReports( keyPair.getHashedAdvertisementKey()); for (var result in jsonResults) { - results.add( - await _decryptResult(result, keyPair, keyPair.privateKeyBase64!)); + try { + results.add( + await _decryptResult(result, keyPair, keyPair.privateKeyBase64!)); + } catch (e) { + print(e); + } } return results; }