oqs 2.0.1
oqs: ^2.0.1 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.
example/oqs_example.dart
import 'dart:convert';
import 'dart:typed_data';
import 'package:oqs/oqs.dart';
import 'package:oqs/src/random.dart';
void main() {
print('=== LibOQS Dart Example ===\n');
// Initialize the library
LibOQS.init();
try {
// Print supported algorithms
KEM.printSupportedKemAlgorithms();
Signature.printSupportedSignatureAlgorithms();
// Print library information
print('LibOQS Version: ${LibOQS.getVersion()}');
print(
'Supported KEM algorithms: ${LibOQS.getSupportedKEMAlgorithms().length}',
);
print(
'Supported Signature algorithms: ${LibOQS.getSupportedSignatureAlgorithms().length}\n',
);
//random example
randomExample();
// KEM Example
kemExample();
print('\n' + '=' * 50 + '\n');
// Signature Example
signatureExample();
} catch (e) {
print('Error: $e');
} finally {
// Clean up
LibOQS.cleanup();
}
}
void kemExample() {
print('=== KEM (Key Encapsulation Mechanism) Example ===');
// Try different KEM algorithms
final kemAlgorithms = ['Kyber512', 'Kyber768', 'Kyber1024'];
final allKemAlgorithms = KEM.getSupportedKemAlgorithms();
for (final algName in kemAlgorithms) {
if (!LibOQS.isKEMSupported(algName)) {
print('$algName is not supported, skipping...');
continue;
}
print('\nTesting $algName:');
final kem = KEM.create(algName);
if (kem == null) {
print('Failed to create KEM instance for $algName');
continue;
}
try {
// Print algorithm details
print(' Public key length: ${kem.publicKeyLength} bytes');
print(' Secret key length: ${kem.secretKeyLength} bytes');
print(' Ciphertext length: ${kem.ciphertextLength} bytes');
print(' Shared secret length: ${kem.sharedSecretLength} bytes');
// Generate key pair
final keyPair = kem.generateKeyPair();
print(' ✓ Generated key pair');
// Encapsulate
final encResult = kem.encapsulate(keyPair.publicKey);
print(' ✓ Encapsulated shared secret');
// Decapsulate
final sharedSecret = kem.decapsulate(
encResult.ciphertext,
keyPair.secretKey,
);
print(' ✓ Decapsulated shared secret');
// Verify the shared secrets match
final match = _compareUint8Lists(encResult.sharedSecret, sharedSecret);
print(' ✓ Shared secrets match: $match');
if (match) {
print(
' Shared secret (hex): ${_bytesToHex(sharedSecret.take(16).toList())}...',
);
}
} catch (e) {
print(' ✗ Error: $e');
} finally {
kem.dispose();
}
}
}
void signatureExample() {
print('=== Digital Signature Example ===');
// Try different signature algorithms
final sigAlgorithms = ['Dilithium2', 'Dilithium3', 'Falcon-512'];
final AllSigAlgorithms = Signature.getSupportedSignatureAlgorithms();
for (final algName in sigAlgorithms) {
if (!LibOQS.isSignatureSupported(algName)) {
print('$algName is not supported, skipping...');
continue;
}
print('\nTesting $algName:');
final sig = Signature.create(algName);
try {
// Print algorithm details
print(' Public key length: ${sig.publicKeyLength} bytes');
print(' Secret key length: ${sig.secretKeyLength} bytes');
print(' Max signature length: ${sig.maxSignatureLength} bytes');
// Generate key pair
final keyPair = sig.generateKeyPair();
print(' ✓ Generated key pair');
// Create a message to sign
final message = Uint8List.fromList(
utf8.encode(
'Hello, Post-Quantum World! This is a test message for $algName.',
),
);
// Sign the message
final signature = sig.sign(message, keyPair.secretKey);
print(' ✓ Signed message (signature length: ${signature.length} bytes)');
// Verify the signature
final isValid = sig.verify(message, signature, keyPair.publicKey);
print(' ✓ Signature verification: $isValid');
// Test with invalid signature
final invalidSignature = Uint8List.fromList(
signature.toList()..shuffle(),
);
final isInvalid = sig.verify(
message,
invalidSignature,
keyPair.publicKey,
);
print(' ✓ Invalid signature verification: $isInvalid (should be false)');
} catch (e) {
print(' ✗ Error: $e');
} finally {
sig.dispose();
}
}
}
void randomExample() {
print('=== Random Number Generation Example ===');
try {
// Generate random bytes
print('Generating random bytes...');
final randomBytes = OQSRandom.generateBytes(32);
print(
' ✓ Generated 32 random bytes: ${_bytesToHex(randomBytes.take(16).toList())}...',
);
// Generate a cryptographic seed
print('\nGenerating cryptographic seed...');
final seed = OQSRandom.generateSeed(32);
print(' ✓ Generated seed: ${_bytesToHex(seed.take(16).toList())}...');
// Generate random integers
print('\nGenerating random integers...');
final randomInts = List.generate(5, (_) => OQSRandom.generateInt(1, 100));
print(' ✓ Random integers (1-99): $randomInts');
// Generate random boolean values
print('\nGenerating random booleans...');
final randomBools = List.generate(
10,
(_) => OQSRandomExtensions.generateBool(),
);
print(' ✓ Random booleans: $randomBools');
// Generate random double
print('\nGenerating random doubles...');
final randomDoubles = List.generate(
5,
(_) => OQSRandomExtensions.generateDouble(),
);
print(
' ✓ Random doubles (0.0-1.0): ${randomDoubles.map((d) => d.toStringAsFixed(6)).toList()}',
);
// Test list shuffling
print('\nTesting cryptographic shuffle...');
final testList = List.generate(10, (i) => i);
print(' Original list: $testList');
OQSRandomExtensions.shuffleList(testList);
print(' ✓ Shuffled list: $testList');
// Show available RNG algorithms
print('\nAvailable RNG algorithms:');
final algorithms = OQSRandom.getAvailableAlgorithms();
for (final alg in algorithms) {
final supported = OQSRandom.isAlgorithmLikelySupported(alg) ? '✓' : '?';
print(' $supported $alg');
}
// Test algorithm switching (optional, be careful with this)
print('\nTesting RNG algorithm info...');
print(' Current algorithm: system (default)');
// Generate some bytes with default algorithm
final defaultBytes = OQSRandom.generateBytes(16);
print(
' ✓ Generated with default: ${_bytesToHex(defaultBytes.take(8).toList())}...',
);
} catch (e) {
print(' ✗ Random generation error: $e');
}
}
// Helper functions
bool _compareUint8Lists(Uint8List a, Uint8List b) {
if (a.length != b.length) return false;
for (int i = 0; i < a.length; i++) {
if (a[i] != b[i]) return false;
}
return true;
}
String _bytesToHex(List<int> bytes) {
return bytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join('');
}