Digestpp
C++11 header-only message digest library
Install / Use
/learn @kerukuro/DigestppREADME
digestpp
Experimental C++11 header-only message digest library.
Derived from cppcrypto, this library aims to provide a more modern, flexible, and versatile C++ API for cryptographic hash functions.
Tested with g++ 6.4.0, clang 4.0.1 and Visual C++ 2017.
Quick Start / Installation
Just copy the digestpp folder to your project or include path and #include <digestpp/digestpp.hpp>.
Examples
Quick Start
Calculate SHA-256 digest of a string literal:
#include <digestpp/digestpp.hpp>
#include <iostream>
int main() {
std::cout << digestpp::sha256().absorb("Hello World").hexdigest() << std::endl;
return 0;
}
Specifying Output Size (Runtime vs Compile-time)
For algorithms supporting variable output lengths (like BLAKE2, SHA512, SHA-3, etc.), the size can be set either at runtime (constructor argument) or at compile-time (template parameter).
Runtime size (more flexible, allows values determined at runtime):
size_t length = 256;
std::cout << digestpp::blake2b(length).absorb("data").hexdigest() << std::endl;
Compile-time size (static checking):
std::cout << digestpp::static_size::blake2b<256>().absorb("data").hexdigest() << std::endl;
Working with Strings
The .absorb() method accepts both string literals and std::string objects. Method chaining is supported:
// Using std::string
std::string str = "The quick brown fox jumps over the lazy dog";
std::cout << digestpp::blake2b().absorb(str).hexdigest() << std::endl;
// Using string literals and chaining
digestpp::blake2b x;
x.absorb("The quick brown fox ");
x.absorb("jumps over the lazy dog");
std::cout << x.hexdigest() << std::endl;
Hashing Binary Data
Absorb data from standard containers (like std::vector) or raw C-arrays:
// From a vector<unsigned char>
std::vector<unsigned char> v = {0x01, 0x02, 0x03};
std::cout << digestpp::sha512(256).absorb(v.begin(), v.end()).hexdigest() << std::endl;
// From a raw C array
unsigned char buf[32] = {0};
std::cout << digestpp::sha512(256).absorb(buf, sizeof(buf)).hexdigest() << std::endl;
Hashing Files
Read and hash a file directly using std::ifstream:
std::ifstream file("filename", std::ios_base::in | std::ios_base::binary);
std::cout << digestpp::sha256().absorb(file).hexdigest() << std::endl;
Output Options
Retrieve the result as a hex string, raw bytes, or write directly to a stream.
Output to std::vector:
std::vector<unsigned char> out;
digestpp::sha3(256).absorb("data").digest(std::back_inserter(out));
Output to a raw buffer:
unsigned char buf[32];
digestpp::sha3(256).absorb("data").digest(buf, sizeof(buf));
Output to a stream:
std::stringstream ss;
digestpp::sha3(256).absorb("data").digest(std::ostream_iterator<char>(ss, ""));
Extendable Output Functions (XOF)
Use squeeze() to generate outputs of arbitrary length.
SHAKE-256:
std::vector<unsigned char> v;
digestpp::shake256 xof;
xof.absorb("data");
xof.squeeze(10, std::back_inserter(v)); // Get first 10 bytes
xof.squeeze(10, std::back_inserter(v)); // Get next 10 bytes
cSHAKE-256 with customization:
digestpp::cshake256 xof;
xof.set_customization("My Custom Protocol");
std::cout << xof.absorb("data").hexsqueeze(64) << std::endl; // Get 64 bytes as hex
Hasher class
Hasher is the main class template implementing the public API for hashing.
It has two template parameters:
- HashProvider is a class implementing the algorithm via the traditional init/update/final interface. We provide our own implementations of hash functions listed in the next section, but using the traditional interface allows anyone to trivially implement the providers as wrappers around popular libraries, such as OpenSSL, Crypto++, or Botan.
- Mixin is a class template which can be used to inject additional functions into the public API of the hasher, for example for setting the customization string for cSHAKE, the salt for BLAKE, etc.
template<class HashProvider, template <class> class Mixin = detail::null_mixin>
class hasher : public Mixin<HashProvider>
{
public:
// Default constructor
// Used for hash functions with fixed output size, for hash functions with sensible
// default output size, and for extendable output functions (XOFs).
template<typename H=HashProvider,
typename std::enable_if<std::is_default_constructible<H>::value>::type* = nullptr>
hasher();
// Constructor with hashsize parameter
// Used with hash functions which can produce hashes of different lengths with length specified at runtime.
// If the requested output size is not supported by the algorithm, std::runtime_error will be thrown.
template<typename H=HashProvider, typename std::enable_if<!detail::is_xof<H>::value>::type* = nullptr>
hasher(size_t hashsize);
// Absorbs bytes from a C-style pointer to a character buffer
template<typename T, typename std::enable_if<detail::is_byte<T>::value>::type* = nullptr>
inline hasher& absorb(const T* data, size_t len);
// Absorbs bytes from std::basic_string
template<typename T,
typename std::enable_if<detail::is_byte<T>::value
&& !std::is_same<T, std::string::value_type>::value>::type* = nullptr>
inline hasher& absorb(const std::basic_string<T>& str);
// Absorbs bytes from std::string
inline hasher& absorb(const std::string& str);
// Absorbs bytes from std::istream
template<typename T, typename std::enable_if<detail::is_byte<T>::value>::type* = nullptr>;
inline hasher& absorb(std::basic_istream<T>& istr);
// Absorbs bytes from an iterator sequence
template<typename IT>
inline hasher& absorb(IT begin, IT end);
// In case HashProvider is an extendable output function, squeeze <len> bytes from absorbed data
// into a user-provided preallocated buffer.
template<typename T, typename H=HashProvider,
typename std::enable_if<detail::is_byte<T>::value && detail::is_xof<H>::value>::type* = nullptr>
inline void squeeze(T* buf, size_t len);
// In case HashProvider is an extendable output function, squeeze <len> bytes from absorbed data
// and write them to the output iterator.
template<typename OI, typename H=HashProvider,
typename std::enable_if<detail::is_xof<H>::value>::type* = nullptr>
inline void squeeze(size_t len, OI it);
// In case HashProvider is an extendable output function, squeeze <len> bytes from absorbed data
// and return them as a hex string.
template<typename H=HashProvider, typename std::enable_if<detail::is_xof<H>::value>::type* = nullptr>
inline std::string hexsqueeze(size_t len);
// In case HashProvider is a hash function, output binary digest to a user-provided preallocated buffer.
template<typename T, typename H=HashProvider,
typename std::enable_if<detail::is_byte<T>::value && !detail::is_xof<H>::value>::type* = nullptr>
inline void digest(T* buf, size_t len) const;
// In case HashProvider is a hash function, generate binary digest from absorbed data
// and write it to an output iterator.
template<typename OI, typename H=HashProvider,
typename std::enable_if<!detail::is_xof<H>::value>::type* = nullptr>
inline void digest(OI it) const;
// In case HashProvider is a hash function, return hex digest of absorbed data.
template<typename H=HashProvider, typename std::enable_if<!detail::is_xof<H>::value>::type* = nullptr>
inline std::string hexdigest() const;
// Resets the state to start new digest computation.
// If resetParameters is true, all customization parameters such as salt will also be cleared.
inline void reset(bool resetParameters = false);
};
Individual hash algorithms are defined by typedefs, e.g.
typedef hasher<detail::sha3_provider> sha3;
typedef hasher<detail::blake_provider, detail::blake_mixin> blake;
// ...
Supported algorithms
Hash functions
Typedef|Description|Security|Supported output sizes|Optional parameters -------|-----------|--------|----------------------|------------------- ascon_hash|Ascon (NIST SP 800-232)|✅Secure|256|- blake|Original BLAKE algorithm|✅Secure|224, 256, 384, 512|salt blake2b|BLAKE2b|✅Secure|8-512|salt, personalization, key blake2s|BLAKE2s|✅Secure|8-256|salt, personalization, key blake2bp|BLAKE2bp|✅Secure|8-512|salt, personalization, key blake2sp|BLAKE2sp|✅Secure|8-256|salt, personalization, key blake2xb|BLAKE2xb|✅Secure|arbitrary|salt, personalization, key blake2xs|BLAKE2xs|✅Secure|arbitrary|salt, personalization, key echo|Echo|✅Secure|8-512|salt esch|Esch|✅Secure|256, 384|- groestl|Grøstl|✅Secure|8-512|- jh|JH|✅Secure|8-512|- kmac128|KMAC128|✅Secure|arbitrary|key, customization kmac256|KMAC256|✅Secure|arbitrary|key, customization kupyna|Kupyna|✅Secure|256, 512|- lsh256|LSH-256|✅Secure|8-256|- lsh512|LSH-512|✅Secure|8-512|- md5|MD5|❌Broken|128|- sha1|SHA-1|❌Broken|160|- sha224|SHA-224|✅Secure|224|- sha256|SHA-256|✅Secure|256|- sha384|SHA-384|✅Secure|384|- sha512|SHA-512|✅Secure|8-512|- sha3|SHA-3|✅Secure|224, 256, 384, 512|- skein256|Skein256|✅Secure|arbitrary|personalization, key, nonce skein512|Skein512|✅Secure|arbitrary|personalization, key, nonce skein1024|Skein1024|✅Secure|arbitrary|personalization, key, nonce sm3|SM3|✅Secure|256|- streebog|Streebog|⚠️Backdoored|256, 512|- whirlpool|Whirlpool|✅Secure|512|-
Extendable output functions
Typedef|Description|Security|Optional parameters -------|-----------|-|------------------ ascon_xof|Ascon-XOF128|✅Secure|- ascon_cxof|Ascon-CXOF128|✅Secure|customization blake2xb_xof|BLAKE2xb in XOF mode|✅Secure|salt, personalization, key blake2xs_xof|BLAKE2xs in XOF mode|✅Secure|salt, personalization, key esch256_xof|XOEsch256|✅Secure|- esch384_xof|XOEsch384|✅Secure|- k12|KangarooTwelve|✅Secure|customization kt128|KangarooTwelve (alias for k12)|✅Secure|customi
