cryptography

Creator: coderz1093

Last updated:

Add to Cart

Description:

cryptography

Overview #
Popular cryptographic algorithms for Dart / Flutter
developers.
Maintained by gohilla.com. Licensed under the Apache License 2.0.
This package is designed to be:

Easy to use. The API is easy to understand and encourages good defaults.
Multi-platform. It's easy to customize implementation of X in platform Y.
Fast. We use platform APIs when available. For example, SHA-512 is over 100 times faster than
package:crypto in browsers.

Any feedback, issue reports, or pull requests are appreciated!
Links #

Github project
Issue tracker
Pub package
API reference

Getting started #
If you use Flutter, it's recommended (but not necessarily) that you also import our sibling package
cryptography_flutter, which delegates calls to
Android / iOS / Mac OS X operating system APIs whenever possible.
In pubspec.yaml:
dependencies:
cryptography: ^2.7.0
cryptography_flutter: ^2.3.2 # Remove if you don't use Flutter
copied to clipboard
You are ready to go!
Issues and discussions #
Please report bugs at github.com/dint-dev/cryptography/issues.
Having questions? Feel free to use our Github Discussions at
github.com/dint-dev/cryptography/discussions.
Some things to know #
General guidance on cryptography #
Please read information about Mobile App Cryptography
by OWASP. It contains a lot of useful information that helps you build more secure software.
Common parameters #

SecretKey

Used by ciphers, message authentication codes, and key derivation functions.


KeyPair

SimpleKeyPair
(Octet sequences such as Ed25519 / X25519 32-byte private keys)
EcKeyPairData
(P-256, P-384, P-521 private keys)
RsaKeyPairData
(RSA private keys)


PublicKey

SimplePublicKey
(Octet sequences such as Ed25519 / X25519 32-byte public keys)
EcPublicKey
(P-256 / P-384 / P-512 public keys)
RsaPublicKey
(RSA public keys)



Note that SecretKey and KeyPair instances are opaque and asynchronous by default. They may not be in
the memory and may not be readable at all. If a SecretKey or KeyPair instance is in memory, it's an
instance of one of the following:

SecretKeyData
SimpleKeyPairData
EcKeyPairData
RsaKeyPairData

For encoding/decoding private/public keys in JWK (JSON Web Key) format, use
package:jwk.
For encoding/decoding X.509, PKCS12, and other formats, we don't have recommended packages
at the moment.
Wands (recommended) #
For a bit higher API abstraction and sometimes a performance boost, we encourage developers to use
Wand
instances which do operations with fixed, "invisible" key (thus "magic wands"). There are currently
three types of wands:

CipherWand
KeyExchangeWand
SignatureWand

In the future version 3.x, we plan to transition to wands as the default API for doing operations.
Ciphers #
The following Cipher
implementations are available:

AES

AesCbc (
AES-CBC)

The throughput is up to 120 MB / second (Macbook Pro, message size 1 MB).


AesCtr (
AES-CTR)

The throughput is up to 80 MB / second (Macbook Pro, message size 1 MB).


AesGcm (
AES-GCM)

The throughput is up to 20 MB / second (Macbook Pro, message size 1 MB).


In browsers, the package uses Web Cryptography, reaching over 500 MB/s.


ChaCha20 / XChaCha20

Chacha20

The throughput is up to 230 MB / second (Macbook Pro, message size 1 MB).


Chacha20.poly1305Aead (
AEAD_CHACHA20_POLY1305)

The throughput is up to 30 MB / second (Macbook Pro, message size 1 MB).


Xchacha20
Xchacha20.poly1305Aead (
AEAD_XCHACHA20_POLY1305)



Digital signature algorithms #
The
following SignatureAlgorithm
implementations are available:

Ed25519 (
curve25519 EdDSA)

Performance of the pure Dart implementation is around 200 (signatures or verifications) per
second in VM and about 50 in browsers.


Elliptic curves approved by NIST

Ecdsa.p256 (
ECDSA P256 / secp256r1 / prime256v1 + SHA256)
Ecdsa.p384 (
ECDSA P384 / secp384r1 / prime384v1 + SHA384)
Ecdsa.p521 (
ECDSA P521 / secp521r1 / prime521v1 + SHA256)
We don't have implementations of these in pure Dart.


