32 changed files with 501 additions and 433 deletions
@ -1,36 +0,0 @@
|
||||
|
||||
#include "crypto/Hasher.hpp" |
||||
|
||||
void Hasher::init(Checksum::Type newType) { |
||||
|
||||
type = newType; |
||||
|
||||
switch(type) { |
||||
case Checksum::Adler32: adler32.init(); break; |
||||
case Checksum::Crc32: crc32.init(); break; |
||||
case Checksum::MD5: md5.init(); break; |
||||
case Checksum::Sha1: sha1.init(); break; |
||||
}; |
||||
} |
||||
|
||||
void Hasher::update(const char * data, size_t size) { |
||||
|
||||
switch(type) { |
||||
case Checksum::Adler32: adler32.update(data, size); break; |
||||
case Checksum::Crc32: crc32.update(data, size); break; |
||||
case Checksum::MD5: md5.update(data, size); break; |
||||
case Checksum::Sha1: sha1.update(data, size); break; |
||||
}; |
||||
} |
||||
|
||||
void Hasher::finalize(Checksum & result) { |
||||
|
||||
result.type = type; |
||||
|
||||
switch(type) { |
||||
case Checksum::Adler32: result.adler32 = adler32.finalize(); break; |
||||
case Checksum::Crc32: result.crc32 = crc32.finalize(); break; |
||||
case Checksum::MD5: md5.finalize(result.md5); break; |
||||
case Checksum::Sha1: sha1.finalize(result.sha1); break; |
||||
}; |
||||
} |
||||
@ -1,40 +0,0 @@
|
||||
|
||||
#ifndef INNOEXTRACT_CRYPTO_HASHER_HPP |
||||
#define INNOEXTRACT_CRYPTO_HASHER_HPP |
||||
|
||||
#include "crypto/Adler-32.hpp" |
||||
#include "crypto/Checksum.hpp" |
||||
#include "crypto/CRC32.hpp" |
||||
#include "crypto/MD5.hpp" |
||||
#include "crypto/SHA-1.hpp" |
||||
#include "util/enum.hpp" |
||||
|
||||
struct checksum_uninitialized_error { }; |
||||
|
||||
class Hasher : ChecksumBase<Hasher> { |
||||
|
||||
public: |
||||
|
||||
inline Hasher() { } |
||||
inline Hasher(Checksum::Type type) { init(type); } |
||||
|
||||
void init(Checksum::Type type); |
||||
|
||||
void update(const char * data, size_t size); |
||||
|
||||
void finalize(Checksum & result); |
||||
|
||||
private: |
||||
|
||||
Checksum::Type type; |
||||
|
||||
union { |
||||
Adler32 adler32; |
||||
Crc32 crc32; |
||||
Md5 md5; |
||||
Sha1 sha1; |
||||
}; |
||||
|
||||
}; |
||||
|
||||
#endif // INNOEXTRACT_CRYPTO_HASHER_HPP;
|
||||
@ -1,188 +0,0 @@
|
||||
|
||||
#ifndef INNOEXTRACT_CRYPTO_ITERATEDHASH_HPP |
||||
#define INNOEXTRACT_CRYPTO_ITERATEDHASH_HPP |
||||
|
||||
// Taken from Crypto++ and modified to fit the project.
|
||||
|
||||
#include <stdint.h> |
||||
#include <cstring> |
||||
#include "crypto/Checksum.hpp" |
||||
#include "util/endian.hpp" |
||||
#include "util/types.hpp" |
||||
#include "util/util.hpp" |
||||
|
||||
template <class T> |
||||
class IteratedHash : public ChecksumBase< IteratedHash<T> > { |
||||
|
||||
public: |
||||
|
||||
typedef T Transform; |
||||
typedef typename Transform::HashWord HashWord; |
||||
typedef typename Transform::ByteOrder ByteOrder; |
||||
static const size_t BlockSize = Transform::BlockSize; |
||||
static const size_t HashSize = Transform::HashSize; |
||||
|
||||
inline void init() { countLo = countHi = 0; Transform::init(state); } |
||||
|
||||
void update(const char * data, size_t length); |
||||
|
||||
void finalize(char * result); |
||||
|
||||
private: |
||||
|
||||
size_t hash(const HashWord * input, size_t length); |
||||
void pad(unsigned int lastBlockSize, uint8_t padFirst = 0x80); |
||||
|
||||
inline HashWord getBitCountHi() const { |
||||
return (countLo >> (8 * sizeof(HashWord) - 3)) + (countHi << 3); |
||||
} |
||||
inline HashWord getBitCountLo() const { return countLo << 3; } |
||||
|
||||
HashWord data[BlockSize / sizeof(HashWord)]; |
||||
HashWord state[HashSize / sizeof(HashWord)]; |
||||
|
||||
HashWord countLo, countHi; |
||||
|
||||
}; |
||||
|
||||
template <class T> |
||||
void IteratedHash<T>::update(const char * input, size_t len) { |
||||
|
||||
HashWord oldCountLo = countLo; |
||||
|
||||
if((countLo = oldCountLo + HashWord(len)) < oldCountLo) { |
||||
countHi++; // carry from low to high
|
||||
} |
||||
|
||||
countHi += HashWord(safe_right_shift<8 * sizeof(HashWord)>(len)); |
||||
|
||||
size_t num = mod_power_of_2(oldCountLo, size_t(BlockSize)); |
||||
uint8_t * d = reinterpret_cast<uint8_t *>(data); |
||||
|
||||
if(num != 0) { // process left over data
|
||||
if(num + len >= BlockSize) { |
||||
std::memcpy(d + num, input, BlockSize-num); |
||||
hash(data, BlockSize); |
||||
input += (BlockSize - num); |
||||
len -= (BlockSize - num); |
||||
num = 0; |
||||
// drop through and do the rest
|
||||
} else { |
||||
std::memcpy(d + num, input, len); |
||||
return; |
||||
} |
||||
} |
||||
|
||||
// now process the input data in blocks of BlockSize bytes and save the leftovers to m_data
|
||||
if(len >= BlockSize) { |
||||
|
||||
if(is_aligned<T>(input)) { |
||||
size_t leftOver = hash(reinterpret_cast<const HashWord *>(input), len); |
||||
input += (len - leftOver); |
||||
len = leftOver; |
||||
|
||||
} else { |
||||
do { // copy input first if it's not aligned correctly
|
||||
std::memcpy(d, input, BlockSize); |
||||
hash(data, BlockSize); |
||||
input += BlockSize; |
||||
len -= BlockSize; |
||||
} while(len >= BlockSize); |
||||
} |
||||
} |
||||
|
||||
if(len) { |
||||
memcpy(d, input, len); |
||||
} |
||||
} |
||||
|
||||
template <class T> |
||||
size_t IteratedHash<T>::hash(const HashWord * input, size_t length) { |
||||
|
||||
do { |
||||
|
||||
if(ByteOrder::native) { |
||||
Transform::transform(state, input); |
||||
} else { |
||||
byteswap(data, input, BlockSize); |
||||
Transform::transform(state, data); |
||||
} |
||||
|
||||
input += BlockSize / sizeof(HashWord); |
||||
length -= BlockSize; |
||||
|
||||
} while(length >= BlockSize); |
||||
|
||||
return length; |
||||
} |
||||
|
||||
template <class T> |
||||
void IteratedHash<T>::pad(unsigned int lastBlockSize, uint8_t padFirst) { |
||||
|
||||
size_t num = mod_power_of_2(countLo, size_t(BlockSize)); |
||||
|
||||
uint8_t * d = reinterpret_cast<uint8_t *>(data); |
||||
|
||||
d[num++] = padFirst; |
||||
|
||||
if(num <= lastBlockSize) { |
||||
memset(d + num, 0, lastBlockSize - num); |
||||
} else { |
||||
memset(d + num, 0, BlockSize - num); |
||||
hash(data, BlockSize); |
||||
memset(d, 0, lastBlockSize); |
||||
} |
||||
} |
||||
|
||||
template <class T> inline T rotlFixed(T x, unsigned int y) { |
||||
return T((x << y) | (x >> (sizeof(T) * 8 - y))); |
||||
} |
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1400 && !defined(__INTEL_COMPILER) |
||||
|
||||
template<> inline uint8_t rotlFixed<uint8_t>(uint8_t x, unsigned int y) { |
||||
return y ? _rotl8(x, y) : x; |
||||
} |
||||
|
||||
// Intel C++ Compiler 10.0 gives undefined externals with these
|
||||
template<> inline uint16_t rotlFixed<uint16_t>(uint16_t x, unsigned int y) { |
||||
return y ? _rotl16(x, y) : x; |
||||
} |
||||
|
||||
#endif |
||||
|
||||
#ifdef _MSC_VER |
||||
template<> inline uint32_t rotlFixed<uint32_t>(uint32_t x, unsigned int y) { |
||||
return y ? _lrotl(x, y) : x; |
||||
} |
||||
#endif |
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1300 && !defined(__INTEL_COMPILER) |
||||
// Intel C++ Compiler 10.0 calls a function instead of using the rotate instruction when
|
||||
// using these instructions
|
||||
template<> inline uint64_t rotlFixed<uint64_t>(uint64_t x, unsigned int y) { |
||||
return y ? _rotl64(x, y) : x; |
||||
} |
||||
#endif |
||||
|
||||
template <class T> |
||||
void IteratedHash<T>::finalize(char * digest) { |
||||
|
||||
size_t order = ByteOrder::offset; |
||||
|
||||
pad(BlockSize - 2 * sizeof(HashWord)); |
||||
data[BlockSize / sizeof(HashWord) - 2 + order] = ByteOrder::byteswap_if_alien(getBitCountLo()); |
||||
data[BlockSize / sizeof(HashWord) - 1 - order] = ByteOrder::byteswap_if_alien(getBitCountHi()); |
||||
|
||||
hash(data, BlockSize); |
||||
|
||||
if(is_aligned<HashWord>(digest) && HashSize % sizeof(HashWord) == 0) { |
||||
ByteOrder::byteswap_if_alien(state, reinterpret_cast<HashWord *>(digest), HashSize); |
||||
} else { |
||||
ByteOrder::byteswap_if_alien(state, state, HashSize); |
||||
memcpy(digest, state, HashSize); |
||||
} |
||||
|
||||
} |
||||
|
||||
#endif // INNOEXTRACT_CRYPTO_ITERATEDHASH_HPP
|
||||
@ -1,24 +0,0 @@
|
||||
|
||||
#ifndef INNOEXTRACT_CRYPTO_MD5_HPP |
||||
#define INNOEXTRACT_CRYPTO_MD5_HPP |
||||
|
||||
#include <stdint.h> |
||||
#include "crypto/IteratedHash.hpp" |
||||
|
||||
class Md5Transform { |
||||
|
||||
public: |
||||
|
||||
typedef uint32_t HashWord; |
||||
typedef little_endian ByteOrder; |
||||
static const size_t BlockSize = 64; |
||||
static const size_t HashSize = 16; |
||||
|
||||
static void init(HashWord * state); |
||||
|
||||
static void transform(HashWord * digest, const HashWord * data); |
||||
}; |
||||
|
||||
typedef IteratedHash<Md5Transform> Md5; |
||||
|
||||
#endif // INNOEXTRACT_CRYPTO_MD5_HPP
|
||||
@ -1,24 +0,0 @@
|
||||
|
||||
#ifndef INNOEXTRACT_CRYPTO_SHA1_HPP |
||||
#define INNOEXTRACT_CRYPTO_SHA1_HPP |
||||
|
||||
#include <stdint.h> |
||||
#include "crypto/IteratedHash.hpp" |
||||
|
||||
class Sha1Transform { |
||||
|
||||
public: |
||||
|
||||
typedef uint32_t HashWord; |
||||
typedef big_endian ByteOrder; |
||||
static const size_t BlockSize = 64; |
||||
static const size_t HashSize = 20; |
||||
|
||||
static void init(HashWord * state); |
||||
|
||||
static void transform(HashWord * digest, const HashWord * data); |
||||
}; |
||||
|
||||
typedef IteratedHash<Sha1Transform> Sha1; |
||||
|
||||
#endif // INNOEXTRACT_CRYPTO_SHA1_HPP
|
||||
@ -0,0 +1,44 @@
|
||||
|
||||
#include "crypto/hasher.hpp" |
||||
|
||||
namespace crypto { |
||||
|
||||
void hasher::init(checksum_type newType) { |
||||
|
||||
type = newType; |
||||
|
||||
switch(type) { |
||||
case crypto::Adler32: adler32.init(); break; |
||||
case crypto::CRC32: crc32.init(); break; |
||||
case crypto::MD5: md5.init(); break; |
||||
case crypto::SHA1: sha1.init(); break; |
||||
}; |
||||
} |
||||
|
||||
void hasher::update(const char * data, size_t size) { |
||||
|
||||
switch(type) { |
||||
case crypto::Adler32: adler32.update(data, size); break; |
||||
case crypto::CRC32: crc32.update(data, size); break; |
||||
case crypto::MD5: md5.update(data, size); break; |
||||
case crypto::SHA1: sha1.update(data, size); break; |
||||
}; |
||||
} |
||||
|
||||
checksum hasher::finalize() { |
||||
|
||||
checksum result; |
||||
|
||||
result.type = type; |
||||
|
||||
switch(type) { |
||||
case crypto::Adler32: result.adler32 = adler32.finalize(); break; |
||||
case crypto::CRC32: result.crc32 = crc32.finalize(); break; |
||||
case crypto::MD5: md5.finalize(result.md5); break; |
||||
case crypto::SHA1: sha1.finalize(result.sha1); break; |
||||
}; |
||||
|
||||
return result; |
||||
} |
||||
|
||||
} // namespace crypto
|
||||
@ -0,0 +1,44 @@
|
||||
|
||||
#ifndef INNOEXTRACT_CRYPTO_HASHER_HPP |
||||
#define INNOEXTRACT_CRYPTO_HASHER_HPP |
||||
|
||||
#include "crypto/adler32.hpp" |
||||
#include "crypto/checksum.hpp" |
||||
#include "crypto/crc32.hpp" |
||||
#include "crypto/md5.hpp" |
||||
#include "crypto/sha1.hpp" |
||||
#include "util/enum.hpp" |
||||
|
||||
struct checksum_uninitialized_error { }; |
||||
|
||||
namespace crypto { |
||||
|
||||
class hasher : checksum_base<hasher> { |
||||
|
||||
public: |
||||
|
||||
inline hasher() { } |
||||
inline hasher(checksum_type type) { init(type); } |
||||
|
||||
void init(checksum_type type); |
||||
|
||||
void update(const char * data, size_t size); |
||||
|
||||
checksum finalize(); |
||||
|
||||
private: |
||||
|
||||
checksum_type type; |
||||
|
||||
union { |
||||
crypto::adler32 adler32; |
||||
crypto::crc32 crc32; |
||||
crypto::md5 md5; |
||||
crypto::sha1 sha1; |
||||
}; |
||||
|
||||
}; |
||||
|
||||
} // namespace crypto
|
||||
|
||||
#endif // INNOEXTRACT_CRYPTO_HASHER_HPP;
|
||||
@ -0,0 +1,161 @@
|
||||
|
||||
#ifndef INNOEXTRACT_CRYPTO_ITERATEDHASH_HPP |
||||
#define INNOEXTRACT_CRYPTO_ITERATEDHASH_HPP |
||||
|
||||
// Taken from Crypto++ and modified to fit the project.
|
||||
|
||||
#include <stdint.h> |
||||
#include <cstring> |
||||
#include "crypto/checksum.hpp" |
||||
#include "util/endian.hpp" |
||||
#include "util/types.hpp" |
||||
#include "util/util.hpp" |
||||
|
||||
namespace crypto { |
||||
|
||||
template <class T> |
||||
class iterated_hash : public checksum_base< iterated_hash<T> > { |
||||
|
||||
public: |
||||
|
||||
typedef T transform; |
||||
typedef typename transform::hash_word hash_word; |
||||
typedef typename transform::byte_order byte_order; |
||||
static const size_t block_size = transform::block_size; |
||||
static const size_t hash_size = transform::hash_size; |
||||
|
||||
inline void init() { count_lo = count_hi = 0; transform::init(state); } |
||||
|
||||
void update(const char * data, size_t length); |
||||
|
||||
void finalize(char * result); |
||||
|
||||
private: |
||||
|
||||
size_t hash(const hash_word * input, size_t length); |
||||
void pad(unsigned int last_block_size, uint8_t pad_first = 0x80); |
||||
|
||||
inline hash_word bit_count_hi() const { |
||||
return (count_lo >> (8 * sizeof(hash_word) - 3)) + (count_hi << 3); |
||||
} |
||||
inline hash_word bit_count_lo() const { return count_lo << 3; } |
||||
|
||||
hash_word data[block_size / sizeof(hash_word)]; |
||||
hash_word state[hash_size / sizeof(hash_word)]; |
||||
|
||||
hash_word count_lo, count_hi; |
||||
|
||||
}; |
||||
|
||||
template <class T> |
||||
void iterated_hash<T>::update(const char * input, size_t len) { |
||||
|
||||
hash_word old_count_lo = count_lo; |
||||
|
||||
if((count_lo = old_count_lo + hash_word(len)) < old_count_lo) { |
||||
count_hi++; // carry from low to high
|
||||
} |
||||
|
||||
count_hi += hash_word(safe_right_shift<8 * sizeof(hash_word)>(len)); |
||||
|
||||
size_t num = mod_power_of_2(old_count_lo, size_t(block_size)); |
||||
uint8_t * d = reinterpret_cast<uint8_t *>(data); |
||||
|
||||
if(num != 0) { // process left over data
|
||||
if(num + len >= block_size) { |
||||
std::memcpy(d + num, input, block_size-num); |
||||
hash(data, block_size); |
||||
input += (block_size - num); |
||||
len -= (block_size - num); |
||||
num = 0; |
||||
// drop through and do the rest
|
||||
} else { |
||||
std::memcpy(d + num, input, len); |
||||
return; |
||||
} |
||||
} |
||||
|
||||
// now process the input data in blocks of BlockSize bytes and save the leftovers to m_data
|
||||
if(len >= block_size) { |
||||
|
||||
if(is_aligned<T>(input)) { |
||||
size_t leftOver = hash(reinterpret_cast<const hash_word *>(input), len); |
||||
input += (len - leftOver); |
||||
len = leftOver; |
||||
|
||||
} else { |
||||
do { // copy input first if it's not aligned correctly
|
||||
std::memcpy(d, input, block_size); |
||||
hash(data, block_size); |
||||
input += block_size; |
||||
len -= block_size; |
||||
} while(len >= block_size); |
||||
} |
||||
} |
||||
|
||||
if(len) { |
||||
memcpy(d, input, len); |
||||
} |
||||
} |
||||
|
||||
template <class T> |
||||
size_t iterated_hash<T>::hash(const hash_word * input, size_t length) { |
||||
|
||||
do { |
||||
|
||||
if(byte_order::native) { |
||||
transform::transform(state, input); |
||||
} else { |
||||
byteswap(data, input, block_size); |
||||
transform::transform(state, data); |
||||
} |
||||
|
||||
input += block_size / sizeof(hash_word); |
||||
length -= block_size; |
||||
|
||||
} while(length >= block_size); |
||||
|
||||
return length; |
||||
} |
||||
|
||||
template <class T> |
||||
void iterated_hash<T>::pad(unsigned int last_block_size, uint8_t pad_first) { |
||||
|
||||
size_t num = mod_power_of_2(count_lo, size_t(block_size)); |
||||
|
||||
uint8_t * d = reinterpret_cast<uint8_t *>(data); |
||||
|
||||
d[num++] = pad_first; |
||||
|
||||
if(num <= last_block_size) { |
||||
memset(d + num, 0, last_block_size - num); |
||||
} else { |
||||
memset(d + num, 0, block_size - num); |
||||
hash(data, block_size); |
||||
memset(d, 0, last_block_size); |
||||
} |
||||
} |
||||
|
||||
template <class T> |
||||
void iterated_hash<T>::finalize(char * digest) { |
||||
|
||||
size_t order = byte_order::offset; |
||||
|
||||
pad(block_size - 2 * sizeof(hash_word)); |
||||
data[block_size / sizeof(hash_word) - 2 + order] = byte_order::byteswap_if_alien(bit_count_lo()); |
||||
data[block_size / sizeof(hash_word) - 1 - order] = byte_order::byteswap_if_alien(bit_count_hi()); |
||||
|
||||
hash(data, block_size); |
||||
|
||||
if(is_aligned<hash_word>(digest) && hash_size % sizeof(hash_word) == 0) { |
||||
byte_order::byteswap_if_alien(state, reinterpret_cast<hash_word *>(digest), hash_size); |
||||
} else { |
||||
byte_order::byteswap_if_alien(state, state, hash_size); |
||||
memcpy(digest, state, hash_size); |
||||
} |
||||
|
||||
} |
||||
|
||||
} // namespace crypto
|
||||
|
||||
#endif // INNOEXTRACT_CRYPTO_ITERATEDHASH_HPP
|
||||
@ -0,0 +1,30 @@
|
||||
|
||||
#ifndef INNOEXTRACT_CRYPTO_MD5_HPP |
||||
#define INNOEXTRACT_CRYPTO_MD5_HPP |
||||
|
||||
#include <stdint.h> |
||||
|
||||
#include "crypto/iteratedhash.hpp" |
||||
#include "util/endian.hpp" |
||||
|
||||
namespace crypto { |
||||
|
||||
class md5_transform { |
||||
|
||||
public: |
||||
|
||||
typedef uint32_t hash_word; |
||||
typedef little_endian byte_order; |
||||
static const size_t block_size = 64; |
||||
static const size_t hash_size = 16; |
||||
|
||||
static void init(hash_word * state); |
||||
|
||||
static void transform(hash_word * digest, const hash_word * data); |
||||
}; |
||||
|
||||
typedef iterated_hash<md5_transform> md5; |
||||
|
||||
} // namespace crypto
|
||||
|
||||
#endif // INNOEXTRACT_CRYPTO_MD5_HPP
|
||||
@ -0,0 +1,30 @@
|
||||
|
||||
#ifndef INNOEXTRACT_CRYPTO_SHA1_HPP |
||||
#define INNOEXTRACT_CRYPTO_SHA1_HPP |
||||
|
||||
#include <stdint.h> |
||||
|
||||
#include "crypto/iteratedhash.hpp" |
||||
#include "util/endian.hpp" |
||||
|
||||
namespace crypto { |
||||
|
||||
class sha1_transform { |
||||
|
||||
public: |
||||
|
||||
typedef uint32_t hash_word; |
||||
typedef big_endian byte_order; |
||||
static const size_t block_size = 64; |
||||
static const size_t hash_size = 20; |
||||
|
||||
static void init(hash_word * state); |
||||
|
||||
static void transform(hash_word * digest, const hash_word * data); |
||||
}; |
||||
|
||||
typedef iterated_hash<sha1_transform> sha1; |
||||
|
||||
} // namespace crypto
|
||||
|
||||
#endif // INNOEXTRACT_CRYPTO_SHA1_HPP
|
||||
Loading…
Reference in new issue