
add-crypto-api
by djx-y-z
Dart FFI wrapper for liboqs, delivering post-quantum cryptographic algorithms. Supports NIST-standardized KEMs (e.g., ML-KEM) and signatures (e.g., ML-DSA), optimized for Flutter and cross-platform applications (Android, iOS, Linux, macOS, Windows). MIT Licensed.
SKILL.md
name: add-crypto-api description: Add new cryptographic API to liboqs_dart. Use when implementing new KEM algorithms, signature schemes, adding new cryptographic features, or extending the library API.
Add New Cryptographic API
Checklist and templates for adding new cryptographic functionality to liboqs_dart.
Pre-Implementation Checklist
- API exists in liboqs C library
- Bindings exist in
lib/src/bindings/liboqs_bindings.dart - If not, run
make regenfirst
Implementation Checklist
1. Create Main Class
File: lib/src/{feature}.dart
import 'dart:ffi';
import 'dart:typed_data';
import 'package:ffi/ffi.dart';
import 'base.dart';
import 'bindings/liboqs_bindings.dart' as oqs;
import 'exception.dart';
import 'utils.dart';
// Finalizer for native resource cleanup
final Finalizer<Pointer<oqs.OQS_FEATURE>> _featureFinalizer = Finalizer(
(ptr) => oqs.OQS_FEATURE_free(ptr),
);
// Finalizer for zeroing secrets
final Finalizer<Uint8List> _secretDataFinalizer = Finalizer((data) {
LibOQSUtils.zeroMemory(data);
});
class Feature {
late final Pointer<oqs.OQS_FEATURE> _ptr;
final String algorithmName;
bool _disposed = false;
Feature._(this._ptr, this.algorithmName) {
_featureFinalizer.attach(this, _ptr, detach: this);
}
void _checkDisposed() {
if (_disposed) throw StateError('Instance has been disposed');
}
static Feature create(String algorithmName) {
LibOQSBase.init();
LibOQSUtils.validateAlgorithmName(algorithmName);
// ... implementation
}
void dispose() {
if (!_disposed) {
oqs.OQS_FEATURE_free(_ptr);
_featureFinalizer.detach(this);
_disposed = true;
}
}
}
2. Create Data Classes
For any class holding secrets:
class FeatureKeyPair {
final Uint8List publicKey;
final Uint8List secretKey; // SECRET!
FeatureKeyPair({required this.publicKey, required this.secretKey}) {
// Attach finalizer for auto-cleanup
_secretDataFinalizer.attach(this, secretKey, detach: this);
}
/// Zero secrets immediately
void clearSecrets() {
LibOQSUtils.zeroMemory(secretKey);
}
/// Safe: public key only
String get publicKeyBase64 => base64Encode(publicKey);
String get publicKeyHex => publicKey.map((b) => b.toRadixString(16).padLeft(2, '0')).join();
/// **Security Warning:** Exports SECRET KEY!
Map<String, String> toStrings() => {
'publicKey': base64Encode(publicKey),
'secretKey': base64Encode(secretKey),
};
}
3. Export from Library
Edit lib/liboqs.dart:
export 'src/feature.dart';
4. Write Tests
File: test/{feature}_test.dart
import 'package:liboqs/liboqs.dart';
import 'package:test/test.dart';
void main() {
group('Feature', () {
late Feature feature;
setUp(() {
feature = Feature.create('Algorithm-Name');
});
tearDown(() {
feature.dispose();
});
test('lists supported algorithms', () {
final algorithms = Feature.getSupportedAlgorithms();
expect(algorithms, isNotEmpty);
});
test('generates key pair', () {
final keyPair = feature.generateKeyPair();
expect(keyPair.publicKey, isNotEmpty);
expect(keyPair.secretKey, isNotEmpty);
// Cleanup secrets
keyPair.clearSecrets();
});
test('throws on disposed instance', () {
feature.dispose();
expect(() => feature.someMethod(), throwsStateError);
});
});
}
5. Add Security Test
File: test/security_test.dart (add to existing)
test('Feature zeros secrets on clearSecrets()', () {
final feature = Feature.create('Algorithm-Name');
final keyPair = feature.generateKeyPair();
final secretCopy = Uint8List.fromList(keyPair.secretKey);
expect(keyPair.secretKey, equals(secretCopy));
keyPair.clearSecrets();
expect(keyPair.secretKey, everyElement(0));
feature.dispose();
});
6. Update Documentation
Add to README.md if it's a major feature:
## Feature Name
Description of the feature...
```dart
final feature = Feature.create('Algorithm-Name');
final keyPair = feature.generateKeyPair();
// ...
keyPair.clearSecrets();
feature.dispose();
## Security Requirements Checklist
- [ ] All secret data uses `secureFreePointer()` in native code
- [ ] All secret data classes have `clearSecrets()` method
- [ ] All secret data classes have `_secretDataFinalizer` attached
- [ ] All function pointers validated before `.asFunction()`
- [ ] All memory freed in `finally` blocks
- [ ] All methods exposing secrets have `/// **Security Warning:**` docs
- [ ] Public-key-only getters provided (`publicKeyBase64`, `publicKeyHex`)
- [ ] `dispose()` follows correct order: free → detach → flag
## Run Quality Checks
```bash
# Format code
make format
# Static analysis
make analyze ARGS="--fatal-infos"
# Run tests
make test
# Run specific test
make test ARGS="test/feature_test.dart"
# Security tests
make test ARGS="test/security_test.dart"
Existing Implementations to Reference
| Feature | File | Description |
|---|---|---|
| KEM | lib/src/kem.dart | Key Encapsulation Mechanism |
| Signature | lib/src/signature.dart | Digital Signatures |
| Random | lib/src/random.dart | Random Number Generation |
These files demonstrate all required patterns.
Score
Total Score
Based on repository quality metrics
SKILL.mdファイルが含まれている
ライセンスが設定されている
100文字以上の説明がある
GitHub Stars 100以上
1ヶ月以内に更新
10回以上フォークされている
オープンIssueが50未満
プログラミング言語が設定されている
1つ以上のタグが設定されている
Reviews
Reviews coming soon

