Dart FFI bindings for liboqs, providing post-quantum KEM and signature primitives.
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.
dependencies:
oqs: ^3.0.1You still need a native liboqs library for your platform.
Use Pre-Built binaries:
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 installimport 'package:oqs/oqs.dart';
LibOQSLoader.customPaths = LibraryPaths(
windows: r'C:\libs\oqs.dll',
linux: '/usr/local/lib/liboqs.so',
macOS: '/opt/homebrew/lib/liboqs.dylib',
);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.
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
- iOS uses
DynamicLibrary.process()(XCFramework/static linking), notDynamicLibrary.open(...). - Android ABI-specific selection is supported through
LibraryPaths.currentPlatformPath. - On Linux/macOS/Windows, system resolution can work when the library is installed in standard paths.
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',
linux: '/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');- Loader caches resolved
DynamicLibraryby default. - Update paths at runtime: set
LibOQSLoader.customPaths = ...(this clears cache). - Manual reset:
LibOQSLoader.clearCache().
- 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.
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();
}- 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
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();
}- Upgrade dependency in
pubspec.yamlto^3.0.1. - 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.
Set LibOQSLoader.customPaths or install liboqs to standard system paths.
Enabled algorithms depend on how your liboqs binary was built. Check:
print(LibOQS.getSupportedKEMAlgorithms());
print(LibOQS.getSupportedSignatureAlgorithms());- 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.
See the example/ directory for end-to-end usage samples.