cppcrypto library

1. Introduction 2. Hash algorithms 3. MAC algorithms 4. Block cipher algorithms 5. Block cipher encryption modes 6. Stream cipher algorithms 7. Key derivation functions 8. Digest utility 9. Portability notes 10. Download link

1. Introduction

cppcrypto is a small cross-platform BSD-licensed C++ library providing some cryptographic primitives. It has no external dependencies.

The library thrives to be as fast as possible. CPU type is detected at runtime and the fastest implementation is selected dynamically.

Supported compilers: Visual C++ 2013, Visual C++ 2015 on Windows; gcc 5.1.1 or later, clang 3.4.1 or later on Linux, OS X, FreeBSD; Solaris Studio on Solaris.
Supported architectures: x86_64 and x86.

Download cppcrypto from sourceforge

Full list of supported cryptographic primitives is described below.

2. Hash algorithms

2.1. Interface description

All hash algorithms derive from crypto_hash class and implement its interface.

    class crypto_hash
    {
    public:
        virtual void init() = 0;
        virtual void update(const uint8_t* data, size_t len) = 0;
        virtual void final(uint8_t* hash) = 0;

        virtual size_t hashsize() const = 0;
        virtual size_t blocksize() const = 0;

        // Convenience functions
        void hash_string(const uint8_t* data, size_t len, uint8_t* hash);
        void hash_string(const char* data, size_t len, uint8_t* hash);
        void hash_string(const std::string& data, uint8_t* hash);
    };

If you have a short message, you can calculate the hash using a single hash_string() call. Otherwise, call init() to start hashing, then call update() any number of times to add the next chunk of data, and finally call final() to get the hash.
The hash parameter should point to a buffer large enough to accept the hash of correspondent size (length in bytes is hashsize()/8).

2.2. Supported algorithms

Classes derived from crypto_hash:

Class NameDescription
blake224
blake256
blake384
blake512
BLAKE hash function (one of SHA-3 finalists) with output sizes 224/256/384/512 bits.
This is one of the fastest hash functions and we recommend it you are free to choose.
blake2b_128
blake2b_160
blake2b_224
blake2b_256
blake2b_384
blake2b_512
BLAKE2b hash function with output sizes 128/160/224/256/384/512 bits.
This is a version of BLAKE-512 with reduced number of rounds and other simplifications.
blake2s_128
blake2s_160
blake2s_224
blake2s_256
BLAKE2s hash function with output sizes 128/160/224/256 bits.
This is a version of BLAKE-256 with reduced number of rounds and other simplifications.
groestl224
groestl256
groestl384
groestl512
Grøstl hash function (one of SHA-3 finalists) with output sizes 224/256/384/512 bits.
jh224
jh256
jh384
jh512
JH hash function (one of SHA-3 finalists) with output sizes 224/256/384/512 bits.
kupyna256
kupyna512
Kupyna hash function (Ukrainian national standard DSTU 7564:2014) with output sizes 256/512 bits.
224/384-bit functions are not provided because their output is identical to the truncated 256/512-bit output.
md5 MD5 hash function. Not secure and therefore not recommended; use only if you need it for compatibility.
sha1 SHA-1 hash function. Not secure and therefore not recommended; use only if you need it for compatibility.
sha224
sha256
sha384
sha512
sha512_224
sha512_256
SHA-2 hash function (NIST standard FIPS 180-4).
New functions sha512_224 and sha512_256 are faster than sha224 and sha256 on 64-bit platforms.
Individual functions are known as SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224 and SHA-512/256.
sha3_224
sha3_256
sha3_384
sha3_512
SHA-3 hash function (NIST standard FIPS 202) based on Keccak algorithm.
skein256_128
skein256_160
skein256_224
skein256_256
Skein hash function (one of SHA-3 finalists) with block size 256 bits and output sizes 128/160/224/256 bits.
These functions are slower than skein512, so use them only if you need them for compatibility.
skein512_128
skein512_160
skein512_224
skein512_256
skein512_384
skein512_512
Skein hash function (one of SHA-3 finalists) with block size 512 bits and output sizes 128/160/224/256/384/512 bits.
This is one of the fastest hash functions and we recommend it if you are free to choose.
skein1024_256
skein1024_384
skein1024_512
skein1024_1024
Skein hash function (one of SHA-3 finalists) with block size 1024 bits and output sizes 256/384/512/1024 bits.
sm3 SM3 hash function (Chinese national standard) with output size 256 bits.
streebog256
streebog512
Streebog hash function (Russian standard GOST R 34.11-2012) with output sizes 256/512 bits.
whirlpool Whirlpool hash function (recommended by NESSIE) with output size 512 bits.

