Add SHAKE128 and SHAKE256 (GH #805)

pull/806/head
Jeffrey Walton 2019-02-12 19:20:24 -05:00
parent 3ea29dec45
commit 6b96dfbe3d
No known key found for this signature in database
GPG Key ID: B36AB348921B1838
12 changed files with 1279 additions and 219 deletions

View File

@ -537,6 +537,7 @@ TestVectors/sha3_256_fips_202.txt
TestVectors/sha3_384_fips_202.txt TestVectors/sha3_384_fips_202.txt
TestVectors/sha3_512_fips_202.txt TestVectors/sha3_512_fips_202.txt
TestVectors/sha3_fips_202.txt TestVectors/sha3_fips_202.txt
TestVectors/shake.txt
TestVectors/shacal2.txt TestVectors/shacal2.txt
TestVectors/simeck.txt TestVectors/simeck.txt
TestVectors/simon.txt TestVectors/simon.txt

View File

@ -43,6 +43,7 @@ Test: TestVectors/seed.txt
Test: TestVectors/sha1_fips_180.txt Test: TestVectors/sha1_fips_180.txt
Test: TestVectors/sha2_fips_180.txt Test: TestVectors/sha2_fips_180.txt
Test: TestVectors/sha3_fips_202.txt Test: TestVectors/sha3_fips_202.txt
Test: TestVectors/shake.txt
Test: TestVectors/shacal2.txt Test: TestVectors/shacal2.txt
Test: TestVectors/sha.txt Test: TestVectors/sha.txt
Test: TestVectors/simeck.txt Test: TestVectors/simeck.txt

File diff suppressed because one or more lines are too long

View File

@ -345,9 +345,13 @@ void ChaCha_Policy::CipherSetKey(const NameValuePairs &params, const byte *key,
CRYPTOPP_ASSERT(key); CRYPTOPP_ASSERT(length == 16 || length == 32); CRYPTOPP_ASSERT(key); CRYPTOPP_ASSERT(length == 16 || length == 32);
CRYPTOPP_UNUSED(key); CRYPTOPP_UNUSED(length); CRYPTOPP_UNUSED(key); CRYPTOPP_UNUSED(length);
m_rounds = params.GetIntValueWithDefault(Name::Rounds(), 20); // Use previous rounds as the default value
if (m_rounds != 20 && m_rounds != 12 && m_rounds != 8) int rounds = params.GetIntValueWithDefault(Name::Rounds(), m_rounds);
throw InvalidRounds(ChaCha::StaticAlgorithmName(), 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" // "expand 16-byte k" or "expand 32-byte k"
m_state[0] = 0x61707865; m_state[0] = 0x61707865;
@ -425,9 +429,9 @@ void ChaChaTLS_Policy::CipherSetKey(const NameValuePairs &params, const byte *ke
// the function, so we have to use the heavier-weight SetKey to change it. // the function, so we have to use the heavier-weight SetKey to change it.
word64 block; word64 block;
if (params.GetValue("InitialBlock", block)) if (params.GetValue("InitialBlock", block))
m_state[CTR] = static_cast<word32>(block); m_counter = static_cast<word32>(block);
else else
m_state[CTR] = 0; m_counter = 0;
// State words are defined in RFC 8439, Section 2.3. Key is 32-bytes. // State words are defined in RFC 8439, Section 2.3. Key is 32-bytes.
GetBlock<word32, LittleEndian> get(key); 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 // State words are defined in RFC 8439, Section 2.3
GetBlock<word32, LittleEndian> get(IV); 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]); get(m_state[13])(m_state[14])(m_state[15]);
} }
@ -506,16 +510,19 @@ void XChaCha20_Policy::CipherSetKey(const NameValuePairs &params, const byte *ke
{ {
CRYPTOPP_ASSERT(key); CRYPTOPP_ASSERT(length == 32); CRYPTOPP_ASSERT(key); CRYPTOPP_ASSERT(length == 32);
// XChaCha20 is always 20 rounds. Fetch Rounds() to avoid a spurious failure. // Use previous rounds as the default value
int rounds = params.GetIntValueWithDefault(Name::Rounds(), ROUNDS); int rounds = params.GetIntValueWithDefault(Name::Rounds(), m_rounds);
if (rounds != 20) if (rounds != 20 && rounds != 12)
throw InvalidRounds(XChaCha20::StaticAlgorithmName(), rounds); throw InvalidRounds(ChaCha::StaticAlgorithmName(), rounds);
// Latch a good value
m_rounds = rounds;
word64 block; word64 block;
if (params.GetValue("InitialBlock", block)) if (params.GetValue("InitialBlock", block))
m_state[CTR] = static_cast<word32>(block); m_counter = static_cast<word32>(block);
else else
m_state[CTR] = 1; m_counter = 1;
// Stash key away for use in CipherResynchronize // Stash key away for use in CipherResynchronize
GetBlock<word32, LittleEndian> get(key); 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; m_state[2] = 0x79622d32; m_state[3] = 0x6b206574;
// Setup new IV // Setup new IV
m_state[12] = m_state[CTR]; m_state[12] = m_counter;
m_state[13] = 0; m_state[13] = 0;
m_state[14] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, iv+16); m_state[14] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, iv+16);
m_state[15] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, iv+20); 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) byte *output, const byte *input, size_t iterationCount)
{ {
ChaCha_OperateKeystream(operation, m_state, m_state[12], m_state[13], ChaCha_OperateKeystream(operation, m_state, m_state[12], m_state[13],
ROUNDS, output, input, iterationCount); m_rounds, output, input, iterationCount);
} }
NAMESPACE_END NAMESPACE_END

