diff options
author | weidai <weidai11@users.noreply.github.com> | 2002-10-04 17:31:41 +0000 |
---|---|---|
committer | weidai <weidai11@users.noreply.github.com> | 2002-10-04 17:31:41 +0000 |
commit | a3b6ece7ab341b5b14135baeccea7d5e4c086771 (patch) | |
tree | 8b045309c238226c32a563b1df6b9c30a2f0e0b3 /iterhash.cpp | |
download | cryptopp-git-a3b6ece7ab341b5b14135baeccea7d5e4c086771.tar.gz |
Initial revision
Diffstat (limited to 'iterhash.cpp')
-rw-r--r-- | iterhash.cpp | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/iterhash.cpp b/iterhash.cpp new file mode 100644 index 00000000..08f76261 --- /dev/null +++ b/iterhash.cpp @@ -0,0 +1,123 @@ +// iterhash.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "iterhash.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) + +template <class T, class BASE> +IteratedHashBase<T, BASE>::IteratedHashBase(unsigned int blockSize, unsigned int digestSize) + : m_data(blockSize/sizeof(T)), m_digest(digestSize/sizeof(T)) + , m_countHi(0), m_countLo(0) +{ +} + +template <class T, class BASE> void IteratedHashBase<T, BASE>::Update(const byte *input, unsigned int len) +{ + HashWordType tmp = m_countLo; + if ((m_countLo = tmp + len) < tmp) + m_countHi++; // Carry from low to high + m_countHi += SafeRightShift<8*sizeof(HashWordType)>(len); + + unsigned int blockSize = BlockSize(); + unsigned int num = (unsigned int)(tmp & (blockSize-1)); + + if (num != 0) + { + if ((num+len) >= blockSize) + { + memcpy((byte *)m_data.begin()+num, input, blockSize-num); + HashBlock(m_data); + input += (blockSize-num); + len-=(blockSize - num); + num=0; + // drop through and do the rest + } + else + { + memcpy((byte *)m_data.begin()+num, input, len); + return; + } + } + + // we now can process the input data in blocks of blockSize + // chars and save the leftovers to this->data. + if (len >= blockSize) + { + if (input == (byte *)m_data.begin()) + { + assert(len == blockSize); + HashBlock(m_data); + return; + } + else if (IsAligned<T>(input)) + { + unsigned int leftOver = HashMultipleBlocks((T *)input, len); + input += (len - leftOver); + len = leftOver; + } + else + do + { // copy input first if it's not aligned correctly + memcpy(m_data, input, blockSize); + HashBlock(m_data); + input+=blockSize; + len-=blockSize; + } while (len >= blockSize); + } + + memcpy(m_data, input, len); +} + +template <class T, class BASE> byte * IteratedHashBase<T, BASE>::CreateUpdateSpace(unsigned int &size) +{ + unsigned int blockSize = BlockSize(); + unsigned int num = ModPowerOf2(m_countLo, blockSize); + size = blockSize - num; + return (byte *)m_data.begin() + num; +} + +template <class T, class BASE> unsigned int IteratedHashBase<T, BASE>::HashMultipleBlocks(const T *input, unsigned int length) +{ + unsigned int blockSize = BlockSize(); + do + { + HashBlock(input); + input += blockSize/sizeof(T); + length -= blockSize; + } + while (length >= blockSize); + return length; +} + +template <class T, class BASE> void IteratedHashBase<T, BASE>::PadLastBlock(unsigned int lastBlockSize, byte padFirst) +{ + unsigned int blockSize = BlockSize(); + unsigned int num = ModPowerOf2(m_countLo, blockSize); + ((byte *)m_data.begin())[num++]=padFirst; + if (num <= lastBlockSize) + memset((byte *)m_data.begin()+num, 0, lastBlockSize-num); + else + { + memset((byte *)m_data.begin()+num, 0, blockSize-num); + HashBlock(m_data); + memset(m_data, 0, lastBlockSize); + } +} + +template <class T, class BASE> void IteratedHashBase<T, BASE>::Restart() +{ + m_countLo = m_countHi = 0; + Init(); +} + +#ifdef WORD64_AVAILABLE +template class IteratedHashBase<word64, HashTransformation>; +template class IteratedHashBase<word64, MessageAuthenticationCode>; +#endif + +template class IteratedHashBase<word32, HashTransformation>; +template class IteratedHashBase<word32, MessageAuthenticationCode>; + +NAMESPACE_END |