RSA

RsaPss (
RSA-PSS)
RsaSsaPkcs1v15 (
RSASSA-PKCS1v15)
We don't have implementations of these in pure Dart.



Key exchange algorithms #
The following KeyExchangeAlgorithm
implementations are available:

Elliptic curves approved by NIST

Ecdh.p256 (
ECDH P256 / secp256r1 / prime256v1)
Ecdh.p384 (
ECDH P384 / secp384r1 / prime384v1)
Ecdh.p521 (
ECDH P521 / secp521r1 / prime521v1)
We don't have implementations of these in pure Dart.


X25519 (
curve25519 Diffie-Hellman)

Throughput of the pure Dart implementation is around 1000 key agreements per second (in VM).



Key derivation / password hashing algorithms #
The following KdfAlgorithm implementations are available:

Hchacha20
Hkdf
Pbkdf2
Argon2id

Argon2id is the recommended algorithm for password hashing.



Message authentication codes #
The following MacAlgorithm
implementations are available:

Blake2b
Blake2s
Hmac
Poly1305

Cryptographic hash functions #
The following HashAlgorithm
implementations are available:

Blake2b
(BLAKE2B)
Blake2s
(BLAKE2S)
Sha1 (SHA1)
Sha224
(SHA2-224)
Sha256
(SHA2-256)
Sha384
(SHA2-384)
Sha512
(SHA2-512)

The performance is excellent! Our pure Dart implementation of Sha256 is around 2 times faster than
implementation in the older "package:crypto" because of inlining and smarter integer use. If you do
lots of small hashes, the advantage is even bigger because this package allows you re-use the hash
state. Therefore our HMAC-SHA256 is much faster too. In browsers, hashes can be over 100 times
faster because this package automatically uses Web Crypto API.
Random number generators #
We use Dart SDK Random.secure()
as the default random number in all APIs.
If you do want much faster cryptographically reasonably strong random numbers, this package contains
SecureRandom.fast.
It generates random numbers by using 12 round version ChaCha cipher. It can generate up to 0.25 GB
random data per second because it makes expensive operating system call less frequently after the
initial seeding from the operating system. While ChaCha is not designed to be a cryptographic random
number generator, it can be acceptable and a related (Blake2-based) RNG is used by Linux kernel.
If you need a deterministic random number generator for tests, the package contains
SecureRandom.forTesting,
which uses the aforementioned ChaCha-based RNG with a fixed seed and no re-seeding.
Cryptographic factory class #
The class Cryptography
has factory methods that return implementations of cryptographic algorithms. The default
implementation is BrowserCryptography (which works in all platforms, not just browser).
We wrote the following three implementations of Cryptography:

DartCryptography

Gives you implementations written in pure Dart implementations. They work in all platforms.
The algorithms are written and tested by us. They are are licensed under the Apache 2.0 License.
See the class documentation
for list algorithms supported by it.


BrowserCryptography

Uses Web Cryptography API
(crypto.subtle) whenever possible. Methods return pure Dart implementations when Web
Cryptography API is not available.
See the class documentation
for list algorithms supported by it.


FlutterCryptography

Makes cryptographic algorithms up to 100 times faster in Android, iOS, and Mac OS X.
Available in the package cryptography_flutter.
See the class documentation
for list algorithms supported by it.



Deterministic behavior in tests #
If you want to have deterministic behavior in tests, you can supply your own random number
generator:
For example:
import 'package:cryptography/cryptography.dart';

void main() {
setUp(() {
Cryptography.instance = Cryptography.instance.withRandom(SecureRandom.forTesting(seed: 42));
});

test('example', () async {
final algorithm = AesGcm.with256bits();

// This will will always return the same secret key.
// because we use a deterministic random number generator.
final secretKey = await algorithm.newSecretKey();

// ...
});
}
copied to clipboard
Examples #
Digital signature #
In this example, we use
Ed25519,
a popular signature algorithm:
import 'package:cryptography/cryptography.dart';