View File

@ -58,7 +58,7 @@ class CRYPTOPP_NO_VTABLE ChaCha_Policy : public AdditiveCipherConcretePolicy<wor
{ {
public: public:
virtual ~ChaCha_Policy() {} virtual ~ChaCha_Policy() {}
ChaCha_Policy() : m_rounds(0) {} ChaCha_Policy() : m_rounds(ROUNDS) {}
protected: protected:
void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length); void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length);
@ -72,6 +72,7 @@ protected:
std::string AlgorithmName() const; std::string AlgorithmName() const;
std::string AlgorithmProvider() const; std::string AlgorithmProvider() const;
CRYPTOPP_CONSTANT(ROUNDS = 20) // Default rounds
FixedSizeAlignedSecBlock<word32, 16> m_state; FixedSizeAlignedSecBlock<word32, 16> m_state;
unsigned int m_rounds; unsigned int m_rounds;
}; };
@ -114,7 +115,7 @@ class CRYPTOPP_NO_VTABLE ChaChaTLS_Policy : public AdditiveCipherConcretePolicy<
{ {
public: public:
virtual ~ChaChaTLS_Policy() {} virtual ~ChaChaTLS_Policy() {}
ChaChaTLS_Policy() {} ChaChaTLS_Policy() : m_counter(0) {}
protected: protected:
void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length); void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length);
@ -128,7 +129,8 @@ protected:
std::string AlgorithmName() const; std::string AlgorithmName() const;
std::string AlgorithmProvider() 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(ROUNDS = ChaChaTLS_Info::ROUNDS)
CRYPTOPP_CONSTANT(KEY = 16) // Index into m_state CRYPTOPP_CONSTANT(KEY = 16) // Index into m_state
CRYPTOPP_CONSTANT(CTR = 24) // 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 /// \brief XChaCha stream cipher information
/// \since Crypto++ 8.1 /// \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 /// \brief The algorithm name
/// \returns the algorithm name /// \returns the algorithm name
@ -179,7 +181,7 @@ class CRYPTOPP_NO_VTABLE XChaCha20_Policy : public AdditiveCipherConcretePolicy<
{ {
public: public:
virtual ~XChaCha20_Policy() {} virtual ~XChaCha20_Policy() {}
XChaCha20_Policy() {} XChaCha20_Policy() : m_counter(0), m_rounds(ROUNDS) {}
protected: protected:
void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length); void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length);
@ -193,10 +195,10 @@ protected:
std::string AlgorithmName() const; std::string AlgorithmName() const;
std::string AlgorithmProvider() const; std::string AlgorithmProvider() const;
FixedSizeAlignedSecBlock<word32, 16+8+1> m_state; FixedSizeAlignedSecBlock<word32, 16+8> m_state;
CRYPTOPP_CONSTANT(ROUNDS = XChaCha20_Info::ROUNDS) unsigned int m_counter, m_rounds;
CRYPTOPP_CONSTANT(ROUNDS = 20) // Default rounds
CRYPTOPP_CONSTANT(KEY = 16) // Index into m_state CRYPTOPP_CONSTANT(KEY = 16) // Index into m_state
CRYPTOPP_CONSTANT(CTR = 24) // Index into m_state
}; };
/// \brief XChaCha stream cipher /// \brief XChaCha stream cipher

View File

