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. Cryptor utility 10. Portability notes 11. 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 or later on Windows; gcc 5.1.1 or later, clang 3.4.1 or later on Linux, OS X, FreeBSD; Solaris Studio 12.4 or later 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 unsigned char* data, size_t len) = 0;
        virtual void final(unsigned char* hash) = 0;

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

        // Convenience functions
        void hash_string(const unsigned char* data, size_t len, unsigned char* hash);
        void hash_string(const char* data, size_t len, unsigned char* hash);
        void hash_string(const std::string& data, unsigned char* 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 NameDescriptionSupported output sizes
blake BLAKE hash function (one of SHA-3 finalists).
This is one of the fastest hash functions and we recommend it you are free to choose.
224 / 256 / 384 / 512
blake2b BLAKE2b hash function with variable output size up to 512 bits.
This is a version of BLAKE-512 with reduced number of rounds and other simplifications.
8 - 512
blake2s BLAKE2s hash function with variable output size up to 256 bits.
This is a version of BLAKE-256 with reduced number of rounds and other simplifications.
8 - 256
groestl Grøstl hash function (one of SHA-3 finalists).8 - 512
jh JH hash function (one of SHA-3 finalists).224 / 256 / 384 / 512
kupyna 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.
256 / 512
md5 MD5 hash function. Not secure and therefore not recommended; use only if you need it for compatibility.128
sha1 SHA-1 hash function. Not secure and therefore not recommended; use only if you need it for compatibility.160
sha224
sha256
sha384
sha512
SHA-2 hash function (NIST standard FIPS 180-4).
Individual functions are known as SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224 and SHA-512/256.
SHA-512 supports variable output size up to 512 bits (SHA-512/t).
sha512(224) and sha512(256) are faster than sha224 and sha256 on 64-bit platforms.
224 / 256 / 384 / 512,
8 - 512 (SHA-512/t)
sha3
shake128
shake256
SHA-3 hash function (NIST standard FIPS 202) based on Keccak algorithm.
SHAKE-128 and SHAKE-256 support variable output size.
cSHAKE-128 and cSHAKE-256 as defined by NIST SP 800-185 are also supported.
224 / 256 / 384 / 512 (SHA-3)
arbitrary (SHAKE)
skein256 Skein hash function (one of SHA-3 finalists) with block size 256 bits and variable output size.
This algorithm is slower than skein512 on modern PCs, so use it only if you need them for compatibility.
arbitrary
skein512 Skein hash function (one of SHA-3 finalists) with block size 512 bits and variable output size.
This is one of the fastest hash functions and we recommend it if you are free to choose.
arbitrary
skein1024 Skein hash function (one of SHA-3 finalists) with block size 1024 bits and variable output size.arbitrary
sm3 SM3 hash function (Chinese national standard)256
streebog Streebog hash function (Russian standard GOST R 34.11-2012)256 / 512
whirlpool Whirlpool hash function (recommended by NESSIE)512

2.3. Usage example

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

    unsigned char hash[256/8];
    blake(256).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:

    blake(256) hasher;
    unsigned char 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-224358322358301360293174143122109
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-256338304340275339276164133114103
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-3842602332602032582111261038979
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-51218016218014818114781726149
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 unsigned char* 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":

    unsigned char hmackey[3];
    hmackey[0] = 'k';
    hmackey[1] = 'e';
    hmackey[2] = 'y';
    hmac mac(sha256(), hmackey, sizeof(hmackey));
    unsigned char 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 unsigned char* 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":

    unsigned char key[32];
    std::iota(key, key + 32, 0);
    poly1305 poly(key, sizeof(key));
    unsigned char 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 unsigned char* key, block_cipher::direction direction) = 0;
        virtual void encrypt_block(const unsigned char* in, unsigned char* out) = 0;
        virtual void decrypt_block(const unsigned char* in, unsigned char* 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 NameDescriptionSupported block sizesSupported key sizes
anubis128
anubis160
anubis192
anubis224
anubis256
anubis288
anubis320
Anubis cipher128128 / 160 / 192 / 224 / 256 / 288 / 320
aria128
aria192
aria256
Aria cipher (South Korean national standard)128128 / 192 / 256
cast6_128
cast6_160
cast6_192
cast6_224
cast6_256
CAST6 (aka CAST-256) cipher128128 / 160 / 192 / 224 / 256
camellia128
camellia192
camellia256
Camellia cipher (recommended by NESSIE and CRYPTREC)128128 / 192 / 256
kalyna128_128
kalyna128_256
kalyna256_256
kalyna256_512
kalyna512_512
Kalyna cipher (Ukrainian national standard DSTU 7624:2014)128 / 256 / 512128 / 256 / 512
kuznyechik Kuznyechik cipher (Russian national standard GOST R 34.12-2015)128256
mars128
mars160
mars192
mars224
mars256
mars288
mars320
mars352
mars384
mars416
mars448
MARS cipher (one of AES finalists)128128 / 160 / 192 / 224 / 256 / 288 / 320 / 352 / 384 / 416 / 448
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)

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.
128 / 160 / 192 / 224 / 256128 / 160 / 192 / 224 / 256
serpent128
serpent192
serpent256
Serpent cipher (one of AES finalists)128128 / 192 / 256
simon128_128
simon128_192
simon128_256
Simon cipher128128 / 192 / 256
sm4 SM4 cipher (Chinese national standard for Wireless LAN)128128
speck128_128
speck128_192
speck128_256
Speck cipher128128 / 192 / 256
threefish256_256
threefish512_512
threefish1024_1024
Threefish cipher256 / 512 / 1024256 / 512 / 1024
twofish128
twofish192
twofish256
Twofish cipher (one of AES finalists)128128 / 192 / 256

