diff --git a/.github/workflows/flutter-ci.yml b/.github/workflows/flutter-ci.yml index 14838cb..294d388 100644 --- a/.github/workflows/flutter-ci.yml +++ b/.github/workflows/flutter-ci.yml @@ -32,6 +32,8 @@ jobs: steps: - uses: dart-lang/setup-dart@v1 + with: + sdk: main - uses: actions/checkout@v3 with: submodules: true @@ -45,12 +47,6 @@ jobs: - name: Install pdfsig run: sudo apt-get install -y poppler-utils - - name: Install native - run: | - cargo build --release - echo "LD_LIBRARY_PATH=$(pwd)/target/release/" >> "$GITHUB_ENV" - working-directory: meesign_native/native/meesign-crypto - - name: Setup server run: | wget https://raw.githubusercontent.com/crocs-muni/meesign-server/main/generate_keys.sh @@ -61,8 +57,13 @@ jobs: --publish 1337:1337 --volume $(pwd)/keys/:/meesign/keys/:Z \ crocsmuni/meesign:nightly + - run: | + for PKG in native network core; do + (cd meesign_$PKG; dart pub get) + done + - name: Run tests - run: cd meesign_core; dart test + run: cd meesign_core; dart --enable-experiment=native-assets test build: @@ -114,7 +115,7 @@ jobs: - name: Clone Flutter repository with stable channel uses: subosito/flutter-action@v2 with: - channel: stable + channel: main cache: true - name: Install Android dependencies @@ -162,6 +163,9 @@ jobs: flutter config --enable-windows-desktop flutter config --enable-macos-desktop + - name: Enable native assets + run: flutter config --enable-native-assets + # Fetch dart packages - run: flutter pub get @@ -171,17 +175,6 @@ jobs: --release --dart-define=ALLOW_BAD_CERTS=true - - name: Build native libs for macOS - if: matrix.target == 'macOS' - run: | - cd meesign_native/native/meesign-crypto/ - cargo build --release --target x86_64-apple-darwin - cargo build --release --target aarch64-apple-darwin - lipo -create -output libmeesign_crypto.dylib \ - target/x86_64-apple-darwin/release/libmeesign_crypto.dylib \ - target/aarch64-apple-darwin/release/libmeesign_crypto.dylib - cp libmeesign_crypto.dylib ../../../build/macos/Build/Products/Release/meesign_client.app/Contents/Frameworks/ - # Package the build. - name: Copy VC redistributables to release directory for Windows if: matrix.target == 'Windows' diff --git a/meesign_native/ffigen/meesign-crypto.yaml b/meesign_native/ffigen/meesign-crypto.yaml index cd764b1..27eaabc 100644 --- a/meesign_native/ffigen/meesign-crypto.yaml +++ b/meesign_native/ffigen/meesign-crypto.yaml @@ -8,3 +8,5 @@ headers: # so specify only the headers we need (most notably avoid system headers) include-directives: - '**bindings.h' +ffi-native: + assetId: package:meesign_native/libmeesign_crypto \ No newline at end of file diff --git a/meesign_native/hook/build.dart b/meesign_native/hook/build.dart new file mode 100644 index 0000000..a7cccf4 --- /dev/null +++ b/meesign_native/hook/build.dart @@ -0,0 +1,85 @@ +import 'dart:io'; + +import 'package:native_assets_cli/native_assets_cli.dart'; + +String selectTarget(OS os, Architecture architecture) { + return switch ((os, architecture)) { + (OS.linux, Architecture.x64) => 'x86_64-unknown-linux-gnu', + (OS.windows, Architecture.x64) => 'x86_64-pc-windows-msvc', + (OS.macOS, Architecture.x64) => 'x86_64-apple-darwin', + (OS.macOS, Architecture.arm64) => 'aarch64-apple-darwin', + (OS.android, Architecture.x64) => 'x86_64-linux-android', + (OS.android, Architecture.arm64) => 'aarch64-linux-android', + (OS.android, Architecture.arm) => 'armv7-linux-androideabi', + (OS.iOS, Architecture.arm64) => 'aarch64-apple-ios', + _ => throw UnsupportedError('($os, $architecture) not supported'), + }; +} + +String libPrefix(OS os) => switch (os) { + OS.linux || OS.macOS || OS.android || OS.iOS => 'lib', + _ => '', + }; + +String libSuffix(OS os) => switch (os) { + OS.linux || OS.android => '.so', + OS.macOS || OS.iOS => '.dylib', + OS.windows => '.dll', + _ => throw UnsupportedError(''), + }; + +void main(List args) async { + await build(args, (config, output) async { + if (config.linkModePreference == LinkModePreference.static) { + // Simulate that this hook only supports dynamic libraries. + throw UnsupportedError( + 'LinkModePreference.static is not supported.', + ); + } + + final target = selectTarget( + config.targetOS, + config.targetArchitecture ?? Architecture.current, + ); + String libName = + '${libPrefix(config.targetOS)}meesign_crypto${libSuffix(config.targetOS)}'; + final assetPath = config.outputDirectory.resolve(libName); + final cryptoDir = config.packageRoot.resolve('native/meesign-crypto/'); + + if (!config.dryRun) { + final result = await Process.run( + 'cargo', + ['build', '--release', '--target', target], + workingDirectory: cryptoDir.toFilePath(), + includeParentEnvironment: true, + runInShell: true, + environment: { + 'CC': config.cCompiler.compiler?.toFilePath() ?? '', + 'AR': config.cCompiler.archiver?.toFilePath() ?? '', + }, + ); + stdout.write(result.stdout); + stderr.write(result.stderr); + + final libUri = cryptoDir.resolve('target/$target/release/$libName'); + await File.fromUri(libUri).copy(assetPath.toFilePath()); + + output.addDependencies([ + cryptoDir, + config.packageRoot.resolve('hook/build.dart'), + ]); + } + + output.addAsset( + // TODO: Change to DataAsset once the Dart/Flutter SDK can consume it. + NativeCodeAsset( + package: config.packageName, + name: 'libmeesign_crypto', + file: assetPath, + linkMode: DynamicLoadingBundled(), + os: config.targetOS, + architecture: config.targetArchitecture, + ), + ); + }); +} diff --git a/meesign_native/lib/src/dl_util.dart b/meesign_native/lib/src/dl_util.dart deleted file mode 100644 index 54c98b8..0000000 --- a/meesign_native/lib/src/dl_util.dart +++ /dev/null @@ -1,13 +0,0 @@ -import 'dart:ffi'; -import 'dart:io'; - -String dlPlatformName(String name) { - if (Platform.isAndroid || Platform.isLinux) return 'lib$name.so'; - if (Platform.isWindows) return '$name.dll'; - if (Platform.isMacOS) return 'lib$name.dylib'; - throw Exception('Platform unsupported'); -} - -DynamicLibrary dlOpen(String name) { - return DynamicLibrary.open(dlPlatformName(name)); -} diff --git a/meesign_native/lib/src/generated/meesign_crypto_lib.dart b/meesign_native/lib/src/generated/meesign_crypto_lib.dart index 521269b..5b19f60 100644 --- a/meesign_native/lib/src/generated/meesign_crypto_lib.dart +++ b/meesign_native/lib/src/generated/meesign_crypto_lib.dart @@ -4,245 +4,123 @@ // ignore_for_file: type=lint import 'dart:ffi' as ffi; -/// Bindings to meesign-crypto C API -class MeeSignCryptoLib { - /// Holds the symbol lookup function. - final ffi.Pointer Function(String symbolName) - _lookup; - - /// The symbols are looked up in [dynamicLibrary]. - MeeSignCryptoLib(ffi.DynamicLibrary dynamicLibrary) - : _lookup = dynamicLibrary.lookup; - - /// The symbols are looked up with [lookup]. - MeeSignCryptoLib.fromLookup( - ffi.Pointer Function(String symbolName) - lookup) - : _lookup = lookup; - - void buffer_free( - Buffer buffer, - ) { - return _buffer_free( - buffer, - ); - } - - late final _buffer_freePtr = - _lookup>('buffer_free'); - late final _buffer_free = _buffer_freePtr.asFunction(); - - void error_free( - ffi.Pointer error, - ) { - return _error_free( - error, - ); - } - - late final _error_freePtr = - _lookup)>>( - 'error_free'); - late final _error_free = - _error_freePtr.asFunction)>(); - - Buffer protocol_serialize( - ffi.Pointer proto_ptr, - ) { - return _protocol_serialize( - proto_ptr, - ); - } - - late final _protocol_serializePtr = - _lookup)>>( - 'protocol_serialize'); - late final _protocol_serialize = _protocol_serializePtr - .asFunction)>(); - - ffi.Pointer protocol_deserialize( - ffi.Pointer ctx_ptr, - int ctx_len, - ) { - return _protocol_deserialize( - ctx_ptr, - ctx_len, - ); - } - - late final _protocol_deserializePtr = _lookup< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, ffi.UintPtr)>>('protocol_deserialize'); - late final _protocol_deserialize = _protocol_deserializePtr.asFunction< - ffi.Pointer Function(ffi.Pointer, int)>(); - - ffi.Pointer protocol_keygen( - int proto_id, - bool with_card, - ) { - return _protocol_keygen( - proto_id, - with_card, - ); - } - - late final _protocol_keygenPtr = _lookup< - ffi - .NativeFunction Function(ffi.Int32, ffi.Bool)>>( - 'protocol_keygen'); - late final _protocol_keygen = _protocol_keygenPtr - .asFunction Function(int, bool)>(); - - Buffer protocol_advance( - ffi.Pointer proto_ptr, - ffi.Pointer data_ptr, - int data_len, - ffi.Pointer> error_out, - ) { - return _protocol_advance( - proto_ptr, - data_ptr, - data_len, - error_out, - ); - } - - late final _protocol_advancePtr = _lookup< - ffi.NativeFunction< - Buffer Function( - ffi.Pointer, - ffi.Pointer, - ffi.UintPtr, - ffi.Pointer>)>>('protocol_advance'); - late final _protocol_advance = _protocol_advancePtr.asFunction< - Buffer Function(ffi.Pointer, ffi.Pointer, int, - ffi.Pointer>)>(); - - Buffer protocol_finish( - ffi.Pointer proto_ptr, - ffi.Pointer> error_out, - ) { - return _protocol_finish( - proto_ptr, - error_out, - ); - } - - late final _protocol_finishPtr = _lookup< - ffi.NativeFunction< - Buffer Function(ffi.Pointer, - ffi.Pointer>)>>('protocol_finish'); - late final _protocol_finish = _protocol_finishPtr.asFunction< - Buffer Function( - ffi.Pointer, ffi.Pointer>)>(); - - ffi.Pointer protocol_init( - int proto_id, - ffi.Pointer group_ptr, - int group_len, - ) { - return _protocol_init( - proto_id, - group_ptr, - group_len, - ); - } - - late final _protocol_initPtr = _lookup< - ffi.NativeFunction< - ffi.Pointer Function(ffi.Int32, ffi.Pointer, - ffi.UintPtr)>>('protocol_init'); - late final _protocol_init = _protocol_initPtr.asFunction< - ffi.Pointer Function(int, ffi.Pointer, int)>(); - - void auth_key_free( - AuthKey key, - ) { - return _auth_key_free( - key, - ); - } - - late final _auth_key_freePtr = - _lookup>('auth_key_free'); - late final _auth_key_free = - _auth_key_freePtr.asFunction(); - - AuthKey auth_keygen( - ffi.Pointer name, - ffi.Pointer> error_out, - ) { - return _auth_keygen( - name, - error_out, - ); - } - - late final _auth_keygenPtr = _lookup< - ffi.NativeFunction< - AuthKey Function(ffi.Pointer, - ffi.Pointer>)>>('auth_keygen'); - late final _auth_keygen = _auth_keygenPtr.asFunction< - AuthKey Function( - ffi.Pointer, ffi.Pointer>)>(); - - Buffer auth_cert_key_to_pkcs12( - ffi.Pointer key_ptr, - int key_len, - ffi.Pointer cert_ptr, - int cert_len, - ffi.Pointer> error_out, - ) { - return _auth_cert_key_to_pkcs12( - key_ptr, - key_len, - cert_ptr, - cert_len, - error_out, - ); - } - - late final _auth_cert_key_to_pkcs12Ptr = _lookup< - ffi.NativeFunction< - Buffer Function( - ffi.Pointer, - ffi.UintPtr, - ffi.Pointer, - ffi.UintPtr, - ffi.Pointer>)>>('auth_cert_key_to_pkcs12'); - late final _auth_cert_key_to_pkcs12 = _auth_cert_key_to_pkcs12Ptr.asFunction< - Buffer Function(ffi.Pointer, int, ffi.Pointer, int, - ffi.Pointer>)>(); - - Buffer encrypt( - ffi.Pointer msg_ptr, - int msg_len, - ffi.Pointer key_ptr, - int key_len, - ffi.Pointer> error_out, - ) { - return _encrypt( - msg_ptr, - msg_len, - key_ptr, - key_len, - error_out, - ); - } - - late final _encryptPtr = _lookup< - ffi.NativeFunction< - Buffer Function( - ffi.Pointer, - ffi.UintPtr, - ffi.Pointer, - ffi.UintPtr, - ffi.Pointer>)>>('encrypt'); - late final _encrypt = _encryptPtr.asFunction< - Buffer Function(ffi.Pointer, int, ffi.Pointer, int, - ffi.Pointer>)>(); -} +@ffi.Native( + symbol: 'buffer_free', assetId: 'package:meesign_native/libmeesign_crypto') +external void buffer_free( + Buffer buffer, +); + +@ffi.Native)>( + symbol: 'error_free', assetId: 'package:meesign_native/libmeesign_crypto') +external void error_free( + ffi.Pointer error, +); + +@ffi.Native)>( + symbol: 'protocol_serialize', + assetId: 'package:meesign_native/libmeesign_crypto') +external Buffer protocol_serialize( + ffi.Pointer proto_ptr, +); + +@ffi.Native< + ffi.Pointer Function(ffi.Pointer, ffi.UintPtr)>( + symbol: 'protocol_deserialize', + assetId: 'package:meesign_native/libmeesign_crypto') +external ffi.Pointer protocol_deserialize( + ffi.Pointer ctx_ptr, + int ctx_len, +); + +@ffi.Native Function(ffi.Int32, ffi.Bool)>( + symbol: 'protocol_keygen', + assetId: 'package:meesign_native/libmeesign_crypto') +external ffi.Pointer protocol_keygen( + int proto_id, + bool with_card, +); + +@ffi.Native< + Buffer Function(ffi.Pointer, ffi.Pointer, + ffi.UintPtr, ffi.Pointer>)>( + symbol: 'protocol_advance', + assetId: 'package:meesign_native/libmeesign_crypto') +external Buffer protocol_advance( + ffi.Pointer proto_ptr, + ffi.Pointer data_ptr, + int data_len, + ffi.Pointer> error_out, +); + +@ffi.Native< + Buffer Function( + ffi.Pointer, ffi.Pointer>)>( + symbol: 'protocol_finish', + assetId: 'package:meesign_native/libmeesign_crypto') +external Buffer protocol_finish( + ffi.Pointer proto_ptr, + ffi.Pointer> error_out, +); + +@ffi.Native< + ffi.Pointer Function( + ffi.Int32, ffi.Pointer, ffi.UintPtr)>( + symbol: 'protocol_init', + assetId: 'package:meesign_native/libmeesign_crypto') +external ffi.Pointer protocol_init( + int proto_id, + ffi.Pointer group_ptr, + int group_len, +); + +@ffi.Native( + symbol: 'auth_key_free', + assetId: 'package:meesign_native/libmeesign_crypto') +external void auth_key_free( + AuthKey key, +); + +@ffi.Native< + AuthKey Function( + ffi.Pointer, ffi.Pointer>)>( + symbol: 'auth_keygen', assetId: 'package:meesign_native/libmeesign_crypto') +external AuthKey auth_keygen( + ffi.Pointer name, + ffi.Pointer> error_out, +); + +@ffi.Native< + Buffer Function( + ffi.Pointer, + ffi.UintPtr, + ffi.Pointer, + ffi.UintPtr, + ffi.Pointer>)>( + symbol: 'auth_cert_key_to_pkcs12', + assetId: 'package:meesign_native/libmeesign_crypto') +external Buffer auth_cert_key_to_pkcs12( + ffi.Pointer key_ptr, + int key_len, + ffi.Pointer cert_ptr, + int cert_len, + ffi.Pointer> error_out, +); + +@ffi.Native< + Buffer Function( + ffi.Pointer, + ffi.UintPtr, + ffi.Pointer, + ffi.UintPtr, + ffi.Pointer>)>( + symbol: 'encrypt', assetId: 'package:meesign_native/libmeesign_crypto') +external Buffer encrypt( + ffi.Pointer msg_ptr, + int msg_len, + ffi.Pointer key_ptr, + int key_len, + ffi.Pointer> error_out, +); abstract class ProtocolId { static const int Gg18 = 0; diff --git a/meesign_native/lib/src/meesign_crypto_wrapper.dart b/meesign_native/lib/src/meesign_crypto_wrapper.dart index cb79954..09dd5d1 100644 --- a/meesign_native/lib/src/meesign_crypto_wrapper.dart +++ b/meesign_native/lib/src/meesign_crypto_wrapper.dart @@ -4,8 +4,7 @@ import 'dart:typed_data'; import 'package:ffi/ffi.dart'; -import 'dl_util.dart'; -import 'generated/meesign_crypto_lib.dart'; +import 'generated/meesign_crypto_lib.dart' as lib; // TODO: profile the functions in this file // many chunks of data are copied, can it be avoided? @@ -22,7 +21,7 @@ extension IntIterConversion on Iterable { } } -extension BufferConversion on Buffer { +extension BufferConversion on lib.Buffer { Uint8List asTypedList() => ptr.asTypedList(len); Uint8List dupToDart() => Uint8List.fromList(asTypedList()); @@ -44,8 +43,6 @@ class ProtocolData { ProtocolData(this.context, this.data, this.recipient); } -final MeeSignCryptoLib _lib = MeeSignCryptoLib(dlOpen('meesign_crypto')); - class Error { Pointer> ptr; @@ -56,7 +53,7 @@ class Error { Error() : ptr = calloc(); static void free(Error error) { - _lib.error_free(error.ptr.value); + lib.error_free(error.ptr.value); calloc.free(error.ptr); error.ptr = nullptr; } @@ -65,10 +62,10 @@ class Error { class ProtocolWrapper { static Uint8List keygen(int protoId, {bool withCard = false}) { return using((Arena alloc) { - final proto = _lib.protocol_keygen(protoId, withCard); + final proto = lib.protocol_keygen(protoId, withCard); final context = alloc.using( - _lib.protocol_serialize(proto), - _lib.buffer_free, + lib.protocol_serialize(proto), + lib.buffer_free, ); return context.dupToDart(); @@ -79,10 +76,10 @@ class ProtocolWrapper { return using((Arena alloc) { final groupBuf = group.dupToNative(alloc); - final proto = _lib.protocol_init(protoId, groupBuf, group.length); + final proto = lib.protocol_init(protoId, groupBuf, group.length); final context = alloc.using( - _lib.protocol_serialize(proto), - _lib.buffer_free, + lib.protocol_serialize(proto), + lib.buffer_free, ); return context.dupToDart(); @@ -95,19 +92,19 @@ class ProtocolWrapper { final dataBuf = data.dupToNative(alloc); final error = alloc.using(Error(), Error.free); - final proto = _lib.protocol_deserialize(ctxBuf, context.length); + final proto = lib.protocol_deserialize(ctxBuf, context.length); final dataOut = alloc.using( - _lib.protocol_advance( + lib.protocol_advance( proto, dataBuf, data.length, error.ptr, ), - _lib.buffer_free, + lib.buffer_free, ); final contextOut = alloc.using( - _lib.protocol_serialize(proto), - _lib.buffer_free, + lib.protocol_serialize(proto), + lib.buffer_free, ); if (error.occured) throw ProtocolException(error.message); @@ -128,10 +125,10 @@ class ProtocolWrapper { final ctxBuf = context.dupToNative(alloc); final error = alloc.using(Error(), Error.free); - final proto = _lib.protocol_deserialize(ctxBuf, context.length); + final proto = lib.protocol_deserialize(ctxBuf, context.length); final data = alloc.using( - _lib.protocol_finish(proto, error.ptr), - _lib.buffer_free, + lib.protocol_finish(proto, error.ptr), + lib.buffer_free, ); if (error.occured) throw ProtocolException(error.message); @@ -152,8 +149,8 @@ class AuthWrapper { final error = alloc.using(Error(), Error.free); final res = alloc.using( - _lib.auth_keygen(namePtr.cast(), error.ptr), - _lib.auth_key_free, + lib.auth_keygen(namePtr.cast(), error.ptr), + lib.auth_key_free, ); if (error.occured) throw Exception(error.message); @@ -169,9 +166,9 @@ class AuthWrapper { final error = alloc.using(Error(), Error.free); final res = alloc.using( - _lib.auth_cert_key_to_pkcs12( + lib.auth_cert_key_to_pkcs12( keyPtr, key.length, certPtr, cert.length, error.ptr), - _lib.buffer_free, + lib.buffer_free, ); if (error.occured) throw Exception(error.message); @@ -189,9 +186,9 @@ class ElGamalWrapper { final error = alloc.using(Error(), Error.free); final res = alloc.using( - _lib.encrypt(messagePtr.cast(), message.length, publicKeyPtr, + lib.encrypt(messagePtr.cast(), message.length, publicKeyPtr, publicKey.length, error.ptr), - _lib.buffer_free, + lib.buffer_free, ); if (error.occured) throw Exception(error.message); diff --git a/meesign_native/pubspec.yaml b/meesign_native/pubspec.yaml index a512c2c..0882628 100644 --- a/meesign_native/pubspec.yaml +++ b/meesign_native/pubspec.yaml @@ -8,6 +8,7 @@ environment: dependencies: ffi: ^2.0.2 + native_assets_cli: ^0.5.4 dev_dependencies: ffigen: ^11.0.0 diff --git a/pubspec.lock b/pubspec.lock index fe1c125..db3e75d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -49,6 +49,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" + cli_config: + dependency: transitive + description: + name: cli_config + sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec + url: "https://pub.dev" + source: hosted + version: "0.2.0" clock: dependency: transitive description: @@ -388,26 +396,26 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" url: "https://pub.dev" source: hosted - version: "10.0.0" + version: "10.0.5" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.5" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.1" lints: dependency: transitive description: @@ -465,10 +473,10 @@ packages: dependency: transitive description: name: meta - sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 + sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.12.0" mime: dependency: "direct main" description: @@ -485,6 +493,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.5.1" + native_assets_cli: + dependency: transitive + description: + name: native_assets_cli + sha256: "9c1b67ccf85ec9282f34e5348ae78dcb7da2c7dc965c0265306477d977853a0d" + url: "https://pub.dev" + source: hosted + version: "0.5.4" ndef: dependency: transitive description: @@ -621,6 +637,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.0.5" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" + url: "https://pub.dev" + source: hosted + version: "2.1.4" qr: dependency: transitive description: @@ -742,10 +766,10 @@ packages: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.7.0" typed_data: dependency: transitive description: @@ -862,10 +886,10 @@ packages: dependency: transitive description: name: vm_service - sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 + sha256: a75f83f14ad81d5fe4b3319710b90dec37da0e22612326b696c9e1b8f34bbf48 url: "https://pub.dev" source: hosted - version: "13.0.0" + version: "14.2.0" web: dependency: transitive description: @@ -898,6 +922,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.3.0" + yaml: + dependency: transitive + description: + name: yaml + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + url: "https://pub.dev" + source: hosted + version: "3.1.2" sdks: dart: ">=3.3.0 <4.0.0" flutter: ">=3.19.0"