Skip to content

bitanon/cipherlib

Repository files navigation

cipherlib

package version dart support likes pub points codecov Test Ask 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, fromUtf8
import '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';

void main() {
  final key = randomBytes(32); // AES-256
  final nonce = randomBytes(12); // Recommended IV size for GCM
  final aad = toUtf8('order-id=INV-1001');
  final plain = toUtf8('Ship 3 units to dock-7');

  final aes = AES(key).gcm(nonce, aad: aad);
  final sealed = 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

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

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

Authenticated encryption (AEAD)

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.

Post-Quantum Cryptography

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.

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

void main() {
  final key = randomBytes(32);
  final nonce = randomBytes(12);
  final aad = toUtf8('content-type=application/json');
  final message = toUtf8('{"event":"payment.settled","id":42}');

  final sealed = 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';

void main() {
  final key = randomBytes(32);
  final nonce = randomBytes(24); // Extended nonce
  final 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';

void main() {
  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'),
  ]);

  await for (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';

void main() {
  final key = randomBytes(32);
  final nonce = randomBytes(24);
  final sealed = 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)');
  } on StateError catch (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';

void main() {
  final kem = MLKEM.kem768();

  // Alice generates a key pair and publishes the encapsulation key
  final alice = kem.keygen();

  // Bob encapsulates a shared secret with Alice's public key and
  // transmits the ciphertext back to Alice
  final bob = kem.encaps(alice.encapsulationKey);

  // Alice recovers the same shared secret from the ciphertext
  final 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 later
  final 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

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 🌟

AES

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 🌟

Blowfish & Twofish

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

Key Encapsulation

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"

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

License

Security policy

Stars

10 stars

Watchers

1 watching

Forks

Sponsor this project

Packages

 
 
 

Contributors

Languages