2.3. Usage example

The following snippet calculates BLAKE-256 hash of a string using a single function call:

    uint8_t hash[256/8];
    blake256().hash_string("The quick brown fox jumps over the lazy dog", hash);
    // Now hash contains the hash

The following snippet demonstrates how to calculate the hash of a very long message using the init/update/final interface:

    blake256 hasher;
    uint8_t hash[256/8];
    
    hasher.init();
    hasher.update(datachunk1, chunk1len);
    hasher.update(datachunk2, chunk2len);
    ...
    hasher.final(hash); // Now hash contains the hash

2.4. Hashing performance

Performance of various hash algorithms on three different test systems is provided in the table below (in megabytes per second).
Note how 64-bit builds outperform 32-bit builds. For some algorithms 64-bit build is up to 5 times faster than 32-bit build on the same PC.
It's also an interesting comparison between gcc 5.2.1 and clang 3.7.0 optimizers. Some algorithms are faster when compiled by clang, while others are faster when compiled by gcc.

Performance in megabytes per second (MB/s), higher number means faster
(measured by calculating a hash of a 130Kb file 100,000 times)
AlgorithmPC: Intel Xeon E5-1650 v3
(Haswell-EP)
PC: Intel Core i7 930
(Nehalem)
PC: Intel Core i3-3217U
(Ivy Bridge w/o AESNI)
OS: Win7 x64
Compiler: VC++2015
OS: openSUSE (in VM)
Compiler: gcc 5.2.1
OS: openSUSE (in VM)
Compiler: clang 3.7.0
OS: Win7 x64
Compiler: VC++2015
OS: Win7 x64
Compiler: VC++2015
128-bit digest 64-bit build32-bit build64-bit build32-bit build64-bit build32-bit build64-bit build32-bit build64-bit build32-bit build
BLAKE2b/128661543651552704605490335326262
BLAKE2s/128554539549542554547360205274271
MD5528509634627472472382352262252
Skein-256/128383210400186396125261164175103
Skein-512/128517234570253585118340181231112
160-bit digest 64-bit build32-bit build64-bit build32-bit build64-bit build32-bit build64-bit build32-bit build64-bit build32-bit build
BLAKE2b/160661543651552704605490335326262
BLAKE2s/160554539549542554547360205274271
Skein-256/160383210400186396125261164175103
Skein-512/160517234570253585118340181231112
SHA-1789522784512784508480392361247
224-bit digest 64-bit build32-bit build64-bit build32-bit build64-bit build32-bit build64-bit build32-bit build64-bit build32-bit build
BLAKE-224423417421392427404271151208204
BLAKE2b/224661543651552704605490335326262
BLAKE2s/224554539549542554547360205274271
Groestl-224326270279227322229112997371
JH-224206146198156205138132919571
SHA-224398293382282382282202162149127
SHA-512/22455221153420353220329815521497
SHA3-224270243258221260242174143122109
Skein-256/224383210400186396125261164175103
Skein-512/224517234570253585118340181231112
256-bit digest 64-bit build32-bit build64-bit build32-bit build64-bit build32-bit build64-bit build32-bit build64-bit build32-bit build
BLAKE-256423417421392427404271151208204
BLAKE2b/256661543651552704605490335326262
BLAKE2s/256554539549542554547360205274271
Groestl-256326270279227322229112997371
JH-256206146198156205138132919571
Kupyna-25612754111541137977285325
SHA-256398293382282382282202162149127
SHA-512/25655221153420353220329815521497
SHA3-256256227246206245228164133114103
Skein-256/256383210400186396125261164175103
Skein-512/256517234570253585118340181231112
Skein-1024/256406106481934791082176314438
SM31861401661431701481171018170
Streebog-25611264116641136869425032
384-bit digest 64-bit build32-bit build64-bit build32-bit build64-bit build32-bit build64-bit build32-bit build64-bit build32-bit build
BLAKE-384471411477421540437340217227202
BLAKE2b/384661543651552704605490335326262
Groestl-38424619722018123418283735452
JH-384206146198156205138132919571
SHA-38455221153420353220329815521497
SHA3-3841941751871521891751261038979
Skein-512/384517234570253585118340181231112
Skein-1024/384406106481934791082176314438
512-bit digest 64-bit build32-bit build64-bit build32-bit build64-bit build32-bit build64-bit build32-bit build64-bit build32-bit build
BLAKE-512471411477421540437340217227202
BLAKE2b/512661543651552704605490335326262
Groestl-51224619722018123418283735452
JH-512206146198156205138132919571
Kupyna-51281438441885949222320
SHA-51255221153420353220329815521497
SHA3-51213612213010313312381726149
Skein-512/512517234570253585118340181231112
Skein-1024/512406106481934791082176314438
Streebog-51211264116641136869425032
Whirlpool15012514712216212280896158
1024-bit digest 64-bit build32-bit build64-bit build32-bit build64-bit build32-bit build64-bit build32-bit build64-bit build32-bit build
Skein-1024/1024406106481934791082176314438

