Skip to content

Repository files navigation

cipherlib

package versiondart supportlikespub pointscodecovTestAsk DeepWiki

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:

convertlibhashlibcipherlib

It reuses hashlib for the SHA-3/SHAKE, Poly1305, and secure-random primitives it is built on, and that is its only runtime dependency.

Highlights

  • 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 a StreamTransformer.
  • Post-quantum ready: ML-KEM-512/768/1024 (FIPS 203) for quantum-resistant key exchange.
  • Fast: consistently outruns PointyCastle and cryptography, see in the benchmarks below.

Install

dependencies:
cipherlib: ^0.7.1

or 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'; // randomBytes

Full API reference: cipherlib library.

Quickstart

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.

Supported algorithms

Block ciphers

AlgorithmPublic class and methodsSource
AESAESNIST.FIPS.197
BlowfishBlowfishBlowfish-1993
TwofishTwofishTwofish-1998

AES supports 10 modes:

  • ECB - Electronic Codebook
  • CBC - Cipher Block Chaining
  • CTR - Counter
  • GCM - Galois/Counter Mode (authenticated)
  • CCM - Counter with CBC-MAC (authenticated)
  • CFB - Cipher Feedback
  • OFB - Output Feedback
  • IGE - Infinite Garble Extension
  • PCBC - Propagating Cipher Block Chaining
  • XTS - XEX Tweakable Block Cipher with Ciphertext Stealing

Blowfish and Twofish support 2 modes:

  • ECB - Electronic Codebook
  • CBC - Cipher Block Chaining
  • CTR - Counter

Stream ciphers

AlgorithmPublic class and methodsSource
XORXOR, xorWikipedia
ChaCha20ChaCha20, chacha20RFC-8439
XChaCha20XChaCha20, xchacha20libsodium
Salsa20Salsa20, salsa20Snuffle-2005
XSalsa20XSalsa20, xsalsa20libsodium

Authenticated encryption (AEAD)

AlgorithmPublic class and methodsSource
ChaCha20/Poly1305ChaCha20Poly1305, chacha20poly1305RFC-8439
XChaCha20/Poly1305XChaCha20Poly1305, xchacha20poly1305libsodium
Salsa20/Poly1305Salsa20Poly1305, salsa20poly1305Snuffle-2005
XSalsa20/Poly1305XSalsa20Poly1305, xsalsa20poly1305libsodium

AES adds authenticated encryption through its GCM and CCM modes.

Post-Quantum Cryptography

AlgorithmPublic class and methodsSource
ML-KEMMLKEMNIST.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.

Security notes

  • 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.

Recipes

ChaCha20-Poly1305

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 (extended nonce)

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)}');
}

AES-CBC with PKCS#7 padding

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)}');
}

Streaming large data

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.

Detecting tampering

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}');
}
}

Post-quantum key exchange (ML-KEM)

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.

Benchmarks

Libraries

Stream Ciphers

AlgorithmLibrary1MB message1KB message32B message
XORcipherlib████████████████
10.85 Gbps 🌟
████████████████
11.1 Gbps 🌟
████████████████
9.49 Gbps 🌟
Salsa20cipherlib████████████████
2.17 Gbps 🌟
████████████████
2.13 Gbps 🌟
████████████████
909 Mbps 🌟
PointyCastle███░░░░░░░░░░░░░
351 Mbps 🔻6.17x
███░░░░░░░░░░░░░
344 Mbps 🔻6.2x
██░░░░░░░░░░░░░░
133 Mbps 🔻6.84x
Salsa20 / Poly1305cipherlib████████████████
2.16 Gbps 🌟
████████████████
2.02 Gbps 🌟
████████████████
509 Mbps 🌟
XSalsa20cipherlib████████████████
2.16 Gbps 🌟
████████████████
2.01 Gbps 🌟
████████████████
517 Mbps 🌟
XSalsa20 / Poly1305cipherlib████████████████
2.16 Gbps 🌟
████████████████
1.92 Gbps 🌟
████████████████
360 Mbps 🌟
ChaCha20cipherlib████████████████
2.02 Gbps 🌟
████████████████
2 Gbps 🌟
████████████████
856 Mbps 🌟
PointyCastle███░░░░░░░░░░░░░
354 Mbps 🔻5.69x
███░░░░░░░░░░░░░
348 Mbps 🔻5.74x
███░░░░░░░░░░░░░
135 Mbps 🔻6.33x
ChaCha20 / Poly1305cipherlib████████████████
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
XChaCha20cipherlib████████████████
2.01 Gbps 🌟
████████████████
1.88 Gbps 🌟
████████████████
502 Mbps 🌟
XChaCha20 / Poly1305cipherlib████████████████
1.38 Gbps 🌟
████████████████
1.25 Gbps 🌟
████████████████
235 Mbps 🌟

AES

