A pure-Dart cryptography library: modern stream ciphers, authenticated encryption, a full AES mode set, and post-quantum cryptography with no native bindings and a single dependency.
cipherlib is the top layer of a three-package family:
It reuses hashlib for the SHA-3/SHAKE, Poly1305, and secure-random
primitives it is built on, and that is its only runtime dependency.
- Runs on every platform: pure Dart with no native code or FFI, so the same library works everywhere Dart does: the VM, Flutter (Android, iOS, Windows, macOS, Linux), and the web (dart2js and dart2wasm).
- Authenticated by default: AES-GCM, AES-CCM, and a Poly1305 variant of every stream cipher, each with a constant-time tag check that rejects tampered messages.
- Broad AES coverage: ten modes, from ECB and CBC to GCM, CCM, and XTS.
- One-shot or streaming: encrypt a buffer in a single call, or pipe a
Stream<List<int>>through any cipher as aStreamTransformer. - Post-quantum ready: ML-KEM-512/768/1024 (FIPS 203) for quantum-resistant key exchange.
- Fast: consistently outruns
PointyCastleandcryptography, see in the benchmarks below.
dependencies:
cipherlib: ^0.7.1or run dart pub add cipherlib. A single import exposes every algorithm:
import'package:cipherlib/cipherlib.dart';Two optional companions pair well with it — codecs for hex/UTF-8 conversion
(re-exported from hashlib) and random for secure key and nonce generation:
import'package:cipherlib/codecs.dart'; // toHex, fromHex, toUtf8, fromUtf8import'package:cipherlib/random.dart'; // randomBytesFull API reference: cipherlib library.
AES-256-GCM is the recommended default for most applications: it encrypts and authenticates in one step, and decryption fails loudly if the ciphertext or the associated data bound to it was modified.
import'package:cipherlib/cipherlib.dart';
import'package:cipherlib/codecs.dart';
import'package:cipherlib/random.dart';
voidmain() {
final key =randomBytes(32); // AES-256final nonce =randomBytes(12); // Recommended IV size for GCMfinal aad =toUtf8('order-id=INV-1001');
final plain =toUtf8('Ship 3 units to dock-7');
final aes =AES(key).gcm(nonce, aad: aad);
finalsealed= aes.encrypt(plain);
final opened = aes.decrypt(sealed);
print('AES-256-GCM');
print('key : ${toHex(key)}');
print('nonce : ${toHex(nonce)}');
print('aad : ${fromUtf8(aad)}');
print('cipher: ${toHex(sealed)}');
print('plain : ${fromUtf8(opened)}');
}Every snippet in this README is also a runnable program in the example folder.
| Algorithm | Public class and methods | Source |
|---|---|---|
| AES | AES | NIST.FIPS.197 |
| Blowfish | Blowfish | Blowfish-1993 |
| Twofish | Twofish | Twofish-1998 |
AES supports 10 modes:
ECB- Electronic CodebookCBC- Cipher Block ChainingCTR- CounterGCM- Galois/Counter Mode (authenticated)CCM- Counter with CBC-MAC (authenticated)CFB- Cipher FeedbackOFB- Output FeedbackIGE- Infinite Garble ExtensionPCBC- Propagating Cipher Block ChainingXTS- XEX Tweakable Block Cipher with Ciphertext Stealing
Blowfish and Twofish support 2 modes:
ECB- Electronic CodebookCBC- Cipher Block ChainingCTR- Counter
| Algorithm | Public class and methods | Source |
|---|---|---|
| XOR | XOR, xor | Wikipedia |
| ChaCha20 | ChaCha20, chacha20 | RFC-8439 |
| XChaCha20 | XChaCha20, xchacha20 | libsodium |
| Salsa20 | Salsa20, salsa20 | Snuffle-2005 |
| XSalsa20 | XSalsa20, xsalsa20 | libsodium |
| Algorithm | Public class and methods | Source |
|---|---|---|
| ChaCha20/Poly1305 | ChaCha20Poly1305, chacha20poly1305 | RFC-8439 |
| XChaCha20/Poly1305 | XChaCha20Poly1305, xchacha20poly1305 | libsodium |
| Salsa20/Poly1305 | Salsa20Poly1305, salsa20poly1305 | Snuffle-2005 |
| XSalsa20/Poly1305 | XSalsa20Poly1305, xsalsa20poly1305 | libsodium |
AES adds authenticated encryption through its GCM and CCM modes.
| Algorithm | Public class and methods | Source |
|---|---|---|
| ML-KEM | MLKEM | NIST.FIPS.203 |
MLKEM.kem512(), MLKEM.kem768(), and MLKEM.kem1024() provide key
generation, encapsulation, and decapsulation, with optional deterministic key
generation from a 64-byte seed.
- Never reuse a
(key, nonce)pair. For the stream ciphers and for AES-CTR/GCM/CCM, encrypting two messages under the same key and nonce destroys confidentiality — and for GCM/CCM it also lets an attacker forge tags. Use a fresh random nonce (or a strictly increasing counter) per message; XChaCha20/XSalsa20's 24-byte nonce is large enough to randomize safely. - AES is not constant-time. The pure-Dart AES uses table lookups, which are not guaranteed to run in constant time. Weigh the deployment environment before using it where cache-timing side channels matter.
- ML-KEM timing. The implementation follows the constant-time structure of the reference implementation, but Dart runtimes (JIT, AOT, dart2js) cannot guarantee constant-time execution. Consider the deployment environment before using ML-KEM in side-channel-sensitive settings.
A fast software AEAD, well suited to mobile and network protocols. The one-shot
function returns both the ciphertext (.data) and the tag (.mac); pass the
tag back on decryption and a mismatch throws.
import'package:cipherlib/cipherlib.dart';
import'package:cipherlib/codecs.dart';
import'package:cipherlib/random.dart';
voidmain() {
final key =randomBytes(32);
final nonce =randomBytes(12);
final aad =toUtf8('content-type=application/json');
final message =toUtf8('{"event":"payment.settled","id":42}');
finalsealed=chacha20poly1305(
message,
key,
nonce: nonce,
aad: aad,
);
final opened =chacha20poly1305(
sealed.data,
key,
nonce: nonce,
aad: aad,
mac:sealed.mac.bytes,
);
print('ChaCha20-Poly1305');
print('key : ${toHex(key)}');
print('nonce : ${toHex(nonce)}');
print('tag : ${sealed.mac.hex()}');
print('cipher: ${toHex(sealed.data)}');
print('plain : ${fromUtf8(opened.data)}');
}XChaCha20 widens the nonce to 24 bytes, so a random nonce per message is safe
without tracking a counter. Append poly1305 (xchacha20poly1305) for the
authenticated variant.
import'package:cipherlib/cipherlib.dart';
import'package:cipherlib/codecs.dart';
import'package:cipherlib/random.dart';
voidmain() {
final key =randomBytes(32);
final nonce =randomBytes(24); // Extended noncefinal plain =toUtf8('XChaCha20 extended nonce payload');
final cipher =xchacha20(plain, key, nonce: nonce);
final opened =xchacha20(cipher, key, nonce: nonce);
print('XChaCha20');
print('key : ${toHex(key)}');
print('nonce : ${toHex(nonce)}');
print('cipher: ${toHex(cipher)}');
print('plain : ${fromUtf8(opened)}');
}For interoperability with systems that expect classic block modes. AES.pkcs7
adds and strips padding automatically, and encryptString/decrypt handle the
UTF-8 conversion.
import'package:cipherlib/cipherlib.dart';
import'package:cipherlib/codecs.dart';
import'package:cipherlib/random.dart';
voidmain() {
final key =randomBytes(32);
final iv =randomBytes(16);
final plain ='Confidential invoice payload';
// PKCS7 is the common padding choice for block modes like CBC.final cbc =AES.pkcs7(key).cbc(iv);
final cipher = cbc.encryptString(plain);
final opened = cbc.decrypt(cipher);
print('AES-256-CBC + PKCS7');
print('key : ${toHex(key)}');
print('iv : ${toHex(iv)}');
print('cipher: ${toHex(cipher)}');
print('plain : ${fromUtf8(opened)}');
}Every stream cipher is a StreamTransformer<List<int>, Uint8List>, so a
Stream<List<int>> can be piped through cipher.bind(...) (or
stream.transform(cipher)) and processed chunk by chunk without buffering the
whole message in memory:
import'package:cipherlib/cipherlib.dart';
import'package:cipherlib/codecs.dart';
import'package:cipherlib/random.dart';
Future<void> main() async {
final key =randomBytes(32);
final nonce =randomBytes(12);
final chacha =ChaCha20(key, nonce);
final plainChunks =Stream<List<int>>.fromIterable([
toUtf8('a streamed '),
toUtf8('message'),
]);
awaitfor (final encrypted in chacha.bind(plainChunks)) {
print(toHex(encrypted));
}
}For byte-by-byte Stream<int> sources, use the stream() extension instead of
bind.
Authenticated ciphers reject modified input instead of returning garbage —
flipping a single bit of the tag makes decryption throw a StateError:
import'package:cipherlib/cipherlib.dart';
import'package:cipherlib/codecs.dart';
import'package:cipherlib/random.dart';
voidmain() {
final key =randomBytes(32);
final nonce =randomBytes(24);
finalsealed=xchacha20poly1305(
toUtf8('integrity protected'),
key,
nonce: nonce,
);
// Flip one bit of the tag to simulate tampering in transit.final badTag =List<int>.from(sealed.mac.bytes)..[0] ^=0xff;
try {
xchacha20poly1305(sealed.data, key, nonce: nonce, mac: badTag);
print('accepted (unexpected)');
} onStateErrorcatch (e) {
print('rejected: ${e.message}');
}
}Two parties agree on a shared secret that stays safe even against an attacker with a quantum computer. Alice publishes her encapsulation key; Bob derives a shared secret and a ciphertext from it; Alice recovers the same secret from the ciphertext.
import'package:cipherlib/cipherlib.dart';
import'package:cipherlib/codecs.dart';
voidmain() {
final kem =MLKEM.kem768();
// Alice generates a key pair and publishes the encapsulation keyfinal alice = kem.keygen();
// Bob encapsulates a shared secret with Alice's public key and// transmits the ciphertext back to Alicefinal bob = kem.encaps(alice.encapsulationKey);
// Alice recovers the same shared secret from the ciphertextfinal shared = kem.decaps(alice.decapsulationKey, bob.cipherText);
print(kem.name);
print('bob : ${bob.sharedSecret.hex()}');
print('alice : ${shared.hex()}');
print('match : ${shared.isEqual(bob.sharedSecret)}');
// A key pair can be stored as its 64-byte seed and re-derived laterfinal seed =List.generate(64, (i) => i);
final first = kem.keygen(seed: seed);
final again = kem.keygen(seed: seed);
final isSeeded =toHex(first.encapsulationKey) ==toHex(again.encapsulationKey);
print('seeded: $isSeeded');
}The shared secret is a HashDigest; compare it with isEqual (constant-time)
rather than ==, and derive symmetric keys from it with a KDF. A tampered
ciphertext does not throw — ML-KEM performs implicit rejection and returns a
deterministic but unrelated secret, so the two sides simply fail to agree.
- Cipherlib : https://pub.dev/packages/cipherlib
- PointyCastle : https://pub.dev/packages/pointycastle
- Cryptography : https://pub.dev/packages/cryptography
- PQCrypto : https://pub.dev/packages/pqcrypto
| Algorithm | Library | 1MB message | 1KB message | 32B message |
|---|---|---|---|---|
| XOR | cipherlib | ████████████████10.85 Gbps 🌟 | ████████████████11.1 Gbps 🌟 | ████████████████9.49 Gbps 🌟 |
| Salsa20 | cipherlib | ████████████████2.17 Gbps 🌟 | ████████████████2.13 Gbps 🌟 | ████████████████909 Mbps 🌟 |
| PointyCastle | ███░░░░░░░░░░░░░351 Mbps 🔻6.17x | ███░░░░░░░░░░░░░344 Mbps 🔻6.2x | ██░░░░░░░░░░░░░░133 Mbps 🔻6.84x | |
| Salsa20 / Poly1305 | cipherlib | ████████████████2.16 Gbps 🌟 | ████████████████2.02 Gbps 🌟 | ████████████████509 Mbps 🌟 |
| XSalsa20 | cipherlib | ████████████████2.16 Gbps 🌟 | ████████████████2.01 Gbps 🌟 | ████████████████517 Mbps 🌟 |
| XSalsa20 / Poly1305 | cipherlib | ████████████████2.16 Gbps 🌟 | ████████████████1.92 Gbps 🌟 | ████████████████360 Mbps 🌟 |
| ChaCha20 | cipherlib | ████████████████2.02 Gbps 🌟 | ████████████████2 Gbps 🌟 | ████████████████856 Mbps 🌟 |
| PointyCastle | ███░░░░░░░░░░░░░354 Mbps 🔻5.69x | ███░░░░░░░░░░░░░348 Mbps 🔻5.74x | ███░░░░░░░░░░░░░135 Mbps 🔻6.33x | |
| ChaCha20 / Poly1305 | cipherlib | ████████████████1.38 Gbps 🌟 | ████████████████1.26 Gbps 🌟 | ████████████████293 Mbps 🌟 |
| cryptography | ███░░░░░░░░░░░░░283 Mbps 🔻4.87x | ███░░░░░░░░░░░░░258 Mbps 🔻4.89x | ████░░░░░░░░░░░░66.66 Mbps 🔻4.4x | |
| PointyCastle | ███░░░░░░░░░░░░░275 Mbps 🔻5.01x | ███░░░░░░░░░░░░░256 Mbps 🔻4.93x | ██████░░░░░░░░░░116 Mbps 🔻2.53x | |
| XChaCha20 | cipherlib | ████████████████2.01 Gbps 🌟 | ████████████████1.88 Gbps 🌟 | ████████████████502 Mbps 🌟 |
| XChaCha20 / Poly1305 | cipherlib | ████████████████1.38 Gbps 🌟 | ████████████████1.25 Gbps 🌟 | ████████████████235 Mbps 🌟 |
| Algorithm | Library | 1MB message | 1KB message | 32B message |
|---|---|---|---|---|
| AES-128 / CBC | cipherlib | ████████████████1.46 Gbps 🌟 | ████████████████1.33 Gbps 🌟 | ████████████████338 Mbps 🌟 |
| cryptography | ███████████████░1.41 Gbps 🔻1.04x | ████████████░░░░1.02 Gbps 🔻1.31x | █████░░░░░░░░░░░107 Mbps 🔻3.16x | |
| PointyCastle | ███░░░░░░░░░░░░░231 Mbps 🔻6.3x | ██░░░░░░░░░░░░░░203 Mbps 🔻6.53x | ██░░░░░░░░░░░░░░44.35 Mbps 🔻7.61x | |
| AES-192 / CBC | cipherlib | ████████████████1.26 Gbps 🌟 | ████████████████1.16 Gbps 🌟 | ████████████████310 Mbps 🌟 |
| cryptography | ███████████████░1.21 Gbps 🔻1.04x | ████████████░░░░889 Mbps 🔻1.31x | █████░░░░░░░░░░░95.84 Mbps 🔻3.23x | |
| PointyCastle | ███░░░░░░░░░░░░░201 Mbps 🔻6.27x | ██░░░░░░░░░░░░░░177 Mbps 🔻6.57x | ██░░░░░░░░░░░░░░39.48 Mbps 🔻7.84x | |
| AES-256 / CBC | cipherlib | ████████████████1.11 Gbps 🌟 | ████████████████1.02 Gbps 🌟 | ████████████████269 Mbps 🌟 |
| cryptography | ███████████████░1.06 Gbps 🔻1.05x | ████████████░░░░783 Mbps 🔻1.3x | █████░░░░░░░░░░░86.94 Mbps 🔻3.09x | |
| PointyCastle | ███░░░░░░░░░░░░░178 Mbps 🔻6.22x | ██░░░░░░░░░░░░░░157 Mbps 🔻6.47x | ██░░░░░░░░░░░░░░36.37 Mbps 🔻7.39x | |
| AES-128 / CCM | cipherlib | ████████████████554 Mbps 🌟 | ████████████████524 Mbps 🌟 | ████████████████201 Mbps 🌟 |
| PointyCastle | ███░░░░░░░░░░░░░112 Mbps 🔻4.96x | ███░░░░░░░░░░░░░97.2 Mbps 🔻5.39x | ██░░░░░░░░░░░░░░19.61 Mbps 🔻10.24x | |
| AES-192 / CCM | cipherlib | ████████████████492 Mbps 🌟 | ████████████████468 Mbps 🌟 | ████████████████185 Mbps 🌟 |
| PointyCastle | ███░░░░░░░░░░░░░98.09 Mbps 🔻5.01x | ███░░░░░░░░░░░░░84.71 Mbps 🔻5.52x | █░░░░░░░░░░░░░░░16.54 Mbps 🔻11.21x | |
| AES-256 / CCM | cipherlib | ████████████████446 Mbps 🌟 | ████████████████423 Mbps 🌟 | ████████████████165 Mbps 🌟 |
| PointyCastle | ███░░░░░░░░░░░░░86.9 Mbps 🔻5.13x | ███░░░░░░░░░░░░░75.36 Mbps 🔻5.61x | █░░░░░░░░░░░░░░░15.38 Mbps 🔻10.76x | |
| AES-128 / CFB | cipherlib | ████████████████639 Mbps 🌟 | ████████████████629 Mbps 🌟 | ████████████████415 Mbps 🌟 |
| PointyCastle | █░░░░░░░░░░░░░░░3.66 Mbps 🔻174.44x | ███░░░░░░░░░░░░░107 Mbps 🔻5.9x | ██░░░░░░░░░░░░░░41.37 Mbps 🔻10.03x | |
| AES-192 / CFB | cipherlib | ████████████████558 Mbps 🌟 | ████████████████546 Mbps 🌟 | ████████████████385 Mbps 🌟 |
| PointyCastle | █░░░░░░░░░░░░░░░3.64 Mbps 🔻153.4x | ███░░░░░░░░░░░░░92.26 Mbps 🔻5.92x | ██░░░░░░░░░░░░░░36.57 Mbps 🔻10.53x | |
| AES-256 / CFB | cipherlib | ████████████████504 Mbps 🌟 | ████████████████494 Mbps 🌟 | ████████████████330 Mbps 🌟 |
| PointyCastle | █░░░░░░░░░░░░░░░3.61 Mbps 🔻139.45x | ███░░░░░░░░░░░░░82.72 Mbps 🔻5.97x | ██░░░░░░░░░░░░░░33.51 Mbps 🔻9.85x | |
| AES-128 / CTR | cipherlib | ████████████████1.51 Gbps 🌟 | ████████████████1.46 Gbps 🌟 | ████████████████596 Mbps 🌟 |
| cryptography | ████████░░░░░░░░734 Mbps 🔻2.05x | ██████░░░░░░░░░░579 Mbps 🔻2.52x | ██░░░░░░░░░░░░░░77.12 Mbps 🔻7.73x | |
| PointyCastle | ██░░░░░░░░░░░░░░219 Mbps 🔻6.88x | ██░░░░░░░░░░░░░░196 Mbps 🔻7.44x | █░░░░░░░░░░░░░░░47.99 Mbps 🔻12.42x | |
| AES-192 / CTR | cipherlib | ████████████████1.31 Gbps 🌟 | ████████████████1.27 Gbps 🌟 | ████████████████570 Mbps 🌟 |
| cryptography | ████████░░░░░░░░680 Mbps 🔻1.93x | ███████░░░░░░░░░545 Mbps 🔻2.34x | ██░░░░░░░░░░░░░░76.02 Mbps 🔻7.5x | |
| PointyCastle | ██░░░░░░░░░░░░░░193 Mbps 🔻6.82x | ██░░░░░░░░░░░░░░172 Mbps 🔻7.41x | █░░░░░░░░░░░░░░░42.99 Mbps 🔻13.26x | |
| AES-256 / CTR | cipherlib | ████████████████1.15 Gbps 🌟 | ████████████████1.11 Gbps 🌟 | ████████████████489 Mbps 🌟 |
| cryptography | █████████░░░░░░░634 Mbps 🔻1.82x | ███████░░░░░░░░░513 Mbps 🔻2.17x | ██░░░░░░░░░░░░░░73.71 Mbps 🔻6.63x | |
| PointyCastle | ██░░░░░░░░░░░░░░171 Mbps 🔻6.77x | ██░░░░░░░░░░░░░░154 Mbps 🔻7.22x | █░░░░░░░░░░░░░░░40.13 Mbps 🔻12.17x | |
| AES-128 / ECB | cipherlib | ████████████████1.49 Gbps 🌟 | ████████████████1.35 Gbps 🌟 | ████████████████350 Mbps 🌟 |
| PointyCastle | ███░░░░░░░░░░░░░249 Mbps 🔻5.97x | ███░░░░░░░░░░░░░217 Mbps 🔻6.2x | ██░░░░░░░░░░░░░░46.89 Mbps 🔻7.46x | |
| AES-192 / ECB | cipherlib | ████████████████1.28 Gbps 🌟 | ████████████████1.17 Gbps 🌟 | ████████████████322 Mbps 🌟 |
| PointyCastle | ███░░░░░░░░░░░░░215 Mbps 🔻5.94x | ███░░░░░░░░░░░░░189 Mbps 🔻6.2x | ██░░░░░░░░░░░░░░41.35 Mbps 🔻7.79x | |
| AES-256 / ECB | cipherlib | ████████████████1.12 Gbps 🌟 | ████████████████1.03 Gbps 🌟 | ████████████████278 Mbps 🌟 |
| PointyCastle | ███░░░░░░░░░░░░░189 Mbps 🔻5.96x | ███░░░░░░░░░░░░░167 Mbps 🔻6.17x | ██░░░░░░░░░░░░░░37.92 Mbps 🔻7.34x | |
| AES-128 / GCM | cipherlib | ████████████████237 Mbps 🌟 | ████████████████352 Mbps 🌟 | ████████████████63.12 Mbps 🌟 |
| cryptography | ███████████░░░░░157 Mbps 🔻1.51x | ███████████░░░░░250 Mbps 🔻1.41x | █████████████░░░49.76 Mbps 🔻1.27x | |
| PointyCastle | █░░░░░░░░░░░░░░░12.67 Mbps 🔻18.71x | █░░░░░░░░░░░░░░░15.58 Mbps 🔻22.57x | █░░░░░░░░░░░░░░░5.09 Mbps 🔻12.39x | |
| AES-192 / GCM | cipherlib | ████████████████233 Mbps 🌟 | ████████████████350 Mbps 🌟 | ████████████████61.76 Mbps 🌟 |
| cryptography | ███████████░░░░░158 Mbps 🔻1.47x | ███████████░░░░░244 Mbps 🔻1.43x | ████████████░░░░48.22 Mbps 🔻1.28x | |
| PointyCastle | █░░░░░░░░░░░░░░░12.59 Mbps 🔻18.47x | █░░░░░░░░░░░░░░░15.24 Mbps 🔻22.96x | █░░░░░░░░░░░░░░░4.94 Mbps 🔻12.51x | |
| AES-256 / GCM | cipherlib | ████████████████226 Mbps 🌟 | ████████████████333 Mbps 🌟 | ████████████████60.5 Mbps 🌟 |
| cryptography | ███████████░░░░░151 Mbps 🔻1.5x | ███████████░░░░░229 Mbps 🔻1.45x | ████████████░░░░45.65 Mbps 🔻1.33x | |
| PointyCastle | █░░░░░░░░░░░░░░░12.45 Mbps 🔻18.18x | █░░░░░░░░░░░░░░░15.25 Mbps 🔻21.83x | █░░░░░░░░░░░░░░░4.95 Mbps 🔻12.23x | |
| AES-128 / IGE | cipherlib | ████████████████1.41 Gbps 🌟 | ████████████████1.3 Gbps 🌟 | ████████████████356 Mbps 🌟 |
| PointyCastle | ██░░░░░░░░░░░░░░210 Mbps 🔻6.73x | ██░░░░░░░░░░░░░░186 Mbps 🔻6.99x | ██░░░░░░░░░░░░░░43.57 Mbps 🔻8.17x | |
| AES-192 / IGE | cipherlib | ████████████████1.23 Gbps 🌟 | ████████████████1.14 Gbps 🌟 | ████████████████329 Mbps 🌟 |
| PointyCastle | ██░░░░░░░░░░░░░░184 Mbps 🔻6.65x | ██░░░░░░░░░░░░░░164 Mbps 🔻6.92x | ██░░░░░░░░░░░░░░38.67 Mbps 🔻8.51x | |
| AES-256 / IGE | cipherlib | ████████████████1.08 Gbps 🌟 | ████████████████998 Mbps 🌟 | ████████████████286 Mbps 🌟 |
| PointyCastle | ██░░░░░░░░░░░░░░165 Mbps 🔻6.52x | ██░░░░░░░░░░░░░░148 Mbps 🔻6.76x | ██░░░░░░░░░░░░░░35.75 Mbps 🔻8x | |
| AES-128 / OFB | cipherlib | ████████████████637 Mbps 🌟 | ████████████████628 Mbps 🌟 | ████████████████425 Mbps 🌟 |
| PointyCastle | ███░░░░░░░░░░░░░120 Mbps 🔻5.31x | ███░░░░░░░░░░░░░113 Mbps 🔻5.54x | ██░░░░░░░░░░░░░░42.35 Mbps 🔻10.03x | |
| AES-192 / OFB | cipherlib | ████████████████550 Mbps 🌟 | ████████████████552 Mbps 🌟 | ████████████████396 Mbps 🌟 |
| PointyCastle | ███░░░░░░░░░░░░░104 Mbps 🔻5.3x | ███░░░░░░░░░░░░░97.81 Mbps 🔻5.64x | ██░░░░░░░░░░░░░░37.25 Mbps 🔻10.64x | |
| AES-256 / OFB | cipherlib | ████████████████500 Mbps 🌟 | ████████████████494 Mbps 🌟 | ████████████████341 Mbps 🌟 |
| PointyCastle | ███░░░░░░░░░░░░░91.42 Mbps 🔻5.47x | ███░░░░░░░░░░░░░86.64 Mbps 🔻5.7x | ██░░░░░░░░░░░░░░34.42 Mbps 🔻9.92x | |
| AES-128 / PCBC | cipherlib | ████████████████1.45 Gbps 🌟 | ████████████████1.34 Gbps 🌟 | ████████████████383 Mbps 🌟 |
| AES-192 / PCBC | cipherlib | ████████████████1.25 Gbps 🌟 | ████████████████1.17 Gbps 🌟 | ████████████████347 Mbps 🌟 |
| AES-256 / PCBC | cipherlib | ████████████████1.11 Gbps 🌟 | ████████████████1.03 Gbps 🌟 | ████████████████298 Mbps 🌟 |
| AES-128 / XTS | cipherlib | ████████████████1.42 Gbps 🌟 | ████████████████1.29 Gbps 🌟 | ████████████████333 Mbps 🌟 |
| AES-192 / XTS | cipherlib | ████████████████1.23 Gbps 🌟 | ████████████████1.13 Gbps 🌟 | ████████████████265 Mbps 🌟 |
| AES-256 / XTS | cipherlib | ████████████████1.09 Gbps 🌟 | ████████████████978 Mbps 🌟 | ████████████████256 Mbps 🌟 |
| Algorithm | Library | 1MB message | 1KB message | 32B message |
|---|---|---|---|---|
| Twofish-128 / ECB | cipherlib | ████████████████1.08 Gbps 🌟 | ████████████████638 Mbps 🌟 | ████████████████45.85 Mbps 🌟 |
| PointyCastle | █░░░░░░░░░░░░░░░1.84 Mbps 🔻585.2x | █████████░░░░░░░339 Mbps 🔻1.88x | ███████████████░41.74 Mbps 🔻1.1x | |
| Twofish-192 / ECB | cipherlib | ████████████████1.06 Gbps 🌟 | ████████████████567 Mbps 🌟 | ████████████████36.05 Mbps 🌟 |
| PointyCastle | █░░░░░░░░░░░░░░░1.8 Mbps 🔻590.1x | █████████░░░░░░░321 Mbps 🔻1.76x | ███████████████░34.12 Mbps 🔻1.06x | |
| Twofish-256 / ECB | cipherlib | ████████████████1.07 Gbps 🌟 | ████████████████499 Mbps 🌟 | ████████████████28.31 Mbps |
| PointyCastle | █░░░░░░░░░░░░░░░1.83 Mbps 🔻582.99x | ██████████░░░░░░304 Mbps 🔻1.64x | ████████████████28.97 Mbps 🔺1.02x | |
| Twofish-128 / CBC | cipherlib | ████████████████1.06 Gbps 🌟 | ████████████████632 Mbps 🌟 | ████████████████46.42 Mbps 🌟 |
| PointyCastle | █░░░░░░░░░░░░░░░3.62 Mbps 🔻291.97x | ████████░░░░░░░░325 Mbps 🔻1.94x | ██████████████░░40.59 Mbps 🔻1.14x | |
| Twofish-192 / CBC | cipherlib | ████████████████1.05 Gbps 🌟 | ████████████████560 Mbps 🌟 | ████████████████36.14 Mbps 🌟 |
| PointyCastle | █░░░░░░░░░░░░░░░3.6 Mbps 🔻291.63x | █████████░░░░░░░307 Mbps 🔻1.82x | ███████████████░33.4 Mbps 🔻1.08x | |
| Twofish-256 / CBC | cipherlib | ████████████████1.05 Gbps 🌟 | ████████████████496 Mbps 🌟 | ████████████████28.23 Mbps |
| PointyCastle | █░░░░░░░░░░░░░░░3.67 Mbps 🔻286.45x | █████████░░░░░░░293 Mbps 🔻1.69x | ████████████████28.36 Mbps 🔺1x | |
| Twofish-128 / CTR | cipherlib | ████████████████1.03 Gbps 🌟 | ████████████████619 Mbps 🌟 | ████████████████46.41 Mbps 🌟 |
| PointyCastle | ███████░░░░░░░░░422 Mbps 🔻2.43x | ████████░░░░░░░░328 Mbps 🔻1.89x | ██████████████░░40.26 Mbps 🔻1.15x | |
| Twofish-192 / CTR | cipherlib | ████████████████1.03 Gbps 🌟 | ████████████████556 Mbps 🌟 | ████████████████35.99 Mbps 🌟 |
| PointyCastle | ███████░░░░░░░░░426 Mbps 🔻2.42x | █████████░░░░░░░311 Mbps 🔻1.79x | ███████████████░33.26 Mbps 🔻1.08x | |
| Twofish-256 / CTR | cipherlib | ████████████████1.04 Gbps 🌟 | ████████████████491 Mbps 🌟 | ████████████████28.32 Mbps 🌟 |
| PointyCastle | ███████░░░░░░░░░427 Mbps 🔻2.42x | ██████████░░░░░░295 Mbps 🔻1.66x | ████████████████28.15 Mbps 🔻1.01x | |
| Blowfish-128 / ECB | cipherlib | ████████████████755 Mbps 🌟 | ████████████████77.07 Mbps 🌟 | ████████████████2.81 Mbps 🌟 |
| PointyCastle | █░░░░░░░░░░░░░░░1.82 Mbps 🔻414.53x | █████████████░░░64.66 Mbps 🔻1.19x | ██████████████░░2.4 Mbps 🔻1.17x | |
| Blowfish-256 / ECB | cipherlib | ████████████████760 Mbps 🌟 | ████████████████78.54 Mbps 🌟 | ████████████████2.62 Mbps 🌟 |
| PointyCastle | █░░░░░░░░░░░░░░░1.77 Mbps 🔻429.53x | █████████████░░░63.87 Mbps 🔻1.23x | ███████████████░2.38 Mbps 🔻1.1x | |
| Blowfish-448 / ECB | cipherlib | ████████████████707 Mbps 🌟 | ████████████████78.69 Mbps 🌟 | ████████████████2.74 Mbps 🌟 |
| PointyCastle | █░░░░░░░░░░░░░░░1.77 Mbps 🔻399.76x | █████████████░░░64.31 Mbps 🔻1.22x | ██████████████░░2.34 Mbps 🔻1.17x | |
| Blowfish-128 / CBC | cipherlib | ████████████████699 Mbps 🌟 | ████████████████76.81 Mbps 🌟 | ████████████████2.69 Mbps 🌟 |
| PointyCastle | █░░░░░░░░░░░░░░░3.45 Mbps 🔻202.76x | █████████████░░░62.03 Mbps 🔻1.24x | ██████████████░░2.3 Mbps 🔻1.17x | |
| Blowfish-256 / CBC | cipherlib | ████████████████689 Mbps 🌟 | ████████████████77.55 Mbps 🌟 | ████████████████2.72 Mbps 🌟 |
| PointyCastle | █░░░░░░░░░░░░░░░3.52 Mbps 🔻195.93x | █████████████░░░61.94 Mbps 🔻1.25x | ██████████████░░2.34 Mbps 🔻1.16x | |
| Blowfish-448 / CBC | cipherlib | ████████████████699 Mbps 🌟 | ████████████████79.48 Mbps 🌟 | ████████████████2.63 Mbps 🌟 |
| PointyCastle | █░░░░░░░░░░░░░░░3.48 Mbps 🔻200.51x | █████████████░░░62.34 Mbps 🔻1.28x | ██████████████░░2.29 Mbps 🔻1.15x | |
| Blowfish-128 / CTR | cipherlib | ████████████████763 Mbps 🌟 | ████████████████78.47 Mbps 🌟 | ████████████████2.79 Mbps 🌟 |
| PointyCastle | ████████░░░░░░░░403 Mbps 🔻1.9x | █████████████░░░62.67 Mbps 🔻1.25x | █████████████░░░2.33 Mbps 🔻1.2x | |
| Blowfish-256 / CTR | cipherlib | ████████████████767 Mbps 🌟 | ████████████████78.86 Mbps 🌟 | ████████████████2.82 Mbps 🌟 |
| PointyCastle | ████████░░░░░░░░406 Mbps 🔻1.89x | █████████████░░░64.4 Mbps 🔻1.22x | ██████████████░░2.39 Mbps 🔻1.18x | |
| Blowfish-448 / CTR | cipherlib | ████████████████787 Mbps 🌟 | ████████████████81.16 Mbps 🌟 | ████████████████2.78 Mbps 🌟 |
| PointyCastle | ████████░░░░░░░░413 Mbps 🔻1.91x | █████████████░░░64.71 Mbps 🔻1.25x | ██████████████░░2.37 Mbps 🔻1.17x |
| Algorithm | Library | Key Generation | Encapsulation | Decapsulation |
|---|---|---|---|---|
| ML-KEM-512 | cipherlib | ████████████████20.1 Mbps 🌟 | ████████████████204 Mbps 🌟 | ████████████████165 Mbps 🌟 |
| pqcrypto | ██░░░░░░░░░░░░░░2.29 Mbps 🔻8.77x | ██░░░░░░░░░░░░░░22.76 Mbps 🔻8.95x | ██░░░░░░░░░░░░░░20.18 Mbps 🔻8.17x | |
| ML-KEM-768 | cipherlib | ████████████████12.4 Mbps 🌟 | ████████████████183 Mbps 🌟 | ████████████████153 Mbps 🌟 |
| pqcrypto | ██░░░░░░░░░░░░░░1.34 Mbps 🔻9.23x | ██░░░░░░░░░░░░░░19.13 Mbps 🔻9.59x | ██░░░░░░░░░░░░░░16.92 Mbps 🔻9.04x | |
| ML-KEM-1024 | cipherlib | ████████████████8.11 Mbps 🌟 | ████████████████179 Mbps 🌟 | ████████████████152 Mbps 🌟 |
| pqcrypto | ██░░░░░░░░░░░░░░824 Kbps 🔻9.84x | ██░░░░░░░░░░░░░░17.7 Mbps 🔻10.11x | ██░░░░░░░░░░░░░░15.97 Mbps 🔻9.5x |
All benchmarks are done on 36GB Apple M3 Pro using compiled exe
Dart SDK version: 3.12.2 (stable) (Tue Jun 9 01:11:39 2026 -0700) on "macos_arm64"
BSD 3-Clause License. See the LICENSE file for details. Issues and contributions are welcome at github.com/bitanon/cipherlib.