You can run the hashing performance test on your own PC using the following command:

    digest test <number_of_iterations> <filename_to_hash>

3. MAC algorithms

3.1 HMAC

Class hmac is also derived from crypto_hash and implements the same interface. The only difference is that you need to pass a reference to a hash algorithm and a key in the constructor.

    hmac(const crypto_hash& hash, const uint8_t* key, size_t keylen);

The key can be of any length and you can use any of the supported hash algorithms to calculate HMAC. The following sample calculates HMAC-SHA-256 of a string "The quick brown fox jumps over the lazy dog" with key "key":

    uint8_t hmackey[3];
    hmackey[0] = 'k';
    hmackey[1] = 'e';
    hmackey[2] = 'y';
    hmac mac(sha256(), hmackey, sizeof(hmackey));
    uint8_t result[32];
    mac.hash_string("The quick brown fox jumps over the lazy dog", result);

3.2 Poly1305

Class poly1305 is also derived from crypto_hash and implements the same interface. The only difference is that you need to pass a key in the constructor.

    poly1305(const uint8_t* key, size_t keylen);

The key must have length 32 bytes (256 bits). The following sample calculates Poly1305 of a string "The quick brown fox jumps over the lazy dog" with key "\x00\x01\x02...\x31":

    uint8_t key[32];
    std::iota(key, key + 32, 0);
    poly1305 poly(key, sizeof(key));
    uint8_t result[16];
    poly.hash_string("The quick brown fox jumps over the lazy dog", result);

4. Block cipher algorithms

4.1. Interface description

All block cipher algorithms derive from block_cipher class and implement its interface.

    class block_cipher
    {
    public:
        enum direction { encryption, decryption };

        virtual size_t blocksize() const = 0;
        virtual size_t keysize() const = 0;

        virtual bool init(const uint8_t* key, block_cipher::direction direction) = 0;
        virtual void encrypt_block(const uint8_t* in, uint8_t* out) = 0;
        virtual void decrypt_block(const uint8_t* in, uint8_t* out) = 0;
    };

A low-level interface to the block cipher. To start encryption or decryption, call init() (key should point to a key of keysize()/8 bytes), then call encrypt_block() or decrypt_block() to encrypt or decrypt a single block of blocksize()/8 bytes.
In practice in most cases you probably want to use block ciphers in an encryption mode via cbc or ctr class described below.

4.2. Supported algorithms

Classes derived from block_cipher:

