flutter_eddsa 0.0.4
flutter_eddsa: ^0.0.4 copied to clipboard
Flutter FFI plugin for Ed25519 digital signatures and X25519 Diffie-Hellman key exchange. High-performance Curve25519 cryptography via native C.
flutter_eddsa #
Elliptic-curve cryptography for Flutter — Ed25519 digital signatures and X25519 Diffie-Hellman key exchange, delivered through a direct native FFI bridge with no platform-channel overhead.
The same algorithms that secure Signal, WireGuard, OpenSSH, and TLS 1.3 — now available as a clean, cross-platform Flutter plugin.
Why Curve25519? #
Curve25519 is the modern standard for high-speed, high-security elliptic-curve cryptography:
- Ed25519 — deterministic digital signatures. Fast to sign, fast to verify, no random number generator required at signing time, and immune to the class of fault attacks that affect ECDSA.
- X25519 — Diffie-Hellman key agreement. Two parties can establish a shared secret over an untrusted channel without ever transmitting a private key.
Both primitives are built on the same underlying curve, which means an Ed25519 key pair can be converted to X25519 format — useful when a single long-term key pair needs to serve both signing and key-exchange roles.
Features #
- Ed25519 public key derivation, signing, and verification
- X25519 Diffie-Hellman key agreement
- Key conversion — Ed25519 ↔ X25519 for both public and secret keys
- Pure native performance via
dart:ffi— no method channels, no serialisation overhead - Cryptographically secure random key generation
- Android · iOS · Linux · macOS · Windows
Installation #
dependencies:
flutter_eddsa: ^0.0.1
flutter pub get
Usage #
Generate a key pair #
import 'package:flutter_eddsa/flutter_eddsa.dart';
// Generate a random 32-byte secret key
final secret = EddsaUtils.generateRandom32();
// Derive the corresponding Ed25519 public key
final publicKey = Ed25519.derivePublicKey(secret);
Sign a message #
final message = EddsaUtils.bytesFromString('Hello, flutter_eddsa!');
final signature = Ed25519.signMessage(secret, publicKey, message);
Verify a signature #
final isValid = Ed25519.verifySignature(signature, publicKey, message);
print(isValid); // true
X25519 Diffie-Hellman key exchange #
Diffie-Hellman lets two parties establish a shared secret over a public channel without ever transmitting a private key. The idea: each party combines their own secret with the other party's public key, and the mathematics of the elliptic curve guarantees both arrive at the same result.
Alice Bob
───── ───
aliceSecret (private) bobSecret (private)
alicePublic = secret × G bobPublic = secret × G
──── exchange public keys ────▶
sharedSecret = aliceSecret × bobPublic
sharedSecret = bobSecret × alicePublic
(same value on both sides — proven by the associativity of scalar multiplication)
In code:
// Each party generates a key pair
final aliceSecret = EddsaUtils.generateRandom32();
final alicePublic = Ed25519.generateX25519PublicKey(aliceSecret);
final bobSecret = EddsaUtils.generateRandom32();
final bobPublic = Ed25519.generateX25519PublicKey(bobSecret);
// They exchange public keys (safe to send over untrusted network)
// Each computes the shared secret independently
final aliceShared = Ed25519.diffieHellman(aliceSecret, bobPublic);
final bobShared = Ed25519.diffieHellman(bobSecret, alicePublic);
// Both arrive at the same 32-byte value
assert(EddsaUtils.hexFromBytes(aliceShared) ==
EddsaUtils.hexFromBytes(bobShared));
// Use the shared secret to derive an encryption key (e.g. with HKDF or SHA-256)
The shared secret is typically passed through a key-derivation function (KDF) before use as a symmetric encryption key.
Convert an Ed25519 key pair to X25519 #
final xSecret = Ed25519.secretKeyToX25519(secret);
final xPublic = Ed25519.publicKeyToX25519(publicKey);
API reference #
Ed25519 #
All methods are static. Keys are 32 bytes; signatures are 64 bytes.
| Method | Input | Output | Description |
|---|---|---|---|
derivePublicKey(secret) |
32 B secret | 32 B public key | Derives an Ed25519 public key |
signMessage(secret, publicKey, message) |
keys + arbitrary message | 64 B signature | Signs a message |
verifySignature(signature, publicKey, message) |
64 B sig + key + message | bool |
Verifies a signature |
generateX25519PublicKey(scalar) |
32 B scalar | 32 B public key | Scalar × base point (X25519 key generation) |
scalarMultiply(scalar, point) |
32 B scalar + 32 B point | 32 B result | Raw X25519 scalar multiplication |
diffieHellman(secret, peerPublicKey) |
own secret + peer public | 32 B shared secret | X25519 key agreement |
publicKeyToX25519(edPublicKey) |
32 B Ed25519 public key | 32 B X25519 public key | Key format conversion |
secretKeyToX25519(edSecretKey) |
32 B Ed25519 secret key | 32 B X25519 secret key | Key format conversion |
EddsaUtils #
| Method | Description |
|---|---|
generateRandom32() |
Cryptographically secure 32-byte random value |
bytesFromHex(hex) |
Decode a lowercase hex string to Uint8List |
hexFromBytes(bytes) |
Encode Uint8List as a lowercase hex string |
bytesFromString(text) |
Encode a UTF-8 string as bytes |
stringFromBytes(bytes) |
Decode bytes to a UTF-8 string |
Platform support #
| Platform | Status |
|---|---|
| Android | ✅ |
| iOS | ✅ |
| macOS | ✅ |
| Linux | ✅ |
| Windows | ✅ |
| Web | ❌ (not yet supported) |
Native cryptographic core #
The cryptographic implementation is provided by libeddsa — a compact, public-domain C library by Philipp Lay with the following properties:
- Written in portable C99
- Constant-time scalar multiplication (timing-attack resistant)
- Stack-cleaning after secret key operations
- No external dependencies
- Under 90 KB compiled
The C source is vendored directly into src/crypto/ and compiled as part of the
Flutter build for each platform — no pre-built binaries, no external downloads.
Security notes #
- Keys and signatures are passed as raw
Uint8List— never log or persist secret keys. generateRandom32()uses Dart'sRandom.secure(), which draws from the OS entropy pool.- This plugin provides primitives only. For a complete secure channel you will also need a symmetric cipher and message authentication (e.g. AES-GCM or ChaCha20-Poly1305).
License #
This plugin is licensed under the MIT License — see LICENSE.
The bundled C cryptographic library (src/crypto/) is in the public domain
(original work by Philipp Lay).