Pointy Castle

Dart VM Chrome Node JS

A Dart library for encryption and decryption. In this release, most of the classes are ports of Bouncy Castle from Java to Dart. The porting is almost always direct except for some classes that had been added to ease the use of low level data.

To make sure nothing fails, tests and benchmarks for every algorithm are provided. The expected results are taken from the Bouncy Castle Java version and also from standards, and matched against the results got from Pointy Castle.

This library was adopted from the original project at https://github.com/PointyCastle/pointycastle at the request of the authors to help support ongoing development. A list of major contributors is provided at contributors.md

This library is now ported to non-nullable-by-default, a breaking language feature released by the Dart team! See https://dart.dev/null-safety and https://dart.dev/null-safety/migration-guide for more details. Please note that both null-safe and non-null-safe versions are available (v3.x.x-nullsafety for null-safe, v2.x.x for non-null-safe). However, only the null-safe version of this library is actively maintained.

Algorithms

Pointycastle implements a large set of algorithms. They must be instantiated and then initialized with their parameters. Different algorithms have different parameter classes, which represent the arguments to that algorithm. The relevant parameter type is provided for all the algorithms. To initialize an algorithm, call the init method:

var algorithmVar = /* instantiate algorithm using registry here */ ;
var parameter = /* instantiate relevant parameter class here */ ;
algorithmVar.init(parameter);

Some algorithms will ask for more than just a parameter object in the initialization step. Once you have identified the classes you intend to use in your project, it is recommended that you view the API docs at https://pub.dev/documentation/pointycastle/latest/ to find the specifics of the methods from the class you want to use.

In this release, the following algorithms are implemented:

(Most of the below are keywords for algorithms which can be used directly with the registry. The registry is an easy way to instantiate classes in PointyCastle. See "Using the Registry" for more).

AEAD ciphers: To use with the registry, instantiate like this AEADCipher('ChaCha20-Poly1305'). Ciphers use AEADParameters to initialize.

  • 'ChaCha20-Poly1305'
  • 'AES/EAX'

Block ciphers: To use with the registry, instantiate like this PaddedBlockCipher('AES/SomeBlockModeHere/SomePaddingHere') or like this StreamCipher('AES/SomeStreamModeHere'). See sections below for modes and paddings.

  • 'AES'
  • Note that block ciphers can be used in stream cipher modes of operation

Block modes of operation: Most modes use ParametersWithIV to initialize. ECB uses KeyParameter and GCM uses AEADParameters.

  • 'CBC' (Cipher Block Chaining mode)
  • 'ECB' (Electronic Code Book mode)
  • 'CFB-64' (Cipher Feedback mode, using blocks)
  • 'GCTR' (GOST 28147 OFB counter mode, using blocks)
  • 'OFB-64' (Output FeedBack mode, using blocks)
  • 'CTR'/'SIC' (Counter mode, using blocks)
  • 'IGE' (Infinite Garble Extension)
  • Authenticated block modes of operation
    • 'GCM' (Galois-Counter mode)
    • 'CCM' (counter with CBC-MAC)

Stream modes of operation: All modes use ParametersWithIV to initialize.

  • 'CTR'/'SIC' (Counter mode, as a traditional stream)

Paddings:

  • 'PKCS7'
  • 'ISO7816-4'

Asymmetric block ciphers: Instantiate using the registry like this AsymmetricBlockCipher('RSA/SomeEncodingHere'). Initialization requires a RSAPrivateKey or RSAPublicKey.

  • 'RSA'

Asymmetric block cipher encodings:

  • 'PKCS1'
  • 'OAEP'

Stream ciphers: Instantiation using registry is like this StreamCipher('ChaCha20/20'). Initialization requires a ParametersWithIV.

  • 'Salsa20'
  • 'ChaCha20/(# of rounds)' (original implementation)
  • 'ChaCha7539/(# of rounds)' (RFC-7539 implementation)
  • If you don't know how many ChaCha rounds to use, use 20.