Class NameDescription
anubis128
anubis160
anubis192
anubis224
anubis256
anubis288
anubis320
Anubis cipher
with block size 128 bits and key sizes 128/160/192/224/256/288/320 bits.
aria128
aria192
aria256
Aria cipher (South Korean national standard)
with block size 128 bits and key sizes 128/192/256 bits.
cast6_128
cast6_160
cast6_192
cast6_224
cast6_256
CAST6 (aka CAST-256) cipher
with block size 128 bits and key sizes 128/160/192/224/256 bits.
camellia128
camellia192
camellia256
Camellia cipher (recommended by NESSIE and CRYPTREC)
with block size 128 bits and key sizes 128/192/256 bits.
kalyna128_128
kalyna128_256
kalyna256_256
kalyna256_512
kalyna512_512
Kalyna cipher (Ukrainian national standard DSTU 7624:2014)
with block sizes 128/256/512 bits and key sizes 128/256/512 bits.
kuznyechik Kuznyechik cipher (Russian national standard GOST R 34.12-2015)
with block size 128 bits and key size 256 bits.
mars128
mars160
mars192
mars224
mars256
mars288
mars320
mars352
mars384
mars416
mars448
MARS cipher (one of AES finalists)
with block size 128 bits
and key sizes 128/160/192/224/256/288/320/352/384/416/448 bits.
rijndael128_128
rijndael128_160
rijndael128_192
rijndael128_224
rijndael128_256
rijndael160_128
rijndael160_160
rijndael160_192
rijndael160_224
rijndael160_256
rijndael192_128
rijndael192_160
rijndael192_192
rijndael192_224
rijndael192_256
rijndael224_128
rijndael224_160
rijndael224_192
rijndael224_224
rijndael224_256
rijndael256_128
rijndael256_160
rijndael256_192
rijndael256_224
rijndael256_256
Rijndael cipher (AES winner)
with block sizes 128/160/192/224/256 bits
and key sizes 128/160/192/224/256 bits.

Rijndael with block size 128 bits and key size 128, 192, 256 bits
is also known as
AES-128, AES-192, AES-256.

All 25 Rijndael variants are accelerated using AES-NI instructions,
if they are supported by CPU.
serpent128
serpent192
serpent256
Serpent cipher (one of AES finalists)
with block size 128 bits and key sizes 128/192/256 bits.
simon128_128
simon128_192
simon128_256
Simon cipher
with block size 128 bits and key sizes 128/192/256 bits.
sm4 SM4 cipher (Chinese national standard for Wireless LAN)
with block size 128 bits and key size 128 bits.
speck128_128
speck128_192
speck128_256
Speck cipher
with block size 128 bits and key sizes 128/192/256 bits.
threefish256_256
threefish512_512
threefish1024_1024
Threefish cipher
with block sizes 256/512/1024 bits and key sizes 256/512/1024 bits.
twofish128
twofish192
twofish256
Twofish cipher (one of AES finalists)
with block size 128 bits and key sizes 128/192/256 bits.

5. Block cipher encryption modes

5.1. CBC mode

Class cbc implements the following interface:

    cbc(const block_cipher& cipher);

    void init(const uint8_t* key, size_t keylen, const uint8_t* iv, size_t ivlen, block_cipher::direction direction);

    // Functions writing output to preallocated raw buffer (the fastest)
    void encrypt_update(const uint8_t* in, size_t len, uint8_t* out, size_t& resultlen);
    void encrypt_final(uint8_t* out, size_t& resultlen);
    void decrypt_update(const uint8_t* in, size_t len, uint8_t* out, size_t& resultlen);
    void decrypt_final(uint8_t* out, size_t& resultlen);

    // Functions writing output to std::vector (slower)
    void encrypt_update(const uint8_t* in, size_t len, std::vector& out);
    void encrypt_final(std::vector& out);
    void decrypt_update(const uint8_t* in, size_t len, std::vector& out);
    void decrypt_final(std::vector& out);

    // Functions writing output to std::ostream (the slowest)
    void encrypt_update(const uint8_t* in, size_t len, std::ostream& out);
    void encrypt_final(std::ostream& out);
    void decrypt_update(const uint8_t* in, size_t len, std::ostream& out);
    void decrypt_final(std::ostream& out);

The functions are similar to the ones from the crypto_hash class.