AlgorithmLibrary1MB message1KB message32B message
AES-128 / CBCcipherlib████████████████
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 / CBCcipherlib████████████████
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 / CBCcipherlib████████████████
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 / CCMcipherlib████████████████
554 Mbps 🌟
████████████████
524 Mbps 🌟
████████████████
201 Mbps 🌟
PointyCastle███░░░░░░░░░░░░░
112 Mbps 🔻4.96x
███░░░░░░░░░░░░░
97.2 Mbps 🔻5.39x
██░░░░░░░░░░░░░░
19.61 Mbps 🔻10.24x
AES-192 / CCMcipherlib████████████████
492 Mbps 🌟
████████████████
468 Mbps 🌟
████████████████
185 Mbps 🌟
PointyCastle███░░░░░░░░░░░░░
98.09 Mbps 🔻5.01x
███░░░░░░░░░░░░░
84.71 Mbps 🔻5.52x
█░░░░░░░░░░░░░░░
16.54 Mbps 🔻11.21x
AES-256 / CCMcipherlib████████████████
446 Mbps 🌟
████████████████
423 Mbps 🌟
████████████████
165 Mbps 🌟
PointyCastle███░░░░░░░░░░░░░
86.9 Mbps 🔻5.13x
███░░░░░░░░░░░░░
75.36 Mbps 🔻5.61x
█░░░░░░░░░░░░░░░
15.38 Mbps 🔻10.76x
AES-128 / CFBcipherlib████████████████
639 Mbps 🌟
████████████████
629 Mbps 🌟
████████████████
415 Mbps 🌟
PointyCastle█░░░░░░░░░░░░░░░
3.66 Mbps 🔻174.44x
███░░░░░░░░░░░░░
107 Mbps 🔻5.9x
██░░░░░░░░░░░░░░
41.37 Mbps 🔻10.03x
AES-192 / CFBcipherlib████████████████
558 Mbps 🌟
████████████████
546 Mbps 🌟
████████████████
385 Mbps 🌟
PointyCastle█░░░░░░░░░░░░░░░
3.64 Mbps 🔻153.4x
███░░░░░░░░░░░░░
92.26 Mbps 🔻5.92x
██░░░░░░░░░░░░░░
36.57 Mbps 🔻10.53x
AES-256 / CFBcipherlib████████████████
504 Mbps 🌟
████████████████
494 Mbps 🌟
████████████████
330 Mbps 🌟
PointyCastle█░░░░░░░░░░░░░░░
3.61 Mbps 🔻139.45x
███░░░░░░░░░░░░░
82.72 Mbps 🔻5.97x
██░░░░░░░░░░░░░░
33.51 Mbps 🔻9.85x
AES-128 / CTRcipherlib████████████████
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 / CTRcipherlib████████████████
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 / CTRcipherlib████████████████
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 / ECBcipherlib████████████████
1.49 Gbps 🌟
████████████████
1.35 Gbps 🌟
████████████████
350 Mbps 🌟
PointyCastle███░░░░░░░░░░░░░
249 Mbps 🔻5.97x
███░░░░░░░░░░░░░
217 Mbps 🔻6.2x
██░░░░░░░░░░░░░░
46.89 Mbps 🔻7.46x
AES-192 / ECBcipherlib████████████████
1.28 Gbps 🌟
████████████████
1.17 Gbps 🌟
████████████████
322 Mbps 🌟
PointyCastle███░░░░░░░░░░░░░
215 Mbps 🔻5.94x
███░░░░░░░░░░░░░
189 Mbps 🔻6.2x
██░░░░░░░░░░░░░░
41.35 Mbps 🔻7.79x
AES-256 / ECBcipherlib████████████████
1.12 Gbps 🌟
████████████████
1.03 Gbps 🌟
████████████████
278 Mbps 🌟
PointyCastle███░░░░░░░░░░░░░
189 Mbps 🔻5.96x
███░░░░░░░░░░░░░
167 Mbps 🔻6.17x
██░░░░░░░░░░░░░░
37.92 Mbps 🔻7.34x
AES-128 / GCMcipherlib████████████████
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 / GCMcipherlib████████████████
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 / GCMcipherlib████████████████
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 / IGEcipherlib████████████████
1.41 Gbps 🌟
████████████████
1.3 Gbps 🌟
████████████████
356 Mbps 🌟
PointyCastle██░░░░░░░░░░░░░░
210 Mbps 🔻6.73x
██░░░░░░░░░░░░░░
186 Mbps 🔻6.99x
██░░░░░░░░░░░░░░
43.57 Mbps 🔻8.17x
AES-192 / IGEcipherlib████████████████
1.23 Gbps 🌟
████████████████
1.14 Gbps 🌟
████████████████
329 Mbps 🌟
PointyCastle██░░░░░░░░░░░░░░
184 Mbps 🔻6.65x
██░░░░░░░░░░░░░░
164 Mbps 🔻6.92x
██░░░░░░░░░░░░░░
38.67 Mbps 🔻8.51x
AES-256 / IGEcipherlib████████████████
1.08 Gbps 🌟
████████████████
998 Mbps 🌟
████████████████
286 Mbps 🌟
PointyCastle██░░░░░░░░░░░░░░
165 Mbps 🔻6.52x
██░░░░░░░░░░░░░░
148 Mbps 🔻6.76x
██░░░░░░░░░░░░░░
35.75 Mbps 🔻8x
AES-128 / OFBcipherlib████████████████
637 Mbps 🌟
████████████████
628 Mbps 🌟
████████████████
425 Mbps 🌟
PointyCastle███░░░░░░░░░░░░░
120 Mbps 🔻5.31x
███░░░░░░░░░░░░░
113 Mbps 🔻5.54x
██░░░░░░░░░░░░░░
42.35 Mbps 🔻10.03x
AES-192 / OFBcipherlib████████████████
550 Mbps 🌟
████████████████
552 Mbps 🌟
████████████████
396 Mbps 🌟
PointyCastle███░░░░░░░░░░░░░
104 Mbps 🔻5.3x
███░░░░░░░░░░░░░
97.81 Mbps 🔻5.64x
██░░░░░░░░░░░░░░
37.25 Mbps 🔻10.64x
AES-256 / OFBcipherlib████████████████
500 Mbps 🌟
████████████████
494 Mbps 🌟
████████████████
341 Mbps 🌟
PointyCastle███░░░░░░░░░░░░░
91.42 Mbps 🔻5.47x
███░░░░░░░░░░░░░
86.64 Mbps 🔻5.7x
██░░░░░░░░░░░░░░
34.42 Mbps 🔻9.92x
AES-128 / PCBCcipherlib████████████████
1.45 Gbps 🌟
████████████████
1.34 Gbps 🌟
████████████████
383 Mbps 🌟
AES-192 / PCBCcipherlib████████████████
1.25 Gbps 🌟
████████████████
1.17 Gbps 🌟
████████████████
347 Mbps 🌟
AES-256 / PCBCcipherlib████████████████
1.11 Gbps 🌟
████████████████
1.03 Gbps 🌟
████████████████
298 Mbps 🌟
AES-128 / XTScipherlib████████████████
1.42 Gbps 🌟
████████████████
1.29 Gbps 🌟
████████████████
333 Mbps 🌟
AES-192 / XTScipherlib████████████████
1.23 Gbps 🌟
████████████████
1.13 Gbps 🌟
████████████████
265 Mbps 🌟
AES-256 / XTScipherlib████████████████
1.09 Gbps 🌟
████████████████
978 Mbps 🌟
████████████████
256 Mbps 🌟