Digests: Instantiate using registry like this Digest('Keccak/384'). No initialization is necessary.

  • 'Blake2b'
  • 'MD2'
  • 'MD4'
  • 'MD5'
  • 'RIPEMD-128|160|256|320'
  • 'SHA-1'
  • 'SHA-224|256|384|512'
  • 'SHA-512/t' (t=8 to 376 and 392 to 504 in multiples of 8)
  • 'Keccak/224|256|384|512'
  • 'SHA3-224|256|384|512'
  • 'Tiger'
  • 'Whirlpool'
  • 'SM3'

MACs: Instantiate using registry like this Mac('SomeBlockCipher/CMAC') or Mac('SomeDigest/HMAC) or Mac(SomeBlockCipher/Poly1305). CMAC and HMAC require a KeyParameter and Poly1305 requires a ParametersWithIV.

  • 'HMAC'
  • 'CMAC'
  • 'Poly1305'

Signatures: Instantiate using registry like this Signer('SomeDigestHere/(DET-)ECDSA') or Signer('SomeDigestHere/RSA')

  • '(DET-)ECDSA'
  • 'RSA'

Password based key derivators: Instantiation using registry like this KeyDerivator('SomeDigestHere/HMAC/PBKDF2') or KeyDerivator('scrypt/argon2'). To initialize, you'll need a Pbkdf2Parameters, ScryptParameters, or Argon2Parameters.

  • 'PBKDF2'
  • 'scrypt'
  • 'argon2'

HMAC based key derivators: Instantiate using registry like this KeyDerivator('SomeDigestHere/HKDF'). To initialize, use an HkdfParameters.

  • 'HKDF'

Asymmetric key generators Instantiate using registry like this KeyDerivator('RSA'). To initialize, use ECKeyGeneratorParameters or RSAKeyGeneratorParameters.

  • 'ECDSA'
  • 'RSA'

Secure PRNGs:

  • Based on block cipher in CTR mode
  • Based on block cipher in CTR mode with auto reseed (for forward security)
  • Based on Fortuna algorithm

Instantiating implementation objects

There are two ways to instantiate objects that implement the algorithms:

  • using the registry, or
  • without the registry.

Using the registry

Using the registry, the algorithm name is provided to high-level class factories.

This is especially convenient when an algorithm involves multiple algorithm implementation classes to implement. All the necessary classes can all be instantiated with a single name (e.g. "SHA-256/HMAC" or "SHA-1/HMAC/PBKDF2" or "AES/CBC/PKCS7"), and they are automatically combined together with the correct values.

For example,

final sha256 = Digest("SHA-256");
final sha1 = Digest("SHA-1");
final md5 = Digest("MD5");

final hmacSha256 = Mac("SHA-256/HMAC");
final hmacSha1 = Mac("SHA-1/HMAC");
final hmacMd5 = Mac("MD5/HMAC");

final derivator = KeyDerivator("SHA-1/HMAC/PBKDF2");

final signer = Signer("SHA-256/RSA");

Without the registry

Without the registry, each implementation class must be instantiated using its constructor.

If an algorithm involves multiple algorithm implementation classes, they each have to be individually instantiated and combined together with the correct values.

For example,

final sha256 = SHA256Digest();
final sha1 = SHA1Digest();
final md5 = MD5Digest();

final hmacSha256 = HMac(SHA256Digest(), 64);
final hmacSha512 = HMac(SHA512Digest(), 128);
final hmacMd5 = HMac(MD5Digest(), 64);

final derivator = PBKDF2KeyDerivator(HMac(SHA256Digest(), 64));

final signer = RSASigner(SHA256Digest(), '0609608648016503040201');

Registry vs without registry

Using the registry means that all algorithms will be imported by default, which can increase the compiled size of your program.

To avoid this, instantiate all classes directly by using the constructors. But which classes can be instantiated with its constructor will depend on which libraries have been imported.

Importing libraries

A program can take one of these three approaches for importing Point Castle libraries:

  • only import pointycastle.dart;
  • only import exports.dart; or
  • import api.dart and individual libraries as needed.

Only import pointycastle.dart

The "pointycastle.dart" file exports:

  • the high-level API; and
  • implementations of the interfaces.

But it does not export any of the algorithm implementation classes.

import "package:pointycastle/pointycastle.dart";

With this import, none of the implementation classes can be instantiated directly. The program can only use the registry.

For example,

final sha256 = Digest("SHA-256");
// final md5 = MD5Digest(); // not available
final p = Padding("PKCS7");
// final s = FortunaRandom(); // not available

Only import exports.dart

The "export.dart" file exports:

  • the high-level API,
  • implementations of the interfaces; and
  • every algorithm implementation class.

That is, everything!

import "package:pointycastle/export.dart";

With this import, all of the implementation classes can be instantiated directly. The program can also use the registry.

For example, this works without any additional imports:

final sha256 = Digest("SHA-256");
final md5 = MD5Digest();
final p = Padding("PKCS7");
final s = FortunaRandom();

Import api.dart and individual libraries

The "api.dart" exports only:

  • the high-level API.

It does not include the implementations of the interfaces, nor any algorithm implementation class.

import "package:pointycastle/api.dart";
// additional imports will be needed

With this import, only some of the implementation classes can be instantiated directly (i.e. those that are also explicitly imported). The program can also use the registry.

For example, the following only works because of the additional imports:

// In addition to "package:pointycastle/api.dart":
import "package:pointycastle/digests/sha256.dart";
import "package:pointycastle/digests/md5.dart"
import 'package:pointycastle/paddings/pkcs7.dart';

final sha256 = Digest("SHA-256");
final md5 = MD5Digest();
final p = Padding("PKCS7");
// final s = FortunaRandom(); // not available without 'package:pointycastle/random/fortuna_random.dart'

Tutorials

Some articles on how to use some of Pointy Castle's features can be found under the tutorials directory in the sources.

  • Calculating a digest - calculating a hash or digest (e.g. SHA-256, SHA-1, MD5)
  • Calculating a HMAC - calculating a hash-based message authentication code (e.g. HMAC-SHA256, HMAC-SHA1)
  • Using AES-CBC - block encryption and decryption with AES-CBC
  • Using RSA - key generation, signing/verifying, and encryption/decryption
  • Some tips on using Pointy Castle

Note: the above links are to the most recent versions on the master branch on GitHub. They may be different from the version on pub.dev.

Libraries

api
This is the API specification library for the Pointy Castle project.
asymmetric/api
ecc/api
key_derivators/api
key_generators/api
key_derivators/argon2
key_derivators/argon2_native_int_impl
key_derivators/argon2_register64_impl
asn1
asn1/x509/asn1_algorithm_identifier
asn1/x501/asn1_attribute_type_and_value
asn1/pkcs/pkcs12/asn1_authenticated_safe
asn1/primitives/asn1_bit_string
asn1/primitives/asn1_bmp_string
asn1/primitives/asn1_boolean
asn1/pkcs/pkcs12/asn1_cert_bag
asn1/pkcs/pkcs10/asn1_certification_request
asn1/pkcs/pkcs10/asn1_certification_request_info
asn1/pkcs/pkcs7/asn1_content_info
asn1/pkcs/pkcs1/asn1_digest_info
asn1/asn1_encoding_rule
asn1/pkcs/pkcs7/asn1_encrypted_content_info
asn1/pkcs/pkcs8/asn1_encrypted_data
asn1/pkcs/pkcs8/asn1_encrypted_private_key_info
asn1/primitives/asn1_enumerated
asn1/primitives/asn1_generalized_time
asn1/primitives/asn1_ia5_string
asn1/primitives/asn1_integer
asn1/pkcs/pkcs12/asn1_key_bag
asn1/pkcs/pkcs12/asn1_mac_data
asn1/x501/asn1_name
asn1/primitives/asn1_null
asn1/asn1_object
asn1/primitives/asn1_object_identifier
asn1/primitives/asn1_octet_string
asn1/asn1_parser
asn1/pkcs/pkcs12/asn1_pfx
asn1/pkcs/pkcs12/asn1_pkcs12_attribute
asn1/primitives/asn1_printable_string
asn1/pkcs/pkcs8/asn1_private_key_info
asn1/x501/asn1_rdn
asn1/pkcs/pkcs12/asn1_safe_bag
asn1/pkcs/pkcs12/asn1_safe_contents
asn1/primitives/asn1_sequence
asn1/primitives/asn1_set
asn1/pkcs/pkcs10/asn1_subject_public_key_info
asn1/asn1_tags
asn1/primitives/asn1_teletext_string
asn1/primitives/asn1_utc_time
asn1/primitives/asn1_utf8_string
asn1/asn1_utils
key_derivators/concat_kdf
block/des_base
block/desede_engine
ecc/ecdh
key_derivators/ecdh_kdf
export
This library exports all implementation classes from the entire PointyCastle project.
impl
This library contains all out-of-the-box implementations of the interfaces provided in the API which are compatible with client and server sides.
adapters/stream_cipher_as_block_cipher
asymmetric/ec_elgamal
asymmetric/oaep
asymmetric/pkcs1
asymmetric/rsa
block/aes
block/aes_fast
block/modes/cbc
block/modes/ccm
block/modes/cfb
block/modes/ctr
block/modes/ecb
block/modes/gcm
block/modes/gctr
block/modes/ige
block/modes/ofb
block/modes/sic
digests/blake2b
digests/cshake
digests/keccak
digests/md2
digests/md4
digests/md5
digests/ripemd128
digests/ripemd160
digests/ripemd256
digests/ripemd320
digests/sha1
digests/sha3
digests/sha224
digests/sha256
digests/sha384
digests/sha512
digests/sha512t
digests/shake
digests/sm3
digests/tiger
digests/xof_utils
digests/whirlpool
ecc/curves/brainpoolp160r1
ecc/curves/brainpoolp160t1
ecc/curves/brainpoolp192r1
ecc/curves/brainpoolp192t1
ecc/curves/brainpoolp224r1
ecc/curves/brainpoolp224t1
ecc/curves/brainpoolp256r1
ecc/curves/brainpoolp256t1
ecc/curves/brainpoolp320r1
ecc/curves/brainpoolp320t1
ecc/curves/brainpoolp384r1
ecc/curves/brainpoolp384t1
ecc/curves/brainpoolp512r1
ecc/curves/brainpoolp512t1
ecc/curves/gostr3410_2001_cryptopro_a
ecc/curves/gostr3410_2001_cryptopro_b
ecc/curves/gostr3410_2001_cryptopro_c
ecc/curves/gostr3410_2001_cryptopro_xcha
ecc/curves/gostr3410_2001_cryptopro_xchb
ecc/curves/prime192v1
ecc/curves/prime192v2
ecc/curves/prime192v3
ecc/curves/prime239v1
ecc/curves/prime239v2
ecc/curves/prime239v3
ecc/curves/prime256v1
ecc/curves/secp112r1
ecc/curves/secp112r2
ecc/curves/secp128r1
ecc/curves/secp128r2
ecc/curves/secp160k1
ecc/curves/secp160r1
ecc/curves/secp160r2
ecc/curves/secp192k1
ecc/curves/secp192r1
ecc/curves/secp224k1
ecc/curves/secp224r1
ecc/curves/secp256k1
ecc/curves/secp256r1
ecc/curves/secp384r1
ecc/curves/secp521r1
ecc/ecc_base
ecc/ecc_fp
key_derivators/hkdf
key_derivators/pbkdf2
key_derivators/scrypt
key_generators/ec_key_generator
key_generators/rsa_key_generator
macs/cbc_block_cipher_mac
macs/cmac
macs/hmac
macs/poly1305
padded_block_cipher/padded_block_cipher_impl
paddings/iso7816d4
paddings/pkcs7
random/auto_seed_block_ctr_random
random/block_ctr_random
random/fortuna_random
signers/ecdsa_signer
signers/pss_signer
signers/rsa_signer
srp/srp6_client
srp/srp6_server
stream/chacha20
stream/chacha20poly1305
stream/chacha7539
stream/ctr
stream/eax
stream/rc4_engine
stream/salsa20
stream/sic
asn1/object_identifiers
asn1/object_identifiers_database
key_derivators/pkcs5s1_parameter_generator
key_derivators/pkcs12_parameter_generator
pointycastle
This is the main entry point to the cipher library API.
block/rc2_engine
srp/srp6_standard_groups
srp/srp6_util
srp/srp6_verifier_generator
asn1/unsupported_asn1_encoding_rule_exception
asn1/unsupported_asn1_tag_exception
asn1/unsupported_object_identifier_exception