To start encryption, pass one of the block ciphers to the constructor and initialize encryption using init() function. The length of the key in bytes should be equal to keysize()/8 of the block cipher, and the length of the initialization vector (iv) in bytes should be equal to blocksize()/8 of the block cipher. Then call encrypt_update() any number of times to add the next chunk of data of variable length. When all input is consumed by encrypt_update() function, call encrypt_final() to finish the encryption (at this stage the final block will be written to out).

Decryption is done in a similar way.

If you use the low-level functions that write the output to a preallocated buffer, the out argument should point to the next location where the encrypted output should be written; resultlen is the number of bytes written to out as the result of the function call. Because the class implements PKCS#7 padding, the overall size of the output buffer should be equal to the size of the input rounded up to the block size of the cipher algorithm, plus one additional full block if the input size is the exact multiple of the block size. It is responsibility of the caller to make sure the buffer is large enough.

A simpler but slower interface accepts a reference to std::vector<uint8_t> and appends encryption or decryption result to this vector, which is dynamically resized as needed, so that you do not need to calculate and allocate a buffer of proper size in advance.

An even simpler but slower interface writes the output to std::ostream.

Note that regardless of which interface you use, you still need to call init() function to set up the key and initialization vector.

5.2. CTR mode

Class ctr implements the stream_cipher interface for block ciphers:

    ctr(const block_cipher& cipher);

    void init(const uint8_t* key, size_t keylen, const uint8_t* iv, size_t ivlen);
    void encrypt(const uint8_t* in, size_t len, uint8_t* out);
    void decrypt(const uint8_t* in, size_t len, uint8_t* out);

CTR mode turns block cipher into a stream cipher, so no padding is needed in this mode and the size of the output buffer must be the same as the size of the input data. The length of the key in bytes should be equal to keysize()/8 of the block cipher, and the length of the initialization vector (iv) in bytes should be equal to or smaller than blocksize()/8 of the block cipher. Since all output is produced immediately, no finalization function is needed in this mode.

5.3. Encryption performance

Performance in megabytes per second (MB/s), higher number means faster
(measured by encrypting a 130Kb file in CBC mode 100,000 times)
AlgorithmPC: Intel Xeon E5-1650 v3
OS: Win7 x64
Compiler: VC++2015
OS: openSUSE (in VM)
Compiler: gcc 5.2.1
OS: openSUSE (in VM)
Compiler: clang 3.7.0
64-bit build32-bit build 64-bit build32-bit build 64-bit build32-bit build
Anubis-128225138208178198169
Anubis-160206128195167186156
Anubis-192198119196157172145
Anubis-224186112186147162137
Anubis-256176105175138152128
Anubis-288163100166130146121
Anubis-32015794158124136115
Aria-128135113155154150153
Aria-19211698134133129133
Aria-25610286119118114117
Camellia-12814894153130143149
Camellia-1921137111899108114
Camellia-2561137111799108114
CAST6-1281099910410110294
CAST6-1601099910410110294
CAST6-1921099910410110294
CAST6-2241099910410110294
CAST6-2561099910410110294
Kalyna-128/128179112236130206186
Kalyna-128/2561328217595148137
Kalyna-256/2561778520688167113
Kalyna-256/512140671356913189
Kalyna-512/512155661247111983
Kuznyechik109601136811270
Mars-128159136154154138140
Mars-160159136154154138140
Mars-192159136154154138140
Mars-224159136154154138140
Mars-256159136154154138140
Mars-288159136154154138140
Mars-320159136154154138140
Mars-352159136154154138140
Mars-384159136154154138140
Mars-416159136154154138140
Mars-448159136154154138140
Rijndael-128/128657656633632633629
Rijndael-128/160607607589578588579
Rijndael-128/192564566541544545537
Rijndael-128/224525527505506505502
Rijndael-128/256493490472474476471
Rijndael-160/128339253315290331322
Rijndael-160/160339254315290331322
Rijndael-160/192318238293272310302
Rijndael-160/224299223276258292286
Rijndael-160/256282211263245275267
Rijndael-192/128425373361327459452
Rijndael-192/160425373355330456457
Rijndael-192/192425373357327457456
Rijndael-192/224399352333309429426
Rijndael-192/256378334320295402398
Rijndael-224/128370287332306355346
Rijndael-224/160370287332306355346
Rijndael-224/192370287332306355346
Rijndael-224/224370287334306355346
Rijndael-224/256349268314290334329
Rijndael-256/128528527501501501499
Rijndael-256/160528527501501501499
Rijndael-256/192528527501501501499
Rijndael-256/224528527501501501499
Rijndael-256/256528527501501501499
Serpent-128849689939093
Serpent-192849689939093
Serpent-256849689939093
Simon-128/128135461364314261
Simon-128/192128531344315565
Simon-128/256128441304013458
SM4777591957580
Speck-128/128423199422122427206
Speck-128/192416201411120414200
Speck-128/256399201403115406194
Threefish-256/256334115408111396137
Threefish-512/512343118620108610129
Threefish-1024/102432410435983361100
Twofish-128171151171164162167
Twofish-192171151171164162167
Twofish-256171151171164162167

