Add SHAKE128 and SHAKE256 (GH #805)
parent
3ea29dec45
commit
6b96dfbe3d
|
|
@ -537,6 +537,7 @@ TestVectors/sha3_256_fips_202.txt
|
|||
TestVectors/sha3_384_fips_202.txt
|
||||
TestVectors/sha3_512_fips_202.txt
|
||||
TestVectors/sha3_fips_202.txt
|
||||
TestVectors/shake.txt
|
||||
TestVectors/shacal2.txt
|
||||
TestVectors/simeck.txt
|
||||
TestVectors/simon.txt
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ Test: TestVectors/seed.txt
|
|||
Test: TestVectors/sha1_fips_180.txt
|
||||
Test: TestVectors/sha2_fips_180.txt
|
||||
Test: TestVectors/sha3_fips_202.txt
|
||||
Test: TestVectors/shake.txt
|
||||
Test: TestVectors/shacal2.txt
|
||||
Test: TestVectors/sha.txt
|
||||
Test: TestVectors/simeck.txt
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
35
chacha.cpp
35
chacha.cpp
|
|
@ -345,9 +345,13 @@ void ChaCha_Policy::CipherSetKey(const NameValuePairs ¶ms, const byte *key,
|
|||
CRYPTOPP_ASSERT(key); CRYPTOPP_ASSERT(length == 16 || length == 32);
|
||||
CRYPTOPP_UNUSED(key); CRYPTOPP_UNUSED(length);
|
||||
|
||||
m_rounds = params.GetIntValueWithDefault(Name::Rounds(), 20);
|
||||
if (m_rounds != 20 && m_rounds != 12 && m_rounds != 8)
|
||||
throw InvalidRounds(ChaCha::StaticAlgorithmName(), m_rounds);
|
||||
// Use previous rounds as the default value
|
||||
int rounds = params.GetIntValueWithDefault(Name::Rounds(), m_rounds);
|
||||
if (rounds != 20 && rounds != 12 && rounds != 8)
|
||||
throw InvalidRounds(ChaCha::StaticAlgorithmName(), rounds);
|
||||
|
||||
// Latch a good value
|
||||
m_rounds = rounds;
|
||||
|
||||
// "expand 16-byte k" or "expand 32-byte k"
|
||||
m_state[0] = 0x61707865;
|
||||
|
|
@ -425,9 +429,9 @@ void ChaChaTLS_Policy::CipherSetKey(const NameValuePairs ¶ms, const byte *ke
|
|||
// the function, so we have to use the heavier-weight SetKey to change it.
|
||||
word64 block;
|
||||
if (params.GetValue("InitialBlock", block))
|
||||
m_state[CTR] = static_cast<word32>(block);
|
||||
m_counter = static_cast<word32>(block);
|
||||
else
|
||||
m_state[CTR] = 0;
|
||||
m_counter = 0;
|
||||
|
||||
// State words are defined in RFC 8439, Section 2.3. Key is 32-bytes.
|
||||
GetBlock<word32, LittleEndian> get(key);
|
||||
|
|
@ -449,7 +453,7 @@ void ChaChaTLS_Policy::CipherResynchronize(byte *keystreamBuffer, const byte *IV
|
|||
|
||||
// State words are defined in RFC 8439, Section 2.3
|
||||
GetBlock<word32, LittleEndian> get(IV);
|
||||
m_state[12] = m_state[CTR];
|
||||
m_state[12] = m_counter;
|
||||
get(m_state[13])(m_state[14])(m_state[15]);
|
||||
}
|
||||
|
||||
|
|
@ -506,16 +510,19 @@ void XChaCha20_Policy::CipherSetKey(const NameValuePairs ¶ms, const byte *ke
|
|||
{
|
||||
CRYPTOPP_ASSERT(key); CRYPTOPP_ASSERT(length == 32);
|
||||
|
||||
// XChaCha20 is always 20 rounds. Fetch Rounds() to avoid a spurious failure.
|
||||
int rounds = params.GetIntValueWithDefault(Name::Rounds(), ROUNDS);
|
||||
if (rounds != 20)
|
||||
throw InvalidRounds(XChaCha20::StaticAlgorithmName(), rounds);
|
||||
// Use previous rounds as the default value
|
||||
int rounds = params.GetIntValueWithDefault(Name::Rounds(), m_rounds);
|
||||
if (rounds != 20 && rounds != 12)
|
||||
throw InvalidRounds(ChaCha::StaticAlgorithmName(), rounds);
|
||||
|
||||
// Latch a good value
|
||||
m_rounds = rounds;
|
||||
|
||||
word64 block;
|
||||
if (params.GetValue("InitialBlock", block))
|
||||
m_state[CTR] = static_cast<word32>(block);
|
||||
m_counter = static_cast<word32>(block);
|
||||
else
|
||||
m_state[CTR] = 1;
|
||||
m_counter = 1;
|
||||
|
||||
// Stash key away for use in CipherResynchronize
|
||||
GetBlock<word32, LittleEndian> get(key);
|
||||
|
|
@ -548,7 +555,7 @@ void XChaCha20_Policy::CipherResynchronize(byte *keystreamBuffer, const byte *iv
|
|||
m_state[2] = 0x79622d32; m_state[3] = 0x6b206574;
|
||||
|
||||
// Setup new IV
|
||||
m_state[12] = m_state[CTR];
|
||||
m_state[12] = m_counter;
|
||||
m_state[13] = 0;
|
||||
m_state[14] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, iv+16);
|
||||
m_state[15] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, iv+20);
|
||||
|
|
@ -575,7 +582,7 @@ void XChaCha20_Policy::OperateKeystream(KeystreamOperation operation,
|
|||
byte *output, const byte *input, size_t iterationCount)
|
||||
{
|
||||
ChaCha_OperateKeystream(operation, m_state, m_state[12], m_state[13],
|
||||
ROUNDS, output, input, iterationCount);
|
||||
m_rounds, output, input, iterationCount);
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
|
|
|
|||
18
chacha.h
18
chacha.h
|
|
@ -58,7 +58,7 @@ class CRYPTOPP_NO_VTABLE ChaCha_Policy : public AdditiveCipherConcretePolicy<wor
|
|||
{
|
||||
public:
|
||||
virtual ~ChaCha_Policy() {}
|
||||
ChaCha_Policy() : m_rounds(0) {}
|
||||
ChaCha_Policy() : m_rounds(ROUNDS) {}
|
||||
|
||||
protected:
|
||||
void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length);
|
||||
|
|
@ -72,6 +72,7 @@ protected:
|
|||
std::string AlgorithmName() const;
|
||||
std::string AlgorithmProvider() const;
|
||||
|
||||
CRYPTOPP_CONSTANT(ROUNDS = 20) // Default rounds
|
||||
FixedSizeAlignedSecBlock<word32, 16> m_state;
|
||||
unsigned int m_rounds;
|
||||
};
|
||||
|
|
@ -114,7 +115,7 @@ class CRYPTOPP_NO_VTABLE ChaChaTLS_Policy : public AdditiveCipherConcretePolicy<
|
|||
{
|
||||
public:
|
||||
virtual ~ChaChaTLS_Policy() {}
|
||||
ChaChaTLS_Policy() {}
|
||||
ChaChaTLS_Policy() : m_counter(0) {}
|
||||
|
||||
protected:
|
||||
void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length);
|
||||
|
|
@ -128,7 +129,8 @@ protected:
|
|||
std::string AlgorithmName() const;
|
||||
std::string AlgorithmProvider() const;
|
||||
|
||||
FixedSizeAlignedSecBlock<word32, 16+8+1> m_state;
|
||||
FixedSizeAlignedSecBlock<word32, 16+8> m_state;
|
||||
unsigned int m_counter;
|
||||
CRYPTOPP_CONSTANT(ROUNDS = ChaChaTLS_Info::ROUNDS)
|
||||
CRYPTOPP_CONSTANT(KEY = 16) // Index into m_state
|
||||
CRYPTOPP_CONSTANT(CTR = 24) // Index into m_state
|
||||
|
|
@ -161,7 +163,7 @@ struct ChaChaTLS : public ChaChaTLS_Info, public SymmetricCipherDocumentation
|
|||
|
||||
/// \brief XChaCha stream cipher information
|
||||
/// \since Crypto++ 8.1
|
||||
struct XChaCha20_Info : public FixedKeyLength<32, SimpleKeyingInterface::UNIQUE_IV, 24>, FixedRounds<20>
|
||||
struct XChaCha20_Info : public FixedKeyLength<32, SimpleKeyingInterface::UNIQUE_IV, 24>
|
||||
{
|
||||
/// \brief The algorithm name
|
||||
/// \returns the algorithm name
|
||||
|
|
@ -179,7 +181,7 @@ class CRYPTOPP_NO_VTABLE XChaCha20_Policy : public AdditiveCipherConcretePolicy<
|
|||
{
|
||||
public:
|
||||
virtual ~XChaCha20_Policy() {}
|
||||
XChaCha20_Policy() {}
|
||||
XChaCha20_Policy() : m_counter(0), m_rounds(ROUNDS) {}
|
||||
|
||||
protected:
|
||||
void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length);
|
||||
|
|
@ -193,10 +195,10 @@ protected:
|
|||
std::string AlgorithmName() const;
|
||||
std::string AlgorithmProvider() const;
|
||||
|
||||
FixedSizeAlignedSecBlock<word32, 16+8+1> m_state;
|
||||
CRYPTOPP_CONSTANT(ROUNDS = XChaCha20_Info::ROUNDS)
|
||||
FixedSizeAlignedSecBlock<word32, 16+8> m_state;
|
||||
unsigned int m_counter, m_rounds;
|
||||
CRYPTOPP_CONSTANT(ROUNDS = 20) // Default rounds
|
||||
CRYPTOPP_CONSTANT(KEY = 16) // Index into m_state
|
||||
CRYPTOPP_CONSTANT(CTR = 24) // Index into m_state
|
||||
};
|
||||
|
||||
/// \brief XChaCha stream cipher
|
||||
|
|
|
|||
13
keccak.h
13
keccak.h
|
|
@ -48,8 +48,6 @@ public:
|
|||
/// \since Crypto++ 5.6.4
|
||||
Keccak(unsigned int digestSize) : m_digestSize(digestSize) {Restart();}
|
||||
unsigned int DigestSize() const {return m_digestSize;}
|
||||
std::string AlgorithmName() const {return "Keccak-" + IntToString(m_digestSize*8);}
|
||||
CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "Keccak"; }
|
||||
unsigned int OptimalDataAlignment() const {return GetAlignmentOf<word64>();}
|
||||
|
||||
void Update(const byte *input, size_t length);
|
||||
|
|
@ -57,7 +55,7 @@ public:
|
|||
void TruncatedFinal(byte *hash, size_t size);
|
||||
|
||||
protected:
|
||||
inline unsigned int r() const {return 200 - 2 * m_digestSize;}
|
||||
inline unsigned int r() const {return BlockSize();}
|
||||
|
||||
FixedSizeSecBlock<word64, 25> m_state;
|
||||
unsigned int m_digestSize, m_counter;
|
||||
|
|
@ -77,6 +75,7 @@ public:
|
|||
Keccak_Final() : Keccak(DIGESTSIZE) {}
|
||||
static std::string StaticAlgorithmName() { return "Keccak-" + IntToString(DIGESTSIZE * 8); }
|
||||
unsigned int BlockSize() const { return BLOCKSIZE; }
|
||||
|
||||
private:
|
||||
CRYPTOPP_COMPILE_ASSERT(BLOCKSIZE < 200); // ensure there was no underflow in the math
|
||||
CRYPTOPP_COMPILE_ASSERT(BLOCKSIZE > (int)T_DigestSize); // this is a general expectation by HMAC
|
||||
|
|
@ -84,19 +83,19 @@ private:
|
|||
|
||||
/// \brief Keccak-224 message digest
|
||||
/// \since Crypto++ 5.6.4
|
||||
typedef Keccak_Final<28> Keccak_224;
|
||||
DOCUMENTED_TYPEDEF(Keccak_Final<28>, Keccak_224);
|
||||
|
||||
/// \brief Keccak-256 message digest
|
||||
/// \since Crypto++ 5.6.4
|
||||
typedef Keccak_Final<32> Keccak_256;
|
||||
DOCUMENTED_TYPEDEF(Keccak_Final<32>, Keccak_256);
|
||||
|
||||
/// \brief Keccak-384 message digest
|
||||
/// \since Crypto++ 5.6.4
|
||||
typedef Keccak_Final<48> Keccak_384;
|
||||
DOCUMENTED_TYPEDEF(Keccak_Final<48>, Keccak_384);
|
||||
|
||||
/// \brief Keccak-512 message digest
|
||||
/// \since Crypto++ 5.6.4
|
||||
typedef Keccak_Final<64> Keccak_512;
|
||||
DOCUMENTED_TYPEDEF(Keccak_Final<64>, Keccak_512);
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#include "md5.h"
|
||||
#include "keccak.h"
|
||||
#include "sha3.h"
|
||||
#include "shake.h"
|
||||
#include "blake2.h"
|
||||
#include "sha.h"
|
||||
#include "sha3.h"
|
||||
|
|
@ -109,6 +110,8 @@ void RegisterFactories1()
|
|||
RegisterDefaultFactoryFor<HashTransformation, SHA3_256>();
|
||||
RegisterDefaultFactoryFor<HashTransformation, SHA3_384>();
|
||||
RegisterDefaultFactoryFor<HashTransformation, SHA3_512>();
|
||||
RegisterDefaultFactoryFor<HashTransformation, SHAKE128>();
|
||||
RegisterDefaultFactoryFor<HashTransformation, SHAKE256>();
|
||||
RegisterDefaultFactoryFor<HashTransformation, SM3>();
|
||||
RegisterDefaultFactoryFor<HashTransformation, BLAKE2s>();
|
||||
RegisterDefaultFactoryFor<HashTransformation, BLAKE2b>();
|
||||
|
|
|
|||
12
salsa.cpp
12
salsa.cpp
|
|
@ -112,10 +112,13 @@ std::string Salsa20_Policy::AlgorithmProvider() const
|
|||
|
||||
void Salsa20_Policy::CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length)
|
||||
{
|
||||
m_rounds = params.GetIntValueWithDefault(Name::Rounds(), 20);
|
||||
// Use previous rounds as the default value
|
||||
int rounds = params.GetIntValueWithDefault(Name::Rounds(), m_rounds);
|
||||
if (rounds != 20 && rounds != 12 && rounds != 8)
|
||||
throw InvalidRounds(Salsa20::StaticAlgorithmName(), rounds);
|
||||
|
||||
if (!(m_rounds == 8 || m_rounds == 12 || m_rounds == 20))
|
||||
throw InvalidRounds(Salsa20::StaticAlgorithmName(), m_rounds);
|
||||
// Latch a good value
|
||||
m_rounds = rounds;
|
||||
|
||||
// m_state is reordered for SSE2
|
||||
GetBlock<word32, LittleEndian> get1(key);
|
||||
|
|
@ -692,8 +695,7 @@ Salsa20_OperateKeystream ENDP
|
|||
|
||||
void XSalsa20_Policy::CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length)
|
||||
{
|
||||
m_rounds = params.GetIntValueWithDefault(Name::Rounds(), 20);
|
||||
|
||||
m_rounds = params.GetIntValueWithDefault(Name::Rounds(), m_rounds);
|
||||
if (!(m_rounds == 8 || m_rounds == 12 || m_rounds == 20))
|
||||
throw InvalidRounds(XSalsa20::StaticAlgorithmName(), m_rounds);
|
||||
|
||||
|
|
|
|||
2
salsa.h
2
salsa.h
|
|
@ -36,6 +36,7 @@ struct Salsa20_Info : public VariableKeyLength<32, 16, 32, 16, SimpleKeyingInter
|
|||
class CRYPTOPP_NO_VTABLE Salsa20_Policy : public AdditiveCipherConcretePolicy<word32, 16>
|
||||
{
|
||||
protected:
|
||||
Salsa20_Policy() : m_rounds(ROUNDS) {}
|
||||
void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length);
|
||||
void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount);
|
||||
void CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length);
|
||||
|
|
@ -49,6 +50,7 @@ protected:
|
|||
|
||||
std::string AlgorithmProvider() const;
|
||||
|
||||
CRYPTOPP_CONSTANT(ROUNDS = 20) // Default rounds
|
||||
FixedSizeAlignedSecBlock<word32, 16> m_state;
|
||||
int m_rounds;
|
||||
};
|
||||
|
|
|
|||
68
sha3.h
68
sha3.h
|
|
@ -27,27 +27,24 @@ NAMESPACE_BEGIN(CryptoPP)
|
|||
class SHA3 : public HashTransformation
|
||||
{
|
||||
public:
|
||||
/// \brief Construct a SHA3
|
||||
/// \param digestSize the digest size, in bytes
|
||||
/// \details SHA3 is the base class for SHA3_224, SHA3_256, SHA3_384 and SHA3_512.
|
||||
/// Library users should instantiate a derived class, and only use SHA3
|
||||
/// as a base class reference or pointer.
|
||||
SHA3(unsigned int digestSize) : m_digestSize(digestSize) {Restart();}
|
||||
unsigned int DigestSize() const {return m_digestSize;}
|
||||
std::string AlgorithmName() const {return "SHA3-" + IntToString(m_digestSize*8);}
|
||||
CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "SHA3"; }
|
||||
unsigned int OptimalDataAlignment() const {return GetAlignmentOf<word64>();}
|
||||
/// \brief Construct a SHA3
|
||||
/// \param digestSize the digest size, in bytes
|
||||
/// \details SHA3 is the base class for SHA3_224, SHA3_256, SHA3_384 and SHA3_512.
|
||||
/// Library users should instantiate a derived class, and only use SHA3
|
||||
/// as a base class reference or pointer.
|
||||
SHA3(unsigned int digestSize) : m_digestSize(digestSize) {Restart();}
|
||||
unsigned int DigestSize() const {return m_digestSize;}
|
||||
unsigned int OptimalDataAlignment() const {return GetAlignmentOf<word64>();}
|
||||
|
||||
void Update(const byte *input, size_t length);
|
||||
void Restart();
|
||||
void TruncatedFinal(byte *hash, size_t size);
|
||||
void Update(const byte *input, size_t length);
|
||||
void Restart();
|
||||
void TruncatedFinal(byte *hash, size_t size);
|
||||
|
||||
// unsigned int BlockSize() const { return r(); } // that's the idea behind it
|
||||
protected:
|
||||
inline unsigned int r() const {return 200 - 2 * m_digestSize;}
|
||||
inline unsigned int r() const {return BlockSize();}
|
||||
|
||||
FixedSizeSecBlock<word64, 25> m_state;
|
||||
unsigned int m_digestSize, m_counter;
|
||||
FixedSizeSecBlock<word64, 25> m_state;
|
||||
unsigned int m_digestSize, m_counter;
|
||||
};
|
||||
|
||||
/// \brief SHA3 message digest template
|
||||
|
|
@ -57,47 +54,36 @@ template<unsigned int T_DigestSize>
|
|||
class SHA3_Final : public SHA3
|
||||
{
|
||||
public:
|
||||
CRYPTOPP_CONSTANT(DIGESTSIZE = T_DigestSize)
|
||||
CRYPTOPP_CONSTANT(BLOCKSIZE = 200 - 2 * DIGESTSIZE)
|
||||
CRYPTOPP_CONSTANT(DIGESTSIZE = T_DigestSize)
|
||||
CRYPTOPP_CONSTANT(BLOCKSIZE = 200 - 2 * DIGESTSIZE)
|
||||
|
||||
/// \brief Construct a SHA3-X message digest
|
||||
SHA3_Final() : SHA3(DIGESTSIZE) {}
|
||||
static std::string StaticAlgorithmName() { return "SHA3-" + IntToString(DIGESTSIZE * 8); }
|
||||
unsigned int BlockSize() const { return BLOCKSIZE; }
|
||||
|
||||
/// \brief Construct a SHA3-X message digest
|
||||
SHA3_Final() : SHA3(DIGESTSIZE) {}
|
||||
static std::string StaticAlgorithmName() { return "SHA3-" + IntToString(DIGESTSIZE * 8); }
|
||||
unsigned int BlockSize() const { return BLOCKSIZE; }
|
||||
private:
|
||||
#if !defined(__BORLANDC__)
|
||||
CRYPTOPP_COMPILE_ASSERT(BLOCKSIZE < 200); // ensure there was no underflow in the math
|
||||
CRYPTOPP_COMPILE_ASSERT(BLOCKSIZE > (int)T_DigestSize); // this is a general expectation by HMAC
|
||||
CRYPTOPP_COMPILE_ASSERT(BLOCKSIZE < 200); // ensure there was no underflow in the math
|
||||
CRYPTOPP_COMPILE_ASSERT(BLOCKSIZE > (int)T_DigestSize); // this is a general expectation by HMAC
|
||||
#endif
|
||||
};
|
||||
|
||||
/// \brief SHA3-224 message digest
|
||||
/// \since Crypto++ 5.6.2
|
||||
// typedef SHA3_Final<28> SHA3_224;
|
||||
class SHA3_224 : public SHA3_Final<28>
|
||||
{
|
||||
};
|
||||
class SHA3_224 : public SHA3_Final<28> {};
|
||||
|
||||
/// \brief SHA3-256 message digest
|
||||
/// \since Crypto++ 5.6.2
|
||||
// typedef SHA3_Final<32> SHA3_256;
|
||||
class SHA3_256 : public SHA3_Final<32>
|
||||
{
|
||||
};
|
||||
class SHA3_256 : public SHA3_Final<32> {};
|
||||
|
||||
/// \brief SHA3-384 message digest
|
||||
/// \since Crypto++ 5.6.2
|
||||
// typedef SHA3_Final<48> SHA3_384;
|
||||
class SHA3_384 : public SHA3_Final<48>
|
||||
{
|
||||
};
|
||||
class SHA3_384 : public SHA3_Final<48> {};
|
||||
|
||||
/// \brief SHA3-512 message digest
|
||||
/// \since Crypto++ 5.6.2
|
||||
// typedef SHA3_Final<64> SHA3_512;
|
||||
class SHA3_512 : public SHA3_Final<64>
|
||||
{
|
||||
};
|
||||
class SHA3_512 : public SHA3_Final<64> {};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
// shake.cpp - modified by Wei Dai from Ronny Van Keer's public domain
|
||||
// sha3-simple.c. All modifications here are placed in the
|
||||
// public domain by Wei Dai.
|
||||
// Keccack core function moved to keccakc.cpp in AUG 2018
|
||||
// by Jeffrey Walton. Separating the core file allows both
|
||||
// SHA3 and Keccack to share the core implementation.
|
||||
|
||||
/*
|
||||
The SHAKE sponge function, designed by Guido Bertoni, Joan Daemen,
|
||||
Michael Peeters and Gilles Van Assche. For more information, feedback or
|
||||
questions, please refer to our website: http://keccak.noekeon.org/
|
||||
|
||||
Implementation by Ronny Van Keer, hereby denoted as "the implementer".
|
||||
|
||||
To the extent possible under law, the implementer has waived all copyright
|
||||
and related or neighboring rights to the source code in this file.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
#include "pch.h"
|
||||
#include "shake.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
// The Keccak core function
|
||||
extern void KeccakF1600(word64 *state);
|
||||
|
||||
void SHAKE::Update(const byte *input, size_t length)
|
||||
{
|
||||
CRYPTOPP_ASSERT(!(input == NULLPTR && length != 0));
|
||||
if (length == 0) { return; }
|
||||
|
||||
size_t spaceLeft;
|
||||
while (length >= (spaceLeft = r() - m_counter))
|
||||
{
|
||||
if (spaceLeft)
|
||||
xorbuf(m_state.BytePtr() + m_counter, input, spaceLeft);
|
||||
KeccakF1600(m_state);
|
||||
input += spaceLeft;
|
||||
length -= spaceLeft;
|
||||
m_counter = 0;
|
||||
}
|
||||
|
||||
if (length)
|
||||
xorbuf(m_state.BytePtr() + m_counter, input, length);
|
||||
m_counter += (unsigned int)length;
|
||||
}
|
||||
|
||||
void SHAKE::Restart()
|
||||
{
|
||||
memset(m_state, 0, m_state.SizeInBytes());
|
||||
m_counter = 0;
|
||||
}
|
||||
|
||||
void SHAKE::TruncatedFinal(byte *hash, size_t size)
|
||||
{
|
||||
CRYPTOPP_ASSERT(hash != NULLPTR);
|
||||
ThrowIfInvalidTruncatedSize(size);
|
||||
|
||||
m_state.BytePtr()[m_counter] ^= 0x1F;
|
||||
m_state.BytePtr()[r()-1] ^= 0x80;
|
||||
KeccakF1600(m_state);
|
||||
std::memcpy(hash, m_state, size);
|
||||
Restart();
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
// shake.h - originally written and placed in the public domain by Jeffrey Walton
|
||||
|
||||
/// \file shake.h
|
||||
/// \brief Classes for SHAKE message digests
|
||||
/// \sa SHA3, SHAKE128, SHAKE256,
|
||||
/// <a href="https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf">FIPS 202,
|
||||
/// SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions</a>
|
||||
/// \since Crypto++ 8.1
|
||||
|
||||
#ifndef CRYPTOPP_SHAKE_H
|
||||
#define CRYPTOPP_SHAKE_H
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include "secblock.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
/// \brief SHAKE message digest base class
|
||||
/// \details SHAKE is the base class for SHAKE128 and SHAKE258.
|
||||
/// Library users should instantiate a derived class, and only use SHAKE
|
||||
/// as a base class reference or pointer.
|
||||
/// \sa SHA3, SHAKE128, SHAKE256,
|
||||
/// <a href="https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf">FIPS 202,
|
||||
/// SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions</a>
|
||||
/// \since Crypto++ 8.1
|
||||
class SHAKE : public HashTransformation
|
||||
{
|
||||
public:
|
||||
/// \brief Construct a SHAKE
|
||||
/// \param digestSize the digest size, in bytes
|
||||
/// \details SHAKE is the base class for SHAKE128 and SHAKE256.
|
||||
/// Library users should instantiate a derived class, and only use SHAKE
|
||||
/// as a base class reference or pointer.
|
||||
/// \since Crypto++ 8.1
|
||||
SHAKE(unsigned int digestSize) : m_digestSize(digestSize) {Restart();}
|
||||
unsigned int DigestSize() const {return m_digestSize;}
|
||||
unsigned int OptimalDataAlignment() const {return GetAlignmentOf<word64>();}
|
||||
|
||||
void Update(const byte *input, size_t length);
|
||||
void Restart();
|
||||
void TruncatedFinal(byte *hash, size_t size);
|
||||
|
||||
protected:
|
||||
inline unsigned int r() const {return BlockSize();}
|
||||
|
||||
FixedSizeSecBlock<word64, 25> m_state;
|
||||
unsigned int m_digestSize, m_counter;
|
||||
};
|
||||
|
||||
/// \brief SHAKE message digest template
|
||||
/// \tparam T_Strength the strength of the digest
|
||||
/// \since Crypto++ 6.0
|
||||
template<unsigned int T_Strength>
|
||||
class SHAKE_Final : public SHAKE
|
||||
{
|
||||
public:
|
||||
CRYPTOPP_CONSTANT(DIGESTSIZE = (T_Strength == 128 ? 32 : 64))
|
||||
CRYPTOPP_CONSTANT(BLOCKSIZE = (T_Strength == 128 ? 1344/8 : 1088/8))
|
||||
static std::string StaticAlgorithmName() { return "SHAKE" + IntToString(T_Strength); }
|
||||
|
||||
/// \brief Construct a SHAKE-X message digest
|
||||
SHAKE_Final() : SHAKE(DIGESTSIZE) {}
|
||||
unsigned int BlockSize() const { return BLOCKSIZE; }
|
||||
|
||||
private:
|
||||
CRYPTOPP_COMPILE_ASSERT(T_Strength == 128 || T_Strength == 256);
|
||||
CRYPTOPP_COMPILE_ASSERT(BLOCKSIZE < 200); // ensure there was no underflow in the math
|
||||
};
|
||||
|
||||
/// \brief SHAKE128 message digest
|
||||
/// \since Crypto++ 8.1
|
||||
class SHAKE128 : public SHAKE_Final<128> {};
|
||||
|
||||
/// \brief SHAKE256 message digest
|
||||
/// \since Crypto++ 8.1
|
||||
class SHAKE256 : public SHAKE_Final<256> {};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
Loading…
Reference in New Issue