oqs 3.1.0
oqs: ^3.1.0 copied to clipboard
Dart FFI bindings for liboqs — high-performance post-quantum cryptography (PQC) with ML-KEM, ML-DSA, Falcon, SPHINCS+ for key encapsulation and signatures.
OQS for Dart #
Dart FFI bindings for liboqs, providing post-quantum KEM and signature primitives.
Version Compatibility #
oqs package |
liboqs |
|---|---|
3.x |
0.15.x |
2.x |
0.14.x (legacy) |
3.0.0 is a breaking release aligned to liboqs 0.15.0.
Install #
dependencies:
oqs: ^3.1.0
Native Library Setup #
You need a native liboqs library for your platform.
Option 1: Prebuilt binaries (Recommended) #
Download pre-built binaries from:
Supported platforms:
- Linux: x86_64, ARM64 (aarch64)
- macOS: ARM64 (Apple Silicon)
- Windows: x64
- iOS: XCFramework (device + simulator)
- Android: armeabi-v7a, arm64-v8a, x86, x86_64
Using the all-platforms archive:
# Extract the combined archive
tar -xzf liboqs-0.15.0-all-platforms.tar.gz
# Use in your Dart code
LibOQSLoader.loadLibrary(binaryRoot: '/path/to/liboqs-0.15.0');
The all-platforms archive contains architecture-separated binaries:
liboqs-0.15.0/
lib/x86_64/liboqs.so # Linux x86_64
lib/aarch64/liboqs.so # Linux ARM64
lib/liboqs.dylib # macOS ARM64
bin/oqs.dll # Windows x64
android/arm64-v8a/ # Android binaries
liboqs.xcframework/ # iOS
Option 2: Build from source #
git clone https://github.com/open-quantum-safe/liboqs.git
cd liboqs
mkdir build && cd build
cmake -GNinja -DCMAKE_INSTALL_PREFIX=/usr/local ..
ninja
ninja install
Optional explicit paths #
import 'package:oqs/oqs.dart';
LibOQSLoader.customPaths = LibraryPaths(
windows: r'C:\libs\oqs.dll',
linuxX64: '/usr/local/lib/liboqs.so',
linuxArm64: '/usr/local/lib/liboqs.so', // For ARM64 systems
macOS: '/opt/homebrew/lib/liboqs.dylib',
);
Library Loading Guide #
LibOQSLoader.loadLibrary() uses fallback strategies in this exact order:
explicitPathargumentLibOQSLoader.customPaths(LibraryPaths)- Deprecated
LibOQSLoader.customPath - Environment variable (
LIBOQS_PATH, orenvVarName) binaryRootextracted release layout- Package-relative paths
- System loader/default name (
liboqs.so,oqs.dll,liboqs.dylib) - Legacy default paths (
bin/<platform>/...)
If all fail, LibraryLoadException includes all attempted strategies.
Auto Path Selection (Package-relative) #
PackageRelativeStrategy checks:
./bin/<library-file>./lib/<library-file>./lib/native/<library-file>./native/<library-file>./blobs/<library-file>- Android extras:
./lib/arm64-v8a/liboqs.so./lib/armeabi-v7a/liboqs.so./lib/x86_64/liboqs.so./lib/x86/liboqs.so
Platform Notes #
- Linux: Automatically detects x86_64 vs ARM64 (aarch64) architecture
- iOS: Uses
DynamicLibrary.process()(XCFramework/static linking), notDynamicLibrary.open(...) - Android: ABI-specific selection supported through
LibraryPaths.currentPlatformPath - macOS/Windows: System resolution works when library is installed in standard paths
Recommended Config Patterns #
Use explicit, deterministic config for production:
final lib = LibOQSLoader.loadLibrary(
explicitPath: '/opt/liboqs/lib/liboqs.so',
);
Or per-platform config:
LibOQSLoader.customPaths = LibraryPaths(
windows: r'C:\oqs\oqs.dll',
linuxX64: '/usr/local/lib/liboqs.so',
linuxArm64: '/usr/local/lib/liboqs.so',
macOS: '/opt/homebrew/lib/liboqs.dylib',
androidArm64: '/data/local/tmp/liboqs.so',
);
Or extracted release root:
final lib = LibOQSLoader.loadLibrary(binaryRoot: '/opt/liboqs-0.15.0');
Cache Behavior #
- Loader caches resolved
DynamicLibraryby default. - Update paths at runtime: set
LibOQSLoader.customPaths = ...(this clears cache). - Manual reset:
LibOQSLoader.clearCache().
Debug Checklist #
- Verify
LibOQS.getVersion()returns non-empty string. - Print
LibOQS.getSupportedKEMAlgorithms()to confirm expected build features. - If loading fails, inspect thrown
LibraryLoadExceptionstrategy list and fix the earliest intended path.
Quick Start #
import 'dart:typed_data';
import 'package:oqs/oqs.dart';
void main() {
LibOQS.init();
final kems = LibOQS.getSupportedKEMAlgorithms();
if (kems.isEmpty) {
throw StateError('No enabled KEM algorithms in loaded liboqs');
}
final kem = KEM.create(kems.first)!;
final kp = kem.generateKeyPair();
final enc = kem.encapsulate(kp.publicKey);
final dec = kem.decapsulate(enc.ciphertext, kp.secretKey);
print(dec.length == enc.sharedSecret.length); // true
kem.dispose();
LibOQS.cleanup();
}
API Notes #
- Prefer runtime algorithm discovery:
LibOQS.getSupportedKEMAlgorithms()LibOQS.getSupportedSignatureAlgorithms()
- Do not hard-code key/signature lengths. Use:
kem.publicKeyLength,kem.secretKeyLength,kem.ciphertextLengthsig.publicKeyLength,sig.secretKeyLength,sig.maxSignatureLength
- Deterministic keypair generation is algorithm-dependent:
kem.supportsDeterministicGenerationkem.seedLength
Signature Example #
import 'dart:convert';
import 'dart:typed_data';
import 'package:oqs/oqs.dart';
void main() {
final sigAlgs = LibOQS.getSupportedSignatureAlgorithms();
if (sigAlgs.isEmpty) {
throw StateError('No enabled signature algorithms');
}
final sig = Signature.create(sigAlgs.first);
final kp = sig.generateKeyPair();
final msg = Uint8List.fromList(utf8.encode('hello pqc'));
final s = sig.sign(msg, kp.secretKey);
final ok = sig.verify(msg, s, kp.publicKey);
print(ok); // true
sig.dispose();
}
Migration to 3.x (liboqs 0.15.0) #
- Upgrade dependency in
pubspec.yamlto^3.1.0. - Ensure native
liboqsbinary is0.15.x. - Replace fixed algorithm assumptions (
Kyber*,Dilithium*) with runtime discovery. - Remove hard-coded size assertions and read lengths from each algorithm instance.
- Re-run tests against every target platform binary you ship.
Common Problems #
Library not found #
Set LibOQSLoader.customPaths or install liboqs to standard system paths.
Algorithm not available #
Enabled algorithms depend on how your liboqs binary was built. Check:
print(LibOQS.getSupportedKEMAlgorithms());
print(LibOQS.getSupportedSignatureAlgorithms());
Security Notes #
- Use NIST-standardized algorithms (
ML-KEM-*,ML-DSA-*) for production. - Dispose algorithm objects (
kem.dispose(),sig.dispose()) when done. - Keep
liboqsbinaries updated and track security advisories. - Do not share mutable crypto object state across isolates/threads.
Examples #
See the example/ directory for end-to-end usage samples.