Blowfish & Twofish

AlgorithmLibrary1MB message1KB message32B message
Twofish-128 / ECBcipherlib████████████████
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 / ECBcipherlib████████████████
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 / ECBcipherlib████████████████
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 / CBCcipherlib████████████████
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 / CBCcipherlib████████████████
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 / CBCcipherlib████████████████
1.05 Gbps 🌟
████████████████
496 Mbps 🌟
████████████████
28.23 Mbps
PointyCastle█░░░░░░░░░░░░░░░
3.67 Mbps 🔻286.45x
█████████░░░░░░░
293 Mbps 🔻1.69x
████████████████
28.36 Mbps 🔺1x
Twofish-128 / CTRcipherlib████████████████
1.03 Gbps 🌟
████████████████
619 Mbps 🌟
████████████████
46.41 Mbps 🌟
PointyCastle███████░░░░░░░░░
422 Mbps 🔻2.43x
████████░░░░░░░░
328 Mbps 🔻1.89x
██████████████░░
40.26 Mbps 🔻1.15x
Twofish-192 / CTRcipherlib████████████████
1.03 Gbps 🌟
████████████████
556 Mbps 🌟
████████████████
35.99 Mbps 🌟
PointyCastle███████░░░░░░░░░
426 Mbps 🔻2.42x
█████████░░░░░░░
311 Mbps 🔻1.79x
███████████████░
33.26 Mbps 🔻1.08x
Twofish-256 / CTRcipherlib████████████████
1.04 Gbps 🌟
████████████████
491 Mbps 🌟
████████████████
28.32 Mbps 🌟
PointyCastle███████░░░░░░░░░
427 Mbps 🔻2.42x
██████████░░░░░░
295 Mbps 🔻1.66x
████████████████
28.15 Mbps 🔻1.01x
Blowfish-128 / ECBcipherlib████████████████
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 / ECBcipherlib████████████████
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 / ECBcipherlib████████████████
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 / CBCcipherlib████████████████
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 / CBCcipherlib████████████████
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 / CBCcipherlib████████████████
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 / CTRcipherlib████████████████
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 / CTRcipherlib████████████████
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 / CTRcipherlib████████████████
787 Mbps 🌟
████████████████
81.16 Mbps 🌟
████████████████
2.78 Mbps 🌟
PointyCastle████████░░░░░░░░
413 Mbps 🔻1.91x
█████████████░░░
64.71 Mbps 🔻1.25x
██████████████░░
2.37 Mbps 🔻1.17x

Key Encapsulation

AlgorithmLibraryKey GenerationEncapsulationDecapsulation
ML-KEM-512cipherlib████████████████
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-768cipherlib████████████████
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-1024cipherlib████████████████
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"

License

BSD 3-Clause License. See the LICENSE file for details. Issues and contributions are welcome at github.com/bitanon/cipherlib.

About

Implementations of cryptographic algorithms for encryption and decryption in Dart

Topics

Resources

Security policy

Stars

10 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages