infusion_ffi
Public Flutter FFI plugin for Infusion without Rust sources.
- Android: bundled jniLibs in the package (no download).
- iOS: bundled
XCFrameworkin the package (no download). - Desktop: downloads prebuilt binaries from public GitHub Releases on first use and caches per version.
Core code remains private. This repository exposes only the public Dart/Flutter wrapper and minimal platform glue. InfusionLoader downloads from GitHub Releases and verifies SHA-256 checksums per release asset. Releases must be public; private releases return 404 without auth.
Platform Support
| Platform | Architectures | Delivery |
|---|---|---|
| Android | arm64-v8a, armeabi-v7a, x86_64 | Bundled .so (no download) |
| iOS | arm64, simulator (arm64/x86_64) | Bundled XCFramework (no download) |
| macOS | universal (arm64 + x86_64) | Downloaded on first use |
| Linux | x86_64, arm64 | Downloaded on first use |
| Windows | x86_64, arm64 | Downloaded on first use |
Usage
dependencies:
infusion_ffi: ^1.3.17
Ensure releases host platform binaries named:
- macOS: libinfusion_ffi.dylib
- Linux x86_64: libinfusion_ffi-linux-x64.so
- Linux arm64: libinfusion_ffi-linux-arm64.so
- Windows x86_64: infusion_ffi-windows-x64.dll
- Windows arm64: infusion_ffi-windows-arm64.dll
API
Import and call the loader before FFI symbol lookups:
import 'package:infusion_ffi/infusion_ffi.dart';
final lib = await InfusionLoader.load();
Zero-config Loading
InfusionLoader.load() resolves the native library in this order:
- Android/iOS: bundled native libs (AAR/XCFramework)
- Desktop: GitHub Release download, cached in
systemTemp/infusion_ffi/<version>with SHA-256 verification
Testing
Flutter widget tests block HttpClient by default. If you run loader tests in flutter_test,
allow network access (or prefer integration_test) so the release download can complete.
Advanced Security
Encryption (Seal/Open)
Encrypt data into a sealed "frame" that contains the ciphertext, an authentication tag (AEAD), and metadata headers (like algorithm ID and key derivation info).
// Seal (Encrypt)
final plaintext = Uint8List.fromList(utf8.encode('Top Secret'));
final frame = await infusion.seal(
data: plaintext,
policyId: 0, // 0 = default policy
);
// Open (Decrypt)
final decrypted = await infusion.open(frame); // Throws if auth fails
print(utf8.decode(decrypted)); // "Top Secret"
Capabilities (Access Control)
Infusion uses "Capability Tokens" (CapTokens) to delegate access rights.
// Issue a capability
final capToken = await infusion.issueCap(
scopeCid: myScopeCid, // CID of the resource/scope
rights: 0x01, // Bitmask (e.g., READ permission)
expTs: 1735689600, // Expiration timestamp (Unix)
delegatedPub32: recipientPublicKey, // 32-byte Ed25519 public key
);
// Verify a capability
// Checks signature, expiration, and if 'requesterPub32' matches the delegate
final isValid = await infusion.verifyCap(
capToken: capToken,
requesterPub32: recipientPublicKey,
);
Key Derivation
Derive deterministic sub-keys from your vault's master seed using a context string. Useful for generating keys for other systems (e.g., Hive encryption keys) without storing them.
final contextInfo = Uint8List.fromList(utf8.encode('hive_box_encryption'));
final derivedKey = await infusion.deriveKey(contextInfo);