123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444 |
- // blake2.h - written and placed in the public domain by Jeffrey Walton
- // and Zooko Wilcox-O'Hearn. Based on Aumasson, Neves,
- // Wilcox-O'Hearn and Winnerlein's reference BLAKE2
- // implementation at http://github.com/BLAKE2/BLAKE2.
- /// \file blake2.h
- /// \brief Classes for BLAKE2b and BLAKE2s message digests and keyed message digests
- /// \details This implementation follows Aumasson, Neves, Wilcox-O'Hearn and Winnerlein's
- /// <A HREF="http://blake2.net/blake2.pdf">BLAKE2: simpler, smaller, fast as MD5</A> (2013.01.29).
- /// Static algorithm name return either "BLAKE2b" or "BLAKE2s". An object algorithm name follows
- /// the naming described in <A HREF="http://tools.ietf.org/html/rfc7693#section-4">RFC 7693, The
- /// BLAKE2 Cryptographic Hash and Message Authentication Code (MAC)</A>.
- /// \since C++ since Crypto++ 5.6.4, SSE since Crypto++ 5.6.4, NEON since Crypto++ 6.0,
- /// Power8 since Crypto++ 8.0
- #ifndef CRYPTOPP_BLAKE2_H
- #define CRYPTOPP_BLAKE2_H
- #include "cryptlib.h"
- #include "secblock.h"
- #include "seckey.h"
- NAMESPACE_BEGIN(CryptoPP)
- /// \brief BLAKE2s hash information
- /// \since Crypto++ 5.6.4
- struct BLAKE2s_Info : public VariableKeyLength<32,0,32,1,SimpleKeyingInterface::NOT_RESYNCHRONIZABLE>
- {
- typedef VariableKeyLength<32,0,32,1,SimpleKeyingInterface::NOT_RESYNCHRONIZABLE> KeyBase;
- CRYPTOPP_CONSTANT(MIN_KEYLENGTH = KeyBase::MIN_KEYLENGTH);
- CRYPTOPP_CONSTANT(MAX_KEYLENGTH = KeyBase::MAX_KEYLENGTH);
- CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH = KeyBase::DEFAULT_KEYLENGTH);
- CRYPTOPP_CONSTANT(BLOCKSIZE = 64);
- CRYPTOPP_CONSTANT(DIGESTSIZE = 32);
- CRYPTOPP_CONSTANT(SALTSIZE = 8);
- CRYPTOPP_CONSTANT(PERSONALIZATIONSIZE = 8);
- CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "BLAKE2s";}
- };
- /// \brief BLAKE2b hash information
- /// \since Crypto++ 5.6.4
- struct BLAKE2b_Info : public VariableKeyLength<64,0,64,1,SimpleKeyingInterface::NOT_RESYNCHRONIZABLE>
- {
- typedef VariableKeyLength<64,0,64,1,SimpleKeyingInterface::NOT_RESYNCHRONIZABLE> KeyBase;
- CRYPTOPP_CONSTANT(MIN_KEYLENGTH = KeyBase::MIN_KEYLENGTH);
- CRYPTOPP_CONSTANT(MAX_KEYLENGTH = KeyBase::MAX_KEYLENGTH);
- CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH = KeyBase::DEFAULT_KEYLENGTH);
- CRYPTOPP_CONSTANT(BLOCKSIZE = 128);
- CRYPTOPP_CONSTANT(DIGESTSIZE = 64);
- CRYPTOPP_CONSTANT(SALTSIZE = 16);
- CRYPTOPP_CONSTANT(PERSONALIZATIONSIZE = 16);
- CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "BLAKE2b";}
- };
- /// \brief BLAKE2s parameter block
- struct CRYPTOPP_NO_VTABLE BLAKE2s_ParameterBlock
- {
- CRYPTOPP_CONSTANT(SALTSIZE = BLAKE2s_Info::SALTSIZE);
- CRYPTOPP_CONSTANT(DIGESTSIZE = BLAKE2s_Info::DIGESTSIZE);
- CRYPTOPP_CONSTANT(PERSONALIZATIONSIZE = BLAKE2s_Info::PERSONALIZATIONSIZE);
- BLAKE2s_ParameterBlock()
- {
- Reset();
- }
- BLAKE2s_ParameterBlock(size_t digestSize)
- {
- Reset(digestSize);
- }
- BLAKE2s_ParameterBlock(size_t digestSize, size_t keyLength, const byte* salt, size_t saltLength,
- const byte* personalization, size_t personalizationLength);
- void Reset(size_t digestLength=DIGESTSIZE, size_t keyLength=0);
- byte* data() {
- return m_data.data();
- }
- const byte* data() const {
- return m_data.data();
- }
- size_t size() const {
- return m_data.size();
- }
- byte* salt() {
- return m_data + SaltOff;
- }
- byte* personalization() {
- return m_data + PersonalizationOff;
- }
- // Offsets into the byte array
- enum {
- DigestOff = 0, KeyOff = 1, FanoutOff = 2, DepthOff = 3, LeafOff = 4, NodeOff = 8,
- NodeDepthOff = 14, InnerOff = 15, SaltOff = 16, PersonalizationOff = 24
- };
- FixedSizeAlignedSecBlock<byte, 32, true> m_data;
- };
- /// \brief BLAKE2b parameter block
- struct CRYPTOPP_NO_VTABLE BLAKE2b_ParameterBlock
- {
- CRYPTOPP_CONSTANT(SALTSIZE = BLAKE2b_Info::SALTSIZE);
- CRYPTOPP_CONSTANT(DIGESTSIZE = BLAKE2b_Info::DIGESTSIZE);
- CRYPTOPP_CONSTANT(PERSONALIZATIONSIZE = BLAKE2b_Info::PERSONALIZATIONSIZE);
- BLAKE2b_ParameterBlock()
- {
- Reset();
- }
- BLAKE2b_ParameterBlock(size_t digestSize)
- {
- Reset(digestSize);
- }
- BLAKE2b_ParameterBlock(size_t digestSize, size_t keyLength, const byte* salt, size_t saltLength,
- const byte* personalization, size_t personalizationLength);
- void Reset(size_t digestLength=DIGESTSIZE, size_t keyLength=0);
- byte* data() {
- return m_data.data();
- }
- const byte* data() const {
- return m_data.data();
- }
- size_t size() const {
- return m_data.size();
- }
- byte* salt() {
- return m_data + SaltOff;
- }
- byte* personalization() {
- return m_data + PersonalizationOff;
- }
- // Offsets into the byte array
- enum {
- DigestOff = 0, KeyOff = 1, FanoutOff = 2, DepthOff = 3, LeafOff = 4, NodeOff = 8,
- NodeDepthOff = 16, InnerOff = 17, RfuOff = 18, SaltOff = 32, PersonalizationOff = 48
- };
- FixedSizeAlignedSecBlock<byte, 64, true> m_data;
- };
- /// \brief BLAKE2s state information
- /// \since Crypto++ 5.6.4
- struct CRYPTOPP_NO_VTABLE BLAKE2s_State
- {
- BLAKE2s_State() {
- Reset();
- }
- void Reset();
- inline word32* h() {
- return m_hft.data();
- }
- inline word32* t() {
- return m_hft.data() + 8;
- }
- inline word32* f() {
- return m_hft.data() + 10;
- }
- inline byte* data() {
- return m_buf.data();
- }
- // SSE4, Power7 and NEON depend upon t[] and f[] being side-by-side
- CRYPTOPP_CONSTANT(BLOCKSIZE = BLAKE2s_Info::BLOCKSIZE);
- FixedSizeAlignedSecBlock<word32, 8+2+2, true> m_hft;
- FixedSizeAlignedSecBlock<byte, BLOCKSIZE, true> m_buf;
- size_t m_len;
- };
- /// \brief BLAKE2b state information
- /// \since Crypto++ 5.6.4
- struct CRYPTOPP_NO_VTABLE BLAKE2b_State
- {
- BLAKE2b_State() {
- Reset();
- }
- void Reset();
- inline word64* h() {
- return m_hft.data();
- }
- inline word64* t() {
- return m_hft.data() + 8;
- }
- inline word64* f() {
- return m_hft.data() + 10;
- }
- inline byte* data() {
- return m_buf.data();
- }
- // SSE4, Power8 and NEON depend upon t[] and f[] being side-by-side
- CRYPTOPP_CONSTANT(BLOCKSIZE = BLAKE2b_Info::BLOCKSIZE);
- FixedSizeAlignedSecBlock<word64, 8+2+2, true> m_hft;
- FixedSizeAlignedSecBlock<byte, BLOCKSIZE, true> m_buf;
- size_t m_len;
- };
- /// \brief The BLAKE2s cryptographic hash function
- /// \details BLAKE2s can function as both a hash and keyed hash. If you want only the hash,
- /// then use the BLAKE2s constructor that accepts no parameters or digest size. If you
- /// want a keyed hash, then use the constructor that accpts the key as a parameter.
- /// Once a key and digest size are selected, its effectively immutable. The Restart()
- /// method that accepts a ParameterBlock does not allow you to change it.
- /// \sa Aumasson, Neves, Wilcox-O'Hearn and Winnerlein's
- /// <A HREF="http://blake2.net/blake2.pdf">BLAKE2: simpler, smaller, fast as MD5</A> (2013.01.29).
- /// \since C++ since Crypto++ 5.6.4, SSE since Crypto++ 5.6.4, NEON since Crypto++ 6.0,
- /// Power8 since Crypto++ 8.0
- class BLAKE2s : public SimpleKeyingInterfaceImpl<MessageAuthenticationCode, BLAKE2s_Info>
- {
- public:
- CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH = BLAKE2s_Info::DEFAULT_KEYLENGTH);
- CRYPTOPP_CONSTANT(MIN_KEYLENGTH = BLAKE2s_Info::MIN_KEYLENGTH);
- CRYPTOPP_CONSTANT(MAX_KEYLENGTH = BLAKE2s_Info::MAX_KEYLENGTH);
- CRYPTOPP_CONSTANT(DIGESTSIZE = BLAKE2s_Info::DIGESTSIZE);
- CRYPTOPP_CONSTANT(BLOCKSIZE = BLAKE2s_Info::BLOCKSIZE);
- CRYPTOPP_CONSTANT(SALTSIZE = BLAKE2s_Info::SALTSIZE);
- CRYPTOPP_CONSTANT(PERSONALIZATIONSIZE = BLAKE2s_Info::PERSONALIZATIONSIZE);
- typedef BLAKE2s_State State;
- typedef BLAKE2s_ParameterBlock ParameterBlock;
- CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "BLAKE2s";}
- virtual ~BLAKE2s() {}
- /// \brief Construct a BLAKE2s hash
- /// \param digestSize the digest size, in bytes
- /// \param treeMode flag indicating tree mode
- /// \since Crypto++ 5.6.4
- BLAKE2s(bool treeMode=false, unsigned int digestSize = DIGESTSIZE);
- /// \brief Construct a BLAKE2s hash
- /// \param digestSize the digest size, in bytes
- /// \details treeMode flag is set to false
- /// \since Crypto++ 8.2
- BLAKE2s(unsigned int digestSize);
- /// \brief Construct a BLAKE2s hash
- /// \param key a byte array used to key the cipher
- /// \param keyLength the size of the byte array
- /// \param salt a byte array used as salt
- /// \param saltLength the size of the byte array
- /// \param personalization a byte array used as personalization string
- /// \param personalizationLength the size of the byte array
- /// \param treeMode flag indicating tree mode
- /// \param digestSize the digest size, in bytes
- /// \since Crypto++ 5.6.4
- BLAKE2s(const byte *key, size_t keyLength, const byte* salt = NULLPTR, size_t saltLength = 0,
- const byte* personalization = NULLPTR, size_t personalizationLength = 0,
- bool treeMode=false, unsigned int digestSize = DIGESTSIZE);
- /// \brief Retrieve the object's name
- /// \return the object's algorithm name following RFC 7693
- /// \details Object algorithm name follows the naming described in
- /// <A HREF="http://tools.ietf.org/html/rfc7693#section-4">RFC 7693, The BLAKE2 Cryptographic Hash and
- /// Message Authentication Code (MAC)</A>. For example, "BLAKE2b-512" and "BLAKE2s-256".
- std::string AlgorithmName() const {return std::string(BLAKE2s_Info::StaticAlgorithmName()) + "-" + IntToString(DigestSize()*8);}
- unsigned int BlockSize() const {return BLOCKSIZE;}
- unsigned int DigestSize() const {return m_digestSize;}
- unsigned int OptimalDataAlignment() const;
- void Update(const byte *input, size_t length);
- void Restart();
- /// \brief Restart a hash with parameter block and counter
- /// \param block parameter block
- /// \param counter counter array
- /// \details Parameter block is persisted across calls to Restart().
- void Restart(const BLAKE2s_ParameterBlock& block, const word32 counter[2]);
- /// \brief Set tree mode
- /// \param mode the new tree mode
- /// \details BLAKE2 has two finalization flags, called State::f[0] and State::f[1].
- /// If <tt>treeMode=false</tt> (default), then State::f[1] is never set. If
- /// <tt>treeMode=true</tt>, then State::f[1] is set when State::f[0] is set.
- /// Tree mode is persisted across calls to Restart().
- void SetTreeMode(bool mode) {m_treeMode=mode;}
- /// \brief Get tree mode
- /// \return the current tree mode
- /// \details Tree mode is persisted across calls to Restart().
- bool GetTreeMode() const {return m_treeMode;}
- void TruncatedFinal(byte *hash, size_t size);
- std::string AlgorithmProvider() const;
- protected:
- // Operates on state buffer and/or input. Must be BLOCKSIZE, final block will pad with 0's.
- void Compress(const byte *input);
- inline void IncrementCounter(size_t count=BLOCKSIZE);
- void UncheckedSetKey(const byte* key, unsigned int length, const CryptoPP::NameValuePairs& params);
- private:
- State m_state;
- ParameterBlock m_block;
- AlignedSecByteBlock m_key;
- word32 m_digestSize, m_keyLength;
- bool m_treeMode;
- };
- /// \brief The BLAKE2b cryptographic hash function
- /// \details BLAKE2b can function as both a hash and keyed hash. If you want only the hash,
- /// then use the BLAKE2b constructor that accepts no parameters or digest size. If you
- /// want a keyed hash, then use the constructor that accpts the key as a parameter.
- /// Once a key and digest size are selected, its effectively immutable. The Restart()
- /// method that accepts a ParameterBlock does not allow you to change it.
- /// \sa Aumasson, Neves, Wilcox-O'Hearn and Winnerlein's
- /// <A HREF="http://blake2.net/blake2.pdf">BLAKE2: simpler, smaller, fast as MD5</A> (2013.01.29).
- /// \since C++ since Crypto++ 5.6.4, SSE since Crypto++ 5.6.4, NEON since Crypto++ 6.0,
- /// Power8 since Crypto++ 8.0
- class BLAKE2b : public SimpleKeyingInterfaceImpl<MessageAuthenticationCode, BLAKE2b_Info>
- {
- public:
- CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH = BLAKE2b_Info::DEFAULT_KEYLENGTH);
- CRYPTOPP_CONSTANT(MIN_KEYLENGTH = BLAKE2b_Info::MIN_KEYLENGTH);
- CRYPTOPP_CONSTANT(MAX_KEYLENGTH = BLAKE2b_Info::MAX_KEYLENGTH);
- CRYPTOPP_CONSTANT(DIGESTSIZE = BLAKE2b_Info::DIGESTSIZE);
- CRYPTOPP_CONSTANT(BLOCKSIZE = BLAKE2b_Info::BLOCKSIZE);
- CRYPTOPP_CONSTANT(SALTSIZE = BLAKE2b_Info::SALTSIZE);
- CRYPTOPP_CONSTANT(PERSONALIZATIONSIZE = BLAKE2b_Info::PERSONALIZATIONSIZE);
- typedef BLAKE2b_State State;
- typedef BLAKE2b_ParameterBlock ParameterBlock;
- CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "BLAKE2b";}
- virtual ~BLAKE2b() {}
- /// \brief Construct a BLAKE2b hash
- /// \param digestSize the digest size, in bytes
- /// \param treeMode flag indicating tree mode
- /// \since Crypto++ 5.6.4
- BLAKE2b(bool treeMode=false, unsigned int digestSize = DIGESTSIZE);
- /// \brief Construct a BLAKE2s hash
- /// \param digestSize the digest size, in bytes
- /// \details treeMode flag is set to false
- /// \since Crypto++ 8.2
- BLAKE2b(unsigned int digestSize);
- /// \brief Construct a BLAKE2b hash
- /// \param key a byte array used to key the cipher
- /// \param keyLength the size of the byte array
- /// \param salt a byte array used as salt
- /// \param saltLength the size of the byte array
- /// \param personalization a byte array used as personalization string
- /// \param personalizationLength the size of the byte array
- /// \param treeMode flag indicating tree mode
- /// \param digestSize the digest size, in bytes
- /// \since Crypto++ 5.6.4
- BLAKE2b(const byte *key, size_t keyLength, const byte* salt = NULLPTR, size_t saltLength = 0,
- const byte* personalization = NULLPTR, size_t personalizationLength = 0,
- bool treeMode=false, unsigned int digestSize = DIGESTSIZE);
- /// \brief Retrieve the object's name
- /// \return the object's algorithm name following RFC 7693
- /// \details Object algorithm name follows the naming described in
- /// <A HREF="http://tools.ietf.org/html/rfc7693#section-4">RFC 7693, The BLAKE2 Cryptographic Hash and
- /// Message Authentication Code (MAC)</A>. For example, "BLAKE2b-512" and "BLAKE2s-256".
- std::string AlgorithmName() const {return std::string(BLAKE2b_Info::StaticAlgorithmName()) + "-" + IntToString(DigestSize()*8);}
- unsigned int BlockSize() const {return BLOCKSIZE;}
- unsigned int DigestSize() const {return m_digestSize;}
- unsigned int OptimalDataAlignment() const;
- void Update(const byte *input, size_t length);
- void Restart();
- /// \brief Restart a hash with parameter block and counter
- /// \param block parameter block
- /// \param counter counter array
- /// \details Parameter block is persisted across calls to Restart().
- void Restart(const BLAKE2b_ParameterBlock& block, const word64 counter[2]);
- /// \brief Set tree mode
- /// \param mode the new tree mode
- /// \details BLAKE2 has two finalization flags, called State::f[0] and State::f[1].
- /// If <tt>treeMode=false</tt> (default), then State::f[1] is never set. If
- /// <tt>treeMode=true</tt>, then State::f[1] is set when State::f[0] is set.
- /// Tree mode is persisted across calls to Restart().
- void SetTreeMode(bool mode) {m_treeMode=mode;}
- /// \brief Get tree mode
- /// \return the current tree mode
- /// \details Tree mode is persisted across calls to Restart().
- bool GetTreeMode() const {return m_treeMode;}
- void TruncatedFinal(byte *hash, size_t size);
- std::string AlgorithmProvider() const;
- protected:
- // Operates on state buffer and/or input. Must be BLOCKSIZE, final block will pad with 0's.
- void Compress(const byte *input);
- inline void IncrementCounter(size_t count=BLOCKSIZE);
- void UncheckedSetKey(const byte* key, unsigned int length, const CryptoPP::NameValuePairs& params);
- private:
- State m_state;
- ParameterBlock m_block;
- AlignedSecByteBlock m_key;
- word32 m_digestSize, m_keyLength;
- bool m_treeMode;
- };
- NAMESPACE_END
- #endif
|