Pointy Castle

Build Status

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

Algorithms

In this release, the following algorithms are implemented.

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

(The relevant parameter type is provided for all the algorithms. To initialize an algorithm, call algorithm.init(paramsHere).)

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

  • 'ChaCha20-Poly1305'

Block ciphers: To use with the registry, instantiate like this PaddedBlockCipher('AES/SomeBlockModeHere/SomePaddingHere') or like this StreamCipher('AES/SomeStreamModeHere').

  • '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)
  • Authenticated block modes of operation
    • 'GCM' (Galois-Counter mode)

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'
  • 'SHA-3/224|256|384|512'
  • 'Tiger'
  • 'Whirlpool'

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'). To initialize, you'll need a Pbkdf2Parameters or ScryptParameters.

  • 'PBKDF2'
  • 'scrypt'

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. [...]
api.asymmetric
api.ecc
api.key_derivators
api.key_generators
asn1
asn1_bit_string
asn1_boolean
asn1_encoding_rule
asn1_enumerated
asn1_generalized_time
asn1_ia5_string
asn1_integer
asn1_null
asn1_object
asn1_object_identifier
asn1_octet_string
asn1_parser
asn1_printable_string
asn1_sequence
asn1_set
asn1_tags
asn1_teletext_string
asn1_utc_time
asn1_utf8_string
asn1_utils
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.
impl.adapters.stream_cipher_as_block_cipher
impl.asymmetric_block_cipher.oeap
impl.asymmetric_block_cipher.pkcs1
impl.asymmetric_block_cipher.rsa
impl.block_cipher.aes_fast
impl.block_cipher.modes.cbc
impl.block_cipher.modes.cfb
impl.block_cipher.modes.ctr
impl.block_cipher.modes.ecb
impl.block_cipher.modes.gcm
impl.block_cipher.modes.gctr
impl.block_cipher.modes.ofb
impl.block_cipher.modes.sic
impl.digest.blake2b
impl.digest.cshake
impl.digest.keccak
impl.digest.md2
impl.digest.md4
impl.digest.md5
impl.digest.ripemd128
impl.digest.ripemd160
impl.digest.ripemd256
impl.digest.ripemd320
impl.digest.sha1
impl.digest.sha3
impl.digest.sha224
impl.digest.sha256
impl.digest.sha384
impl.digest.sha512
impl.digest.sha512t
impl.digest.shake
impl.digest.tiger
impl.digest.utils
impl.digest.whirlpool
impl.ec_domain_parameters.brainpoolp160r1
impl.ec_domain_parameters.brainpoolp160t1
impl.ec_domain_parameters.brainpoolp192r1
impl.ec_domain_parameters.brainpoolp192t1
impl.ec_domain_parameters.brainpoolp224r1
impl.ec_domain_parameters.brainpoolp224t1
impl.ec_domain_parameters.brainpoolp256r1
impl.ec_domain_parameters.brainpoolp256t1
impl.ec_domain_parameters.brainpoolp320r1
impl.ec_domain_parameters.brainpoolp320t1
impl.ec_domain_parameters.brainpoolp384r1
impl.ec_domain_parameters.brainpoolp384t1
impl.ec_domain_parameters.brainpoolp512r1
impl.ec_domain_parameters.brainpoolp512t1
impl.ec_domain_parameters.gostr3410_2001_cryptopro_a
impl.ec_domain_parameters.gostr3410_2001_cryptopro_b
impl.ec_domain_parameters.gostr3410_2001_cryptopro_c
impl.ec_domain_parameters.gostr3410_2001_cryptopro_xcha
impl.ec_domain_parameters.gostr3410_2001_cryptopro_xchb
impl.ec_domain_parameters.prime192v1
impl.ec_domain_parameters.prime192v2
impl.ec_domain_parameters.prime192v3
impl.ec_domain_parameters.prime239v1
impl.ec_domain_parameters.prime239v2
impl.ec_domain_parameters.prime239v3
impl.ec_domain_parameters.prime256v1
impl.ec_domain_parameters.secp112r1
impl.ec_domain_parameters.secp112r2
impl.ec_domain_parameters.secp128r1
impl.ec_domain_parameters.secp128r2
impl.ec_domain_parameters.secp160k1
impl.ec_domain_parameters.secp160r1
impl.ec_domain_parameters.secp160r2
impl.ec_domain_parameters.secp192k1
impl.ec_domain_parameters.secp192r1
impl.ec_domain_parameters.secp224k1
impl.ec_domain_parameters.secp224r1
impl.ec_domain_parameters.secp256k1
impl.ec_domain_parameters.secp256r1
impl.ec_domain_parameters.secp384r1
impl.ec_domain_parameters.secp521r1
impl.ecc.ecc_base
impl.ecc.ecc_fp
impl.key_derivator.hkdf
impl.key_derivator.pbkdf2
impl.key_derivator.scrypt
impl.key_generator.ec_key_generator
impl.key_generator.rsa_key_generator
impl.mac.cbc_block_cipher_mac
impl.mac.cmac
impl.mac.hmac
impl.mac.poly1305
impl.padded_block_cipher.padded_block_cipher_impl
impl.padding.iso7816d4
impl.padding.pkcs7
impl.secure_random.auto_seed_block_ctr_random
impl.secure_random.block_ctr_random
impl.secure_random.fortuna_random
impl.signer.ecdsa_signer
impl.signer.pss_signer
impl.signer.rsa_signer
impl.stream_cipher.chacha20
impl.stream_cipher.chacha20poly1305
impl.stream_cipher.chacha7539
impl.stream_cipher.ctr
impl.stream_cipher.salsa20
impl.stream_cipher.sic
object_identifiers
pointycastle
This is the main entry point to the cipher library API. [...]
unsupported_asn1_encoding_rule_exception
unsupported_asn1_tag_exception
unsupported_object_identifier_exception