Future<void> main() async {
// The message that we will sign
final message = <int>[1, 2, 3];

// Generate a keypair.
final algorithm = Ed25519();
final keyPair = await algorithm.newKeyPair();

// Sign
final signature = await algorithm.sign(
message,
keyPair: keyPair,
);
print('Signature: ${signature.bytes}');
print('Public key: ${signature.publicKey.bytes}');

// Verify signature
final isSignatureCorrect = await algorithm.verify(
message,
signature: signature,
);
print('Correct signature: $isSignatureCorrect');
}
copied to clipboard
Key agreement #
In this example, we
use X25519,
a popular key agreement algorithm:
import 'package:cryptography/cryptography.dart';

Future<void> main() async {
final algorithm = X25519();

// Alice chooses her key pair
final aliceKeyPair = await algorithm.newKeyPair();

// Alice knows Bob's public key
final bobKeyPair = await algorithm.newKeyPair();
final bobPublicKey = await bobKeyPair.extractPublicKey();

// Alice calculates the shared secret.
final sharedSecret = await algorithm.sharedSecretKey(
keyPair: aliceKeyPair,
remotePublicKey: bobPublicKey,
);
final sharedSecretBytes = await aliceKeyPair.extractBytes();
print('Shared secret: $sharedSecretBytes');
}
copied to clipboard
Authenticated encryption #
When you encrypt, you need:

Clear text (bytes you are encrypting)
SecretKey.
You can generate a random secret key with
cipher.newSecretKey().
An optional nonce (also known as "IV", "Initialization Vector", "salt"), which is some
non-secret byte sequence that MUST be unique each time you encrypt. If you don't provide a
nonce, a random nonce will be automatically generated for you.

The output of encrypting is SecretBox
that contains the nonce, the cipher text (the encrypted message), and
Mac (a message
authentication code).
When you decrypt, you need the SecretBox and the secret key.
In the following example, we encrypt a message
with AesGcm:
import 'dart:convert';
import 'package:cryptography/cryptography.dart';

Future<void> main() async {
// Choose the cipher
final algorithm = AesGcm.with256bits();

// Generate a random secret key.
final secretKey = await algorithm.newSecretKey();
final secretKeyBytes = await secretKey.extractBytes();
print('Secret key: ${secretKeyBytes}');

// Encrypt
final secretBox = await algorithm.encryptString(
'Hello!',
secretKey: secretKey,
);
print('Nonce: ${secretBox.nonce}'); // Randomly generated nonce
print('Ciphertext: ${secretBox.cipherText}'); // Encrypted message
print('MAC: ${secretBox.mac}'); // Message authentication code

// If you are sending the secretBox somewhere, you can concatenate all parts of it:
final concatenatedBytes = secretBox.concatenation();
print('All three parts concatenated: $concatenatedBytes');

// Decrypt
final clearText = await algorithm.decryptString(
secretBox,
secretKey: secretKey,
);
print('Cleartext: $clearText'); // Hello!
}
copied to clipboard
Password hashing #
In this example, we use Argon2id:
import 'package:cryptography/cryptography.dart';

Future<void> main() async {
final algorithm = Argon2id(
memory: 10*1000, // 10 MB
parallelism: 2, // Use maximum two CPU cores.
iterations: 1, // For more security, you should usually raise memory parameter, not iterations.
hashLength: 32, // Number of bytes in the returned hash
);

final secretKey = await algorithm.deriveKeyFromPassword(
password: 'qwerty',
nonce: [1, 2, 3],
);
final secretKeyBytes = await secretKey.extractBytes();

print('Hash: ${secretKeyBytes}');
}
copied to clipboard
Hashing #
In this example, we use Sha256:
import 'package:cryptography/cryptography.dart';

Future<void> main() async {
final sink = Sha256().newHashSink();

// Add all parts of the authenticated message
sink.add([1, 2, 3]);
sink.add([4, 5]);
sink.add([6]);

// Calculate hash
sink.close();
final hash = await sink.hash();

print('SHA-512 hash: ${hash.bytes}');
}
copied to clipboard

License

For personal and professional use. You cannot resell or redistribute these repositories in their original state.

Customer Reviews

There are no reviews.