@ -48,8 +48,6 @@ public:
/// \since Crypto++ 5.6.4 /// \since Crypto++ 5.6.4
Keccak(unsigned int digestSize) : m_digestSize(digestSize) {Restart();} Keccak(unsigned int digestSize) : m_digestSize(digestSize) {Restart();}
unsigned int DigestSize() const {return m_digestSize;} 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>();} unsigned int OptimalDataAlignment() const {return GetAlignmentOf<word64>();}
void Update(const byte *input, size_t length); void Update(const byte *input, size_t length);
@ -57,7 +55,7 @@ public:
void TruncatedFinal(byte *hash, size_t size); void TruncatedFinal(byte *hash, size_t size);
protected: protected:
inline unsigned int r() const {return 200 - 2 * m_digestSize;} inline unsigned int r() const {return BlockSize();}
FixedSizeSecBlock<word64, 25> m_state; FixedSizeSecBlock<word64, 25> m_state;
unsigned int m_digestSize, m_counter; unsigned int m_digestSize, m_counter;
@ -77,6 +75,7 @@ public:
Keccak_Final() : Keccak(DIGESTSIZE) {} Keccak_Final() : Keccak(DIGESTSIZE) {}
static std::string StaticAlgorithmName() { return "Keccak-" + IntToString(DIGESTSIZE * 8); } static std::string StaticAlgorithmName() { return "Keccak-" + IntToString(DIGESTSIZE * 8); }
unsigned int BlockSize() const { return BLOCKSIZE; } unsigned int BlockSize() const { return BLOCKSIZE; }
private: private:
CRYPTOPP_COMPILE_ASSERT(BLOCKSIZE < 200); // ensure there was no underflow in the math 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 > (int)T_DigestSize); // this is a general expectation by HMAC
@ -84,19 +83,19 @@ private:
/// \brief Keccak-224 message digest /// \brief Keccak-224 message digest
/// \since Crypto++ 5.6.4 /// \since Crypto++ 5.6.4
typedef Keccak_Final<28> Keccak_224; DOCUMENTED_TYPEDEF(Keccak_Final<28>, Keccak_224);
/// \brief Keccak-256 message digest /// \brief Keccak-256 message digest
/// \since Crypto++ 5.6.4 /// \since Crypto++ 5.6.4
typedef Keccak_Final<32> Keccak_256; DOCUMENTED_TYPEDEF(Keccak_Final<32>, Keccak_256);
/// \brief Keccak-384 message digest /// \brief Keccak-384 message digest
/// \since Crypto++ 5.6.4 /// \since Crypto++ 5.6.4
typedef Keccak_Final<48> Keccak_384; DOCUMENTED_TYPEDEF(Keccak_Final<48>, Keccak_384);
/// \brief Keccak-512 message digest /// \brief Keccak-512 message digest
/// \since Crypto++ 5.6.4 /// \since Crypto++ 5.6.4
typedef Keccak_Final<64> Keccak_512; DOCUMENTED_TYPEDEF(Keccak_Final<64>, Keccak_512);
NAMESPACE_END NAMESPACE_END

View File

@ -15,6 +15,7 @@
#include "md5.h" #include "md5.h"
#include "keccak.h" #include "keccak.h"
#include "sha3.h" #include "sha3.h"
#include "shake.h"
#include "blake2.h" #include "blake2.h"
#include "sha.h" #include "sha.h"
#include "sha3.h" #include "sha3.h"
@ -109,6 +110,8 @@ void RegisterFactories1()
RegisterDefaultFactoryFor<HashTransformation, SHA3_256>(); RegisterDefaultFactoryFor<HashTransformation, SHA3_256>();
RegisterDefaultFactoryFor<HashTransformation, SHA3_384>(); RegisterDefaultFactoryFor<HashTransformation, SHA3_384>();
RegisterDefaultFactoryFor<HashTransformation, SHA3_512>(); RegisterDefaultFactoryFor<HashTransformation, SHA3_512>();
RegisterDefaultFactoryFor<HashTransformation, SHAKE128>();
RegisterDefaultFactoryFor<HashTransformation, SHAKE256>();
RegisterDefaultFactoryFor<HashTransformation, SM3>(); RegisterDefaultFactoryFor<HashTransformation, SM3>();
RegisterDefaultFactoryFor<HashTransformation, BLAKE2s>(); RegisterDefaultFactoryFor<HashTransformation, BLAKE2s>();
RegisterDefaultFactoryFor<HashTransformation, BLAKE2b>(); RegisterDefaultFactoryFor<HashTransformation, BLAKE2b>();

View File

@ -112,10 +112,13 @@ std::string Salsa20_Policy::AlgorithmProvider() const
void Salsa20_Policy::CipherSetKey(const NameValuePairs &params, const byte *key, size_t length) void Salsa20_Policy::CipherSetKey(const NameValuePairs &params, 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)) // Latch a good value
throw InvalidRounds(Salsa20::StaticAlgorithmName(), m_rounds); m_rounds = rounds;
// m_state is reordered for SSE2 // m_state is reordered for SSE2
GetBlock<word32, LittleEndian> get1(key); GetBlock<word32, LittleEndian> get1(key);
@ -692,8 +695,7 @@ Salsa20_OperateKeystream ENDP
void XSalsa20_Policy::CipherSetKey(const NameValuePairs &params, const byte *key, size_t length) void XSalsa20_Policy::CipherSetKey(const NameValuePairs &params, 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)) if (!(m_rounds == 8 || m_rounds == 12 || m_rounds == 20))
throw InvalidRounds(XSalsa20::StaticAlgorithmName(), m_rounds); throw InvalidRounds(XSalsa20::StaticAlgorithmName(), m_rounds);

