#ifndef CRYPTOPP_ITERHASH_H
#define CRYPTOPP_ITERHASH_H
#include "cryptopp.h"
#include "cryptopp_misc.h"
NAMESPACE_BEGIN(CryptoPP)
template <class T>
class IteratedHashBase : public HashModuleWithTruncation
{
public:
typedef T HashWordType;
IteratedHashBase(unsigned int blockSize, unsigned int digestSize);
unsigned int DigestSize() const {return digest.size * sizeof(T);};
void Update(const byte *input, unsigned int length);
protected:
virtual unsigned int HashMultipleBlocks(const T *input, unsigned int length);
void PadLastBlock(unsigned int lastBlockSize, byte padFirst=0x80);
void Reinit();
virtual void Init() =0;
virtual void HashBlock(const T *input) =0;
unsigned int blockSize;
word32 countLo, countHi; SecBlock<T> data; SecBlock<T> digest; };
template <class T, bool H, unsigned int S>
class IteratedHash : public IteratedHashBase<T>
{
public:
typedef T HashWordType;
enum {HIGHFIRST = H, BLOCKSIZE = S};
IteratedHash(unsigned int digestSize) : IteratedHashBase<T>(BLOCKSIZE, digestSize) {}
inline static void CorrectEndianess(HashWordType *out, const HashWordType *in, unsigned int byteCount)
{
if (!CheckEndianess(HIGHFIRST))
byteReverse(out, in, byteCount);
else if (in!=out)
memcpy(out, in, byteCount);
}
void TruncatedFinal(byte *hash, unsigned int size)
{
assert(size <= DigestSize());
PadLastBlock(BLOCKSIZE - 2*sizeof(HashWordType));
CorrectEndianess(data, data, BLOCKSIZE - 2*sizeof(HashWordType));
data[data.size-2] = HIGHFIRST ? countHi : countLo;
data[data.size-1] = HIGHFIRST ? countLo : countHi;
vTransform(data);
CorrectEndianess(digest, digest, DigestSize());
memcpy(hash, digest, size);
Reinit(); }
protected:
void HashBlock(const HashWordType *input)
{
if (CheckEndianess(HIGHFIRST))
vTransform(input);
else
{
byteReverse(data.ptr, input, (unsigned int)BLOCKSIZE);
vTransform(data);
}
}
virtual void vTransform(const HashWordType *data) =0;
};
NAMESPACE_END
#endif