You can run the block cipher encryption performance test on your own PC using the following command:

    digest bctest <number_of_iterations> <filename_to_encrypt>

6. Stream cipher algorithms

6.1. Interface description

All stream cipher algorithms derive from stream_cipher class and implement its interface.

    class stream_cipher
    {
    public:
        virtual size_t keysize() const = 0;
        virtual size_t ivsize() const = 0;

        virtual void init(const uint8_t* key, size_t keylen, const uint8_t* iv, size_t ivlen) = 0;
        virtual void encrypt(const uint8_t* in, size_t len, uint8_t* out) = 0;
        virtual void decrypt(const uint8_t* in, size_t len, uint8_t* out) = 0;
    };

To start encryption or decryption, call init() (key should point to a key of keysize()/8 bytes, and iv should point to an initialization vector of ivsize()/8 bytes). Then call encrypt() or decrypt() to encrypt or decrypt a stream of any length.

6.2. Supported algorithms

Classes derived from stream_cipher:

Class NameDescription
chacha20_128
chacha20_256
chacha12_128
chacha12_256
ChaCha cipher (a variant of Salsa20)
including full 20-round version and reduced 12-round version
with key sizes 128 and 256 bits and initialization vector size 64 bits.
hc128
hc256
HC cipher (member of eSTREAM portfolio)
with key sizes 128 and 256 bits and initialization vector sizes 128 and 256 bits.
salsa20_128
salsa20_256
salsa20_12_128
salsa20_12_256
Salsa20 cipher (member of eSTREAM portfolio)
including full 20-round version and reduced 12-round version
with key sizes 128 and 256 bits and initialization vector size 64 bits.
xchacha20_128
xchacha20_256
xchacha12_128
xchacha12_256
XChaCha cipher (a variant of ChaCha with longer nonce)
including full 20-round version and reduced 12-round version
with key sizes 128 and 256 bits and initialization vector size 192 bits.
xsalsa20_128
xsalsa20_256
xsalsa20_12_128
xsalsa20_12_256
XSalsa20 cipher (a variant of Salsa20 with longer nonce)
including full 20-round version and reduced 12-round version
with key sizes 128 and 256 bits and initialization vector size 192 bits.

You can also use any of the supported block ciphers like a stream cipher via ctr class, which implements the same stream_cipher interface.

6.3. Encryption performance

Performance in megabytes per second (MB/s), higher number means faster
(measured by encrypting a 130Kb file 100,000 times)
AlgorithmPC: Intel Xeon E5-1650 v3
OS: Win7 x64
Compiler: VC++2015
OS: openSUSE (in VM)
Compiler: gcc 5.2.1
OS: openSUSE (in VM)
Compiler: clang 3.7.0
64-bit build32-bit build 64-bit build32-bit build 64-bit build32-bit build
ChaCha20-12812001050128699513401130
ChaCha20-25612001050128699513401130
ChaCha12-128192015952070158521401795
ChaCha12-256192015952070158521401795
HC-128175013501760155018101965
HC-2561050825115796511101095
Salsa20-1281150855110090011701045
Salsa20-2561150855110090011701045
Salsa20/12-128183513101750141018501660
Salsa20/12-256183513101750141018501660
XChaCha20-12812001050128699513401130
XChaCha20-25612001050128699513401130
XChaCha12-128192015952070158521401795
XChaCha12-256192015952070158521401795
XSalsa20-1281150855110090011701045
XSalsa20-2561150855110090011701045
XSalsa20/12-128183513101750141018501660
XSalsa20/12-256183513101750141018501660