View File

@ -36,6 +36,7 @@ struct Salsa20_Info : public VariableKeyLength<32, 16, 32, 16, SimpleKeyingInter
class CRYPTOPP_NO_VTABLE Salsa20_Policy : public AdditiveCipherConcretePolicy<word32, 16> class CRYPTOPP_NO_VTABLE Salsa20_Policy : public AdditiveCipherConcretePolicy<word32, 16>
{ {
protected: protected:
Salsa20_Policy() : m_rounds(ROUNDS) {}
void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length); void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length);
void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount); void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount);
void CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length); void CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length);
@ -49,6 +50,7 @@ protected:
std::string AlgorithmProvider() const; std::string AlgorithmProvider() const;
CRYPTOPP_CONSTANT(ROUNDS = 20) // Default rounds
FixedSizeAlignedSecBlock<word32, 16> m_state; FixedSizeAlignedSecBlock<word32, 16> m_state;
int m_rounds; int m_rounds;
}; };

68
sha3.h
View File

@ -27,27 +27,24 @@ NAMESPACE_BEGIN(CryptoPP)
class SHA3 : public HashTransformation class SHA3 : public HashTransformation
{ {
public: public:
/// \brief Construct a SHA3 /// \brief Construct a SHA3
/// \param digestSize the digest size, in bytes /// \param digestSize the digest size, in bytes
/// \details SHA3 is the base class for SHA3_224, SHA3_256, SHA3_384 and SHA3_512. /// \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 /// Library users should instantiate a derived class, and only use SHA3
/// as a base class reference or pointer. /// as a base class reference or pointer.
SHA3(unsigned int digestSize) : m_digestSize(digestSize) {Restart();} SHA3(unsigned int digestSize) : m_digestSize(digestSize) {Restart();}
unsigned int DigestSize() const {return m_digestSize;} unsigned int DigestSize() const {return m_digestSize;}
std::string AlgorithmName() const {return "SHA3-" + IntToString(m_digestSize*8);} unsigned int OptimalDataAlignment() const {return GetAlignmentOf<word64>();}
CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "SHA3"; }
unsigned int OptimalDataAlignment() const {return GetAlignmentOf<word64>();}
void Update(const byte *input, size_t length); void Update(const byte *input, size_t length);
void Restart(); void Restart();
void TruncatedFinal(byte *hash, size_t size); void TruncatedFinal(byte *hash, size_t size);
// unsigned int BlockSize() const { return r(); } // that's the idea behind it
protected: protected:
inline unsigned int r() const {return 200 - 2 * m_digestSize;} inline unsigned int r() const {return BlockSize();}
FixedSizeSecBlock<word64, 25> m_state; FixedSizeSecBlock<word64, 25> m_state;
unsigned int m_digestSize, m_counter; unsigned int m_digestSize, m_counter;
}; };
/// \brief SHA3 message digest template /// \brief SHA3 message digest template
@ -57,47 +54,36 @@ template<unsigned int T_DigestSize>
class SHA3_Final : public SHA3 class SHA3_Final : public SHA3
{ {
public: public:
CRYPTOPP_CONSTANT(DIGESTSIZE = T_DigestSize) CRYPTOPP_CONSTANT(DIGESTSIZE = T_DigestSize)
CRYPTOPP_CONSTANT(BLOCKSIZE = 200 - 2 * 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: private:
#if !defined(__BORLANDC__) #if !defined(__BORLANDC__)
CRYPTOPP_COMPILE_ASSERT(BLOCKSIZE < 200); // ensure there was no underflow in the math 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 > (int)T_DigestSize); // this is a general expectation by HMAC
#endif #endif
}; };
/// \brief SHA3-224 message digest /// \brief SHA3-224 message digest
/// \since Crypto++ 5.6.2 /// \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 /// \brief SHA3-256 message digest
/// \since Crypto++ 5.6.2 /// \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 /// \brief SHA3-384 message digest
/// \since Crypto++ 5.6.2 /// \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 /// \brief SHA3-512 message digest
/// \since Crypto++ 5.6.2 /// \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 NAMESPACE_END

67
shake.cpp Normal file
View File

@ -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

80
shake.h Normal file
View File

@ -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