5. Block cipher encryption modes

5.1. CBC mode

Class cbc implements the following interface:

    cbc(const block_cipher& cipher);

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

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

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

    // Functions writing output to std::ostream (the slowest)
    void encrypt_update(const unsigned char* in, size_t len, std::ostream& out);
    void encrypt_final(std::ostream& out);
    void decrypt_update(const unsigned char* 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<unsigned char> 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 unsigned char* key, size_t keylen, const unsigned char* iv, size_t ivlen);
    void encrypt(const unsigned char* in, size_t len, unsigned char* out);
    void decrypt(const unsigned char* in, size_t len, unsigned char* 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 unsigned char* key, size_t keylen, const unsigned char* iv, size_t ivlen) = 0;
        virtual void encrypt(const unsigned char* in, size_t len, unsigned char* out) = 0;
        virtual void decrypt(const unsigned char* in, size_t len, unsigned char* 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 NameDescriptionSupported key sizesSupported IV/nonce sizes
chacha20_128
chacha20_256
chacha12_128
chacha12_256
ChaCha cipher (a variant of Salsa20)
including full 20-round version and reduced 12-round version
128 / 25664
hc128
hc256
HC cipher (member of eSTREAM portfolio)128 / 256128 / 256
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
128 / 25664
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
128 / 256192
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
128 / 256192

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 unsigned char* salt, size_t salt_len, int iterations, unsigned char* 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");
    unsigned char key[256 / 8];
    pbkdf2(hmac, (const unsigned char*)"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 unsigned char* salt, size_t salt_len, size_t N, size_t r, size_t p, unsigned char* 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");
    unsigned char key[256 / 8];
    scrypt(hmac, (const unsigned char*)"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 three versions of Argon2 function: argon2i, argon2d and argon2id. 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 unsigned char* salt, uint32_t salt_len,
                 uint32_t p, uint32_t m, uint32_t t, unsigned char* dk, uint32_t dklen,
                 unsigned char* data = nullptr, uint32_t datalen = 0, unsigned char* secret = nullptr, uint32_t secretlen = 0,
                 argon2_version version = argon2_version::version13);

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

    void argon2id(const char* password, uint32_t pwd_len, const unsigned char* salt, uint32_t salt_len,
                  uint32_t p, uint32_t m, uint32_t t, unsigned char* dk, uint32_t dklen,
                  unsigned char* data = nullptr, uint32_t datalen = 0, unsigned char* 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):

    unsigned char key[256 / 8];
    argon2i("password", 8, (const unsigned char*)"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. Cryptor utility

Command-line utility 'cryptor.exe' is intended to demonstrate how cppcrypto library can be utilized to encrypt or decrypt a file. To encrypt a file, run:

   cryptor enc file.ext

To decrypt a file, run:

   cryptor dec file.ext

The utility demonstrates the steps needed for encryption:

The utility is provided mainly for demonstration purposes, algorithm choice is arbitrary.

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

10.1. Windows

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

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 or later. 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 or later, 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'.

10.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, gcc 7.1.1, clang 3.7.0, clang 4.0.1.

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

Note that if you do not use recent versions of libstdc++ and 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 libstdc++ (stack overflow on long regexes), which is fixed in latest versions. 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.

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

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

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

11. Download link

Download cppcrypto from sourceforge