You can run the stream cipher encryption performance test on your own PC using the following command:

    digest sctest <number_of_iterations> <filename_to_encrypt>

7. Key derivation functions

7.1. PBKDF2

Function pbkdf2 has the following prototype:

    void pbkdf2(hmac& hmac, const uint8_t* salt, size_t salt_len, int iterations, uint8_t* dk, size_t dklen);

You can use this function to derive an encryption key from a password. The password should be passed to the constructor of hmac object as the key.

The following snippet generates a 256-bit key from password "password" and salt "salt" using PBKDF2 algorithm with 100000 iterations of HMAC-SHA256:

    hmac hmac(sha256(), "password");
    uint8_t key[256 / 8];
    pbkdf2(hmac, (const uint8_t*)"salt", 4, 100000, key, sizeof(key));

7.2. scrypt

Function scrypt has the following prototype:

    /*
    scrypt key derivation function.

    Input:
    hmac    HMAC to use (e.g. HMAC-SHA-256). The password shall be passed to the constructor of hmac object.
    salt    Salt.
    N       CPU/Memory cost parameter, must be larger than 1, a power of 2 and less than 216*r.
    r       Block size factor parameter.
    p       Parallelization parameter, a positive integer less than 230/r.
    dklen   Intended output length of the derived key; a positive integer less than or equal to (232 - 1) * 32.

    Output:
    dk      Derived key, of length dklen bytes.
    */

    void scrypt(hmac& hmac, const uint8_t* salt, size_t salt_len, size_t N, size_t r, size_t p, uint8_t* dk, size_t dklen);

You can use this function to derive an encryption key from a password. The password should be passed to the constructor of hmac object as the key.

The following snippet generates a 256-bit key from password "password" and salt "salt" using scrypt with N=16384, r=8 and p=16 (which takes 0.10 seconds on Intel Xeon E5-1650 v3):

    hmac hmac(sha256(), "password");
    uint8_t key[256 / 8];
    scrypt(hmac, (const uint8_t*)"salt", 4, 16384, 8, 16, key, sizeof(key));

7.3. Argon2

Argon2 is a winner of Password Hashing Competition and is the recommended function for hashing passwords.

There are two versions of Argon2 function: argon2i and argon2d. Argon2i is the safest against side-channel attacks, while Argon2d provides the highest resistance against GPU cracking attacks.

    /*
    Argon2 key derivation function.

    Input:
    password Passphrase.
    salt     Salt.
    p        A parallelism degree, which defines the number of parallel threads.
    m        A memory cost, which defines the memory usage, given in kibibytes.
    t        A time cost, which defines the amount of computation realized and therefore the execution time, given in number of iterations.
    dklen    Intended output length of the derived key, given in bytes.

    Optional input:
    data     Associated data which will affect the derived key.
    secret   Secret value which will affect the derived key.
    version  Version of the algorithm (argon2_version::version12 is supported for compatibility, for new development use the latest argon2_version::version13).

    Output:
    dk       Derived key, of length dklen bytes.
    */

    void argon2d(const char* password, uint32_t pwd_len, const uint8_t* salt, uint32_t salt_len,
                 uint32_t p, uint32_t m, uint32_t t, uint8_t* dk, uint32_t dklen,
                 uint8_t* data = nullptr, uint32_t datalen = 0, uint8_t* secret = nullptr, uint32_t secretlen = 0,
                 argon2_version version = argon2_version::version13);

    void argon2i(const char* password, uint32_t pwd_len, const uint8_t* salt, uint32_t salt_len,
                 uint32_t p, uint32_t m, uint32_t t, uint8_t* dk, uint32_t dklen,
                 uint8_t* data = nullptr, uint32_t datalen = 0, uint8_t* secret = nullptr, uint32_t secretlen = 0,
                 argon2_version version = argon2_version::version13);

The following snippet generates a 256-bit key from password "password" and salt "salt" using argon2i function with p=4, m=4096 and t=1000 (which takes 0.68 seconds on Intel Xeon E5-1650 v3):

    uint8_t key[256 / 8];
    argon2i("password", 8, (const uint8_t*)"salt", 4, 4, 4096, 1000, key, sizeof(key));

Our implementation of Argon2 is faster than the optimized reference implementation, which needs 1.05 seconds to compute the same Argon2i hash on the same PC (both implementations were compiled by VC++ 2015 with /O2 optimization).

8. Digest utility

Also included is a command-line utility 'digest.exe' which can be used to calculate message digest of any file(s) using any of the supported hash algorithms (similar to md5sum), for example, if you want to calculate Skein-512/256 hash of a file, you can run:

   digest skein512/256 file.ext
You can save the checksums to a text file using the following command:

   digest skein512/256 * > checksums.skein
Like md5sum, the utility can also verify checksums saved in a file, for example, if you want to verify the hashes saved by the previous command, you can run:

   digest -c skein512/256 checksums.skein

9. Portability notes

At the moment we support only x86 processors (in 32-bit or 64-bit mode).
To build cppcrypto from the sources you need to have yasm installed.
We have successfully compiled and tested cppcrypto under the following operating systems.

9.1. Windows

Tested OS versions: Windows 7, Windows 10.
Tested compilers: Visual C++ 2013, Visual C++ 2015.

First, download the latest yasm for Visual Studio and install it according to the instructions in its readme.txt. Note that the latest stable release of yasm (1.3.0) ships vsyasm.props file which is not compatible with Visual Studio 2013 and 2015. The fixed version of vsyasm.props is included in the cppcrypto source archive, so you just need to replace that single file. (Alternatively, use the development version of yasm from their git repository, which reportedly fixes the compatibility issue.)

Then, open the supplied Visual C++ project files or solution file and build cppcrypto. If you're using Visual Studio 2015, right-click each project and choose "Upgrade VC Compilers and Libraries" menu item, since the provided project files are from VS2013.

If you use the precompiled static libraries then you don't need yasm. Just link against cppcryptomd.lib or cppcryptomt.lib depending on your /MT or /MD settings.

Experimental support for Cygwin gcc builds has been added recently; to build in cygwin, run 'make UNAME=Cygwin' and 'make UNAME=Cygwin install'.

9.2. Linux

Tested OS versions: openSUSE Tumbleweed (x86_64 and i586), Debian Sid (x86_64), Fedora 23 (x86_64).
Tested compilers: gcc 5.1.1, gcc 5.2.1, clang 3.7.0.

Make sure yasm is installed, then run make and [sudo] make install as usual.

Note that if you try to run the vectortest.sh script on Linux, you may get a crash during checking sha384 and sha512 test vectors. This is caused by a bug in the current version of libstdc++ (stack overflow on long regexes). The developers of libstdc++ are informed and acknowledge the bug. This bug does not affect the functionality of cppcrypto library anyhow, C++ regexes are only used in the test application for parsing the test vectors.

9.3. Mac OS X

Tested OS versions: OS X 10.11.1 El Capitan.
Tested compilers: Apple LLVM version 7.0.0 (clang-700.1.76).

Download and install yasm. Then run make and [sudo] make install to build and install cppcrypto.

9.4. FreeBSD

Tested OS versions: FreeBSD 10.2-RELEASE.
Tested compilers: clang 3.4.1.

Install yasm (pkg install yasm) and GNU make (pkg install gmake). Then, run gmake and [sudo] gmake install to build and install cppcrypto.

9.5. Solaris

Tested OS versions: Solaris 11.3.
Tested compilers: Solaris Studio 12.4.

Install yasm from OpenCSW. Be sure yasm, gmake, ginstall and Solaris Studio compiler (CC) are in the PATH. Then, run gmake and [sudo] gmake install to build and install cppcrypto.

10. Download link

Download cppcrypto from sourceforge