added codes of Hash

This commit is contained in:
hyzboy 2021-06-08 20:11:25 +08:00
parent af510a6cfc
commit 863293fbc8
12 changed files with 2090 additions and 0 deletions

317
inc/hgl/util/hash/Hash.h Normal file
View File

@ -0,0 +1,317 @@
#ifndef HGL_UTIL_HASH_INCLUDE
#define HGL_UTIL_HASH_INCLUDE
#include<hgl/type/String.h>
namespace hgl
{
namespace util
{
/**
* Hash算法枚举
*/
enum class HASH ///Hash算法枚举
{
Adler32, ///<一种较CRC32更为安全的快速HASH算法
CRC32, ///<最快速的HASH算法但最不安全仅用于低安全性的简单验证
MD4, ///<较MD5在安全性下稍弱。但仍未被攻破且较MD5更快
MD5, ///<最常用的HASH算法
SHA1, ///<较MD5更为安全但计算较慢
SHA1LE, ///<SHA1改版
SHA256,
SHA512,
ENUM_CLASS_RANGE(Adler32,SHA512)
};//enum HASH
/**
* Hash编码结构模板
*/
template<int SIZE> struct HashCode
{
unsigned char code[SIZE];
public:
template<typename T>
using CharArray=T[(SIZE<<1)+1];
public:
HashCode()
{
hgl_zero(code);
}
static constexpr int size(){return SIZE;}
const unsigned char operator[](int index)const
{
return code[index];
}
void CopyFrom(const void *ptr)
{
memcpy(code,ptr,SIZE);
}
void FromString(const char *str)
{
ParseHexStr(code,str,SIZE);
}
template<typename T>
void ToUpperString(T *str,const T gap_char=0) const
{
ToUpperHexStr<T>(str,code,SIZE,gap_char);
}
template<typename T>
void ToLowerString(T *str,const T gap_char=0) const
{
ToLowerHexStr<T>(str,code,SIZE,gap_char);
}
const int CompFunc(const HashCode<SIZE> &hash)const
{
const unsigned char *s=code;
const unsigned char *t=hash.code;
for(int i=0;i<SIZE;i++)
{
if(*s!=*t)
return(*s-*t);
s++;
t++;
}
return(0);
}
CompOperator(const HashCode<SIZE> &,CompFunc)
};//template<int SIZE> struct HashCode
using HashCodeCRC32 =HashCode<4> ;
using HashCodeAdler32 =HashCode<4> ;
using HashCodeMD5 =HashCode<16> ;
using HashCodeMD4 =HashCode<16> ;
using HashCodeSHA1 =HashCode<20> ;
using HashCodeSHA1LE =HashCode<20> ;
using HashCodeSHA256 =HashCode<32> ;
using HashCodeSHA512 =HashCode<64> ;
const int hash_code_bytes[]={4,4,16,16,20,20,32,64}; //hash码长度
/**
*
*/
class Hash ///散列值计算功能基类
{
public:
virtual ~Hash()=default;
virtual void GetName(UTF8String &)const=0; ///<取得HASH算法的名称
virtual void GetName(UTF16String &)const=0; ///<取得HASH算法的名称
virtual const int GetHashBytes()const=0; ///<取得HASH码字节长度(MD4/MD5为16,SHA1为20)
virtual void Init()=0; ///<初始化散列值计算
virtual void Update(const void *,uint)=0; ///<提交新的数据
virtual void Final(void *)=0; ///<结束并取得结果
};//class Hash
template<HASH ha> Hash *CreateHash(); ///<创建一个hash值计算类实例
#define HGL_CREATE_HASH_FUNC(name) Hash *Create##name##Hash(); \
template<> inline Hash *CreateHash<HASH::name>(){return Create##name##Hash();}
HGL_CREATE_HASH_FUNC(Adler32)
HGL_CREATE_HASH_FUNC(CRC32)
HGL_CREATE_HASH_FUNC(MD4)
HGL_CREATE_HASH_FUNC(MD5)
HGL_CREATE_HASH_FUNC(SHA1)
HGL_CREATE_HASH_FUNC(SHA1LE)
HGL_CREATE_HASH_FUNC(SHA256)
HGL_CREATE_HASH_FUNC(SHA512)
#undef HGL_CREATE_HASH_FUNC
inline Hash *CreateHash(HASH ha)
{
ENUM_CLASS_RANGE_ERROR_RETURN_NULLPTR(HASH,ha)
using CreateHashFunc=Hash *(*)();
const CreateHashFunc func[(size_t)HASH::RANGE_SIZE]=
{
CreateAdler32Hash,
CreateCRC32Hash,
CreateMD4Hash,
CreateMD5Hash,
CreateSHA1Hash,
CreateSHA1LEHash,
CreateSHA256Hash,
CreateSHA512Hash
};
return func[(size_t)ha]();
}
/**
* Hash值
* @param data
* @param size
* @param ha hash算法
* @param hash_code hash值存放处
* @return
*/
template<HASH ha> bool CountHash(const void *data,int size,void *hash_code)
{
if(!data||size<=0||!hash_code)return(false);
Hash *h=CreateHash<ha>();
if(!h)return(false);
h->Init();
h->Update(data,size);
h->Final(hash_code);
delete h;
return(true);
}
/**
* Hash值
* @param data
* @param size
* @param ha hash算法
* @param hash_code hash值存放处
* @return
*/
inline bool CountHash(const void *data,int size,HASH ha,void *hash_code)
{
ENUM_CLASS_RANGE_ERROR_RETURN_FALSE(HASH,ha)
if(!data||size<=0||!hash_code)return(false);
using CountHashFunc=bool (*)(const void *,int size,void *);
const CountHashFunc func[(size_t)HASH::RANGE_SIZE]=
{
CountHash<HASH::Adler32 >,
CountHash<HASH::CRC32 >,
CountHash<HASH::MD4 >,
CountHash<HASH::MD5 >,
CountHash<HASH::SHA1 >,
CountHash<HASH::SHA1LE >,
CountHash<HASH::SHA256 >,
CountHash<HASH::SHA512 >
};
return func[(size_t)ha](data,size,hash_code);
}
/**
* Hash值
* @param data
* @param size
* @param ha hash算法
* @param hash_str hash值存放处
* @param litter
* @return
*/
template<HASH ha> bool CountHashStr(const void *data,int size,UTF8String &hash_str,bool litter=true)
{
if(!data||size<=0)return(false);
Hash *h=CreateHash<ha>();
if(!h)return(false);
const int hash_bytes=hash_code_bytes[(size_t)ha];
uint8 *hash_code=new uint8[hash_bytes];
char *hash_code_str=new char[1+(hash_bytes<<1)];
h->Init();
h->Update(data,size);
h->Final(hash_code);
delete h;
DataToHexStr(hash_code_str,hash_code,hash_bytes,litter?LowerHexChar:UpperHexChar);
hash_str.SetInstance(hash_code_str,hash_bytes<<1);
delete[] hash_code;
return(true);
}
/**
* Hash值
* @param data
* @param size
* @param ha hash算法
* @param hash_str hash值存放处
* @param litter
* @return
*/
inline bool CountHash(const void *data,int size,HASH ha,UTF8String &hash_str,bool litter=true)
{
ENUM_CLASS_RANGE_ERROR_RETURN_FALSE(HASH,ha)
if(!data||size<=0)return(false);
using CountHashFunc=bool (*)(const void *,int size,UTF8String &,bool);
const CountHashFunc func[(size_t)HASH::RANGE_SIZE]=
{
CountHashStr<HASH::Adler32 >,
CountHashStr<HASH::CRC32 >,
CountHashStr<HASH::MD4 >,
CountHashStr<HASH::MD5 >,
CountHashStr<HASH::SHA1 >,
CountHashStr<HASH::SHA1LE >,
CountHashStr<HASH::SHA256 >,
CountHashStr<HASH::SHA512 >
};
return func[(size_t)ha](data,size,hash_str,litter);
}
#define HGL_COUNT_HASH_FUNC(name) inline bool Count##name(const void *data, int size, HashCode##name &hc) { return CountHash<HASH::name>(data, size, &hc); } \
inline bool Count##name(const void *data, int size, UTF8String &hash_str, bool litter = true) { return CountHashStr<HASH::name>(data, size, hash_str, litter); } \
inline bool Count##name(const UTF8String &str, UTF8String &hash_str, bool litter = true) { return CountHashStr<HASH::name>(str.c_str(), str.Length(), hash_str, litter); }
HGL_COUNT_HASH_FUNC(Adler32)
HGL_COUNT_HASH_FUNC(CRC32)
HGL_COUNT_HASH_FUNC(MD4)
HGL_COUNT_HASH_FUNC(MD5)
HGL_COUNT_HASH_FUNC(SHA1)
HGL_COUNT_HASH_FUNC(SHA1LE)
HGL_COUNT_HASH_FUNC(SHA256)
HGL_COUNT_HASH_FUNC(SHA512)
#undef HGL_COUNT_HASH_FUNC
/**
* hash值
* @param filename
* @param ha hash算法
* @param hash_code hash存放处
* @return
*/
bool GetFileHash(const OSString &filename,HASH ha,void *hash_code);
/**
* hash值
* @param filename
* @param ha hash算法
* @param hash_str hash值存放处
* @param litter
* @return
*/
bool GetFileHash(const OSString &filename,HASH ha,UTF8String &hash_str,bool litter=true);
}//namespace util
}//namespace hgl
#endif//HGL_UTIL_HASH_INCLUDE

View File

@ -0,0 +1,55 @@
#ifndef HGL_ALGORITHM_HASH_SHA1LE_INCLUDE
#define HGL_ALGORITHM_HASH_SHA1LE_INCLUDE
#include<hgl/util/hash/Hash.h>
namespace hgl
{
namespace util
{
/**
* SHA1-LE Hash算法<br>
* SHA1不变:<br>
* 1.BigEndian设计造成的LittleEndian处理器需要做大小头转换的部分
* 2.
* 3.
*/
class SHA1LE:public Hash
{
enum
{
BLOCK_SIZE = 64,
DIGEST_SIZE = 20
};
uint32 digest[5]; // Message digest
uint32 countLo; // 64-bit bit count
uint32 countHi;
uint32 data[16]; // SHA data buffer
uint32 slop; // # of bytes saved in data[]
uint32 K[4];
uint32 W[80];
private:
void sha1_transform();
public:
void GetName(UTF8String &str)const override{str="SHA1LE";}
void GetName(UTF16String &str)const override{str=U16_TEXT("SHA1LE");}
const int GetHashBytes()const override {return DIGEST_SIZE;}
void Init(const uint32 *start_digest,const uint32 *mysterious_constants); ///<开始一次新的HASH计算并指定初始因子和扰乱因子
void Init()override; ///<开始一次新的HASH计算并使用缺省初始因子和扰乱因子
void SetMark(const uint32 *mysterious_constants); ///<更新扰乱因子
void Update(const void *input,uint count)override; ///<添加新的HASH数据
void Final(void *result)override; ///<结束本次HASH计算
};//class SHA1LE
}//namespace util
}//namespace hgl
#endif//HGL_ALGORITHM_HASH_SHA1LE_INCLUDE

View File

@ -78,9 +78,32 @@ SET(CMD_SOURCE ${CMUTIL_ROOT_INCLUDE_PATH}/hgl/util/cmd/CmdParse.h
SOURCE_GROUP("Command Line" FILES ${CMD_SOURCE}) SOURCE_GROUP("Command Line" FILES ${CMD_SOURCE})
#SOURCE_GROUP("Time" FILES ${TIME_SOURCE}) #SOURCE_GROUP("Time" FILES ${TIME_SOURCE})
option(CM_UTIL_SUPPORT_HASH "Build HASH module" ON)
IF(CM_UTIL_SUPPORT_HASH)
SET(HASH_HEADER_FILES ${CMUTIL_ROOT_INCLUDE_PATH}/hgl/util/hash/Hash.h
${CMUTIL_ROOT_INCLUDE_PATH}/hgl/util/hash/SHA1LE.h)
SET(HASH_SOURCE_FILES hash/adler32.cpp
hash/crc32.cpp
hash/Hash.cpp
hash/md4.cpp
hash/md5.cpp
hash/sha1.cpp
hash/sha1le.cpp
hash/sha256.cpp
hash/sha512.cpp)
SOURCE_GROUP("HASH" FILES ${HASH_HEADER_FILES} ${HASH_SOURCE_FILES})
ENDIF(CM_UTIL_SUPPORT_HASH)
add_cm_library(CMUtil "CM" ${CMD_SOURCE} add_cm_library(CMUtil "CM" ${CMD_SOURCE}
# ${TIME_SOURCE} # ${TIME_SOURCE}
${XML_PARSE_SOURCE} ${XML_PARSE_SOURCE}
${JSON_TOOL_SOURCE} ${JSON_TOOL_SOURCE}
${HASH_HEADER_FILES}
${HASH_SOURCE_FILES}
) )

43
src/hash/Hash.cpp Normal file
View File

@ -0,0 +1,43 @@
#include<hgl/util/hash/Hash.h>
#include<hgl/io/FileInputStream.h>
namespace hgl
{
namespace util
{
bool GetFileHash(const OSString &filename,HASH ha,void *hash_code)
{
Hash *hash=CreateHash(ha);
if(!hash)return(false);
io::FileInputStream fp;
if(fp.Open(filename)==false)
return(false);
int filesize=fp.GetSize();
int pos=0,size;
uint8 data[HGL_SIZE_1MB];
hash->Init();
while(pos<filesize)
{
size=HGL_SIZE_1MB;
if(pos+size>filesize)size=filesize-pos;
fp.Read(data,size);
hash->Update(data,size);
pos+=size;
}
hash->Final(hash_code);
fp.Close();
delete hash;
return(true);
}
}//namespace util
}//namespace hgl

150
src/hash/adler32.cpp Normal file
View File

@ -0,0 +1,150 @@
#include<hgl/util/hash/Hash.h>
namespace hgl
{
namespace
{
#define BASE 65521UL /* largest prime smaller than 65536 */
#define NMAX 5552
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
#define DO16(buf) DO8(buf,0); DO8(buf,8);
/* use NO_DIVIDE if your processor does not do division in hardware */
#define NO_DIVIDE //不使用除法
#ifdef NO_DIVIDE
# define MOD(a) \
do { \
if (a >= (BASE << 16)) a -= (BASE << 16); \
if (a >= (BASE << 15)) a -= (BASE << 15); \
if (a >= (BASE << 14)) a -= (BASE << 14); \
if (a >= (BASE << 13)) a -= (BASE << 13); \
if (a >= (BASE << 12)) a -= (BASE << 12); \
if (a >= (BASE << 11)) a -= (BASE << 11); \
if (a >= (BASE << 10)) a -= (BASE << 10); \
if (a >= (BASE << 9)) a -= (BASE << 9); \
if (a >= (BASE << 8)) a -= (BASE << 8); \
if (a >= (BASE << 7)) a -= (BASE << 7); \
if (a >= (BASE << 6)) a -= (BASE << 6); \
if (a >= (BASE << 5)) a -= (BASE << 5); \
if (a >= (BASE << 4)) a -= (BASE << 4); \
if (a >= (BASE << 3)) a -= (BASE << 3); \
if (a >= (BASE << 2)) a -= (BASE << 2); \
if (a >= (BASE << 1)) a -= (BASE << 1); \
if (a >= BASE) a -= BASE; \
} while (0)
# define MOD4(a) \
do { \
if (a >= (BASE << 4)) a -= (BASE << 4); \
if (a >= (BASE << 3)) a -= (BASE << 3); \
if (a >= (BASE << 2)) a -= (BASE << 2); \
if (a >= (BASE << 1)) a -= (BASE << 1); \
if (a >= BASE) a -= BASE; \
} while (0)
#else
# define MOD(a) a %= BASE
# define MOD4(a) a %= BASE
#endif
}//namespace
namespace util
{
/**
* Adler32校检码计算
* @param adler
* @param buf
* @param len
* @return
*/
uint32 CountAdler32(uint32 adler,const uint8 *buf,uint32 len)
{
uint32 sum2;
uint32 n;
/* split Adler-32 into component sums */
sum2 = (adler >> 16) & 0xffff;
adler &= 0xffff;
/* in case user likes doing a byte at a time, keep it fast */
if (len == 1) {
adler += buf[0];
if (adler >= BASE)
adler -= BASE;
sum2 += adler;
if (sum2 >= BASE)
sum2 -= BASE;
return adler | (sum2 << 16);
}
/* initial Adler-32 value (deferred check for len == 1 speed) */
if (buf == 0)
return 1L;
/* in case short lengths are provided, keep it somewhat fast */
if (len < 16) {
while (len--) {
adler += *buf++;
sum2 += adler;
}
if (adler >= BASE)
adler -= BASE;
MOD4(sum2); /* only added so many BASE's */
return adler | (sum2 << 16);
}
/* do length NMAX blocks -- requires just one modulo operation */
while (len >= NMAX) {
len -= NMAX;
n = NMAX / 16; /* NMAX is divisible by 16 */
do {
DO16(buf); /* 16 sums unrolled */
buf += 16;
} while (--n);
MOD(adler);
MOD(sum2);
}
/* do remaining bytes (less than NMAX, still just one modulo) */
if (len) { /* avoid modulos if none remaining */
while (len >= 16) {
len -= 16;
DO16(buf);
buf += 16;
}
while (len--) {
adler += *buf++;
sum2 += adler;
}
MOD(adler);
MOD(sum2);
}
/* return recombined sums */
return adler | (sum2 << 16);
}
class Adler32:public Hash
{
uint32 result;
public:
void GetName(UTF8String &str)const override{str=U8_TEXT("Adler32");}
void GetName(UTF16String &str)const override{str=U16_TEXT("Adler32");}
const int GetHashBytes()const override{return 4;}
void Init()override
{
result=0;
}
void Update(const void *input,uint inputLen)override
{
result=CountAdler32(result,(const uint8 *)input,inputLen);
}
void Final(void *digest)override
{
*(uint32 *)digest=result;
}
};//class Adler32
Hash *CreateAdler32Hash(){return(new Adler32);}
}//namespace util
}//namespace hgl

98
src/hash/crc32.cpp Normal file
View File

@ -0,0 +1,98 @@
#include<hgl/util/hash/Hash.h>
namespace hgl
{
namespace
{
const uint32 crc32_tab[] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
}//namespace
namespace util
{
uint32 CountCRC32(uint32 crc, const uint8 *buf, uint32 size)
{
const uint8 *p;
p = buf;
crc = crc ^ ~0U;
while (size--)
crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
return crc ^ ~0U;
}
class CRC32:public Hash
{
uint32 result;
public:
void GetName(UTF8String &str)const override{str=U8_TEXT("CRC32");}
void GetName(UTF16String &str)const override{str=U16_TEXT("CRC32");}
const int GetHashBytes()const override{return 4;}
void Init()override
{
result=0;
}
void Update(const void *input,uint inputLen)override
{
result=CountCRC32(result,(const uint8 *)input,inputLen);
}
void Final(void *digest)override
{
*(uint32 *)digest=result;
}
};//class CRC32
Hash *CreateCRC32Hash(){return(new CRC32);}
}//namespace util
}//namepace hgl

227
src/hash/md4.cpp Normal file
View File

@ -0,0 +1,227 @@
#include<hgl/util/hash/Hash.h>
#include<hgl/type/DataType.h>
namespace hgl
{
namespace util
{
namespace
{
/* Constants for MD4Transform routine. */
#define S11 3
#define S12 7
#define S13 11
#define S14 19
#define S21 3
#define S22 5
#define S23 9
#define S24 13
#define S31 3
#define S32 9
#define S33 11
#define S34 15
/* F, G and H are basic MD4 functions. */
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
/* ROTATE_LEFT rotates x left n bits. */
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/* FF, GG and HH are transformations for rounds 1, 2 and 3 */
/* Rotation is separate from addition to prevent recomputation */
#define FF(a, b, c, d, x, s) { \
(a) += F ((b), (c), (d)) + (x); \
(a) = ROTATE_LEFT ((a), (s)); \
}
#define GG(a, b, c, d, x, s) { \
(a) += G ((b), (c), (d)) + (x) + (uint32)0x5a827999; \
(a) = ROTATE_LEFT ((a), (s)); \
}
#define HH(a, b, c, d, x, s) { \
(a) += H ((b), (c), (d)) + (x) + (uint32)0x6ed9eba1; \
(a) = ROTATE_LEFT ((a), (s)); \
}
void md4_encode(unsigned char* output, const uint32* input, unsigned int len)
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
{
output[j] = (unsigned char)(input[i] & 0xff);
output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
}
}
void md4_decode(uint32* output, const unsigned char* input, unsigned int len)
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((uint32)input[j]) | (((uint32)input[j+1]) << 8) |
(((uint32)input[j+2]) << 16) | (((uint32)input[j+3]) << 24);
}
void md4_transform (uint32 state[4], const unsigned char block[64])
{
uint32 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
md4_decode(x, block, 64);
/* Round 1 */
FF (a, b, c, d, x[ 0], S11); /* 1 */
FF (d, a, b, c, x[ 1], S12); /* 2 */
FF (c, d, a, b, x[ 2], S13); /* 3 */
FF (b, c, d, a, x[ 3], S14); /* 4 */
FF (a, b, c, d, x[ 4], S11); /* 5 */
FF (d, a, b, c, x[ 5], S12); /* 6 */
FF (c, d, a, b, x[ 6], S13); /* 7 */
FF (b, c, d, a, x[ 7], S14); /* 8 */
FF (a, b, c, d, x[ 8], S11); /* 9 */
FF (d, a, b, c, x[ 9], S12); /* 10 */
FF (c, d, a, b, x[10], S13); /* 11 */
FF (b, c, d, a, x[11], S14); /* 12 */
FF (a, b, c, d, x[12], S11); /* 13 */
FF (d, a, b, c, x[13], S12); /* 14 */
FF (c, d, a, b, x[14], S13); /* 15 */
FF (b, c, d, a, x[15], S14); /* 16 */
/* Round 2 */
GG (a, b, c, d, x[ 0], S21); /* 17 */
GG (d, a, b, c, x[ 4], S22); /* 18 */
GG (c, d, a, b, x[ 8], S23); /* 19 */
GG (b, c, d, a, x[12], S24); /* 20 */
GG (a, b, c, d, x[ 1], S21); /* 21 */
GG (d, a, b, c, x[ 5], S22); /* 22 */
GG (c, d, a, b, x[ 9], S23); /* 23 */
GG (b, c, d, a, x[13], S24); /* 24 */
GG (a, b, c, d, x[ 2], S21); /* 25 */
GG (d, a, b, c, x[ 6], S22); /* 26 */
GG (c, d, a, b, x[10], S23); /* 27 */
GG (b, c, d, a, x[14], S24); /* 28 */
GG (a, b, c, d, x[ 3], S21); /* 29 */
GG (d, a, b, c, x[ 7], S22); /* 30 */
GG (c, d, a, b, x[11], S23); /* 31 */
GG (b, c, d, a, x[15], S24); /* 32 */
/* Round 3 */
HH (a, b, c, d, x[ 0], S31); /* 33 */
HH (d, a, b, c, x[ 8], S32); /* 34 */
HH (c, d, a, b, x[ 4], S33); /* 35 */
HH (b, c, d, a, x[12], S34); /* 36 */
HH (a, b, c, d, x[ 2], S31); /* 37 */
HH (d, a, b, c, x[10], S32); /* 38 */
HH (c, d, a, b, x[ 6], S33); /* 39 */
HH (b, c, d, a, x[14], S34); /* 40 */
HH (a, b, c, d, x[ 1], S31); /* 41 */
HH (d, a, b, c, x[ 9], S32); /* 42 */
HH (c, d, a, b, x[ 5], S33); /* 43 */
HH (b, c, d, a, x[13], S34); /* 44 */
HH (a, b, c, d, x[ 3], S31); /* 45 */
HH (d, a, b, c, x[11], S32); /* 46 */
HH (c, d, a, b, x[ 7], S33); /* 47 */
HH (b, c, d, a, x[15], S34); /* 48 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
/* Zeroize sensitive information. */
memset(x, 0, sizeof(x));
}
}//namespace
class MD4:public Hash
{
enum
{
BLOCK_SIZE = 64,
DIGEST_SIZE = 16
};
uint32 state[4]; // state (ABCD)
uint32 count[2]; // number of bits, modulo 2^64 (lsb first)
uchar buffer[64]; // input buffer
public:
void GetName(UTF8String &str)const override{str="MD4";}
void GetName(UTF16String &str)const override{str=U16_TEXT("MD4");}
const int GetHashBytes()const override{return DIGEST_SIZE;}
void Init()override
{
count[0] = count[1] = 0;
state[0] = 0x67452301;
state[1] = 0xefcdab89;
state[2] = 0x98badcfe;
state[3] = 0x10325476;
}
void Update(const void *input,uint inputLen)override
{
unsigned int i, index, partLen;
/* Compute number of bytes mod 64 */
index = (unsigned int)((count[0] >> 3) & 0x3F);
/* Update number of bits */
if ((count[0] += ((uint32) inputLen << 3)) < ((uint32) inputLen << 3))
count[1]++;
count[1] += ((uint32) inputLen >> 29);
partLen = 64 - index;
/* Transform as many times as possible. */
if (inputLen >= partLen)
{
memcpy(&buffer[index], input, partLen);
md4_transform(state, buffer);
for (i = partLen; i + 63 < inputLen; i += 64)
md4_transform(state, ((uchar *)input)+i);
index = 0;
}
else i = 0;
/* Buffer remaining input */
memcpy(&buffer[index], ((uchar *)input)+i, inputLen-i);
}
void Final(void *digest)override
{
static const unsigned char PADDING[64] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
unsigned char bits[8];
unsigned int index, padLen;
/* Save number of bits */
md4_encode(bits, count, 8);
/* Pad out to 56 mod 64. */
index = (unsigned int)((count[0] >> 3) & 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
Update(PADDING, padLen);
/* Append length (before padding) */
Update(bits, 8);
/* Store state in digest */
md4_encode((uchar *)digest, state, 16);
}
};//class MD4
Hash *CreateMD4Hash(){return(new MD4);}
}//namespace util
}//namespace hgl

258
src/hash/md5.cpp Normal file
View File

@ -0,0 +1,258 @@
#include<hgl/util/hash/Hash.h>
namespace hgl
{
namespace util
{
namespace
{
/* Constants for MD5Transform routine. */
#define S11 7
#define S12 12
#define S13 17
#define S14 22
#define S21 5
#define S22 9
#define S23 14
#define S24 20
#define S31 4
#define S32 11
#define S33 16
#define S34 23
#define S41 6
#define S42 10
#define S43 15
#define S44 21
/* F, G, H and I are basic MD5 functions. */
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))
/* ROTATE_LEFT rotates x left n bits. */
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
Rotation is separate from addition to prevent recomputation. */
#define FF(a, b, c, d, x, s, ac) { \
(a) += F ((b), (c), (d)) + (x) + (uint32)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) { \
(a) += G ((b), (c), (d)) + (x) + (uint32)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) { \
(a) += H ((b), (c), (d)) + (x) + (uint32)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define II(a, b, c, d, x, s, ac) { \
(a) += I ((b), (c), (d)) + (x) + (uint32)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
void md5_encode(unsigned char* output, const uint32* input, unsigned int len)
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
{
output[j] = (unsigned char)(input[i] & 0xff);
output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
}
}
void md5_decode(uint32* output, const unsigned char* input, unsigned int len)
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((uint32)input[j]) | (((uint32)input[j+1]) << 8) |
(((uint32)input[j+2]) << 16) | (((uint32)input[j+3]) << 24);
}
void md5_transform (uint32 state[4], const unsigned char block[64])
{
uint32 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
md5_decode(x, block, 64);
/* Round 1 */
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 2 */
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
/* Round 4 */
II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
/* Zeroize sensitive information. */
memset(x, 0, sizeof(x));
}
}//namespace
class MD5:public Hash
{
enum
{
BLOCK_SIZE = 64,
DIGEST_SIZE = 16
};
uint32 state[4];
uint32 count[2];
uchar buffer[64];
public:
void GetName(UTF8String &str)const override{str="MD5";}
void GetName(UTF16String &str)const override{str=U16_TEXT("MD5");}
const int GetHashBytes()const override{return DIGEST_SIZE;}
void Init()override
{
count[0] = count[1] = 0;
state[0] = 0x67452301;
state[1] = 0xefcdab89;
state[2] = 0x98badcfe;
state[3] = 0x10325476;
}
void Update(const void *input,uint inputLen)override
{
unsigned int i, index, partLen;
/* Compute number of bytes mod 64 */
index = (unsigned int)((count[0] >> 3) & 0x3F);
/* Update number of bits */
if ((count[0] += ((uint32) inputLen << 3)) < ((uint32) inputLen << 3))
count[1]++;
count[1] += ((uint32) inputLen >> 29);
partLen = 64 - index;
/* Transform as many times as possible. */
if (inputLen >= partLen)
{
memcpy(&buffer[index], input, partLen);
md5_transform(state, buffer);
for (i = partLen; i + 63 < inputLen; i += 64)
md5_transform(state, ((uchar *)input)+i);
index = 0;
}
else i = 0;
/* Buffer remaining input */
memcpy(&buffer[index], ((uchar *)input)+i,inputLen-i);
}
void Final(void *digest)override
{
static const unsigned char PADDING[64] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
unsigned char bits[8];
unsigned int index, padLen;
/* Save number of bits */
md5_encode(bits, count, 8);
/* Pad out to 56 mod 64. */
index = (unsigned int)((count[0] >> 3) & 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
Update(PADDING, padLen);
/* Append length (before padding) */
Update(bits, 8);
/* Store state in digest */
md5_encode((uchar *)digest, state, 16);
}
};//class MD5
Hash *CreateMD5Hash(){return(new MD5);}
}//namespace util
}//namespace hgl

250
src/hash/sha1.cpp Normal file
View File

@ -0,0 +1,250 @@
#include<hgl/util/hash/Hash.h>
#include<hgl/Endian.h>
namespace hgl
{
namespace util
{
namespace
{
/* The SHA f()-functions */
#define f1(x,y,z) ( ( x & y ) | ( ~x & z ) ) /* Rounds 0-19 */
#define f2(x,y,z) ( x ^ y ^ z ) /* Rounds 20-39 */
#define f3(x,y,z) ( ( x & y ) | ( x & z ) | ( y & z ) ) /* Rounds 40-59 */
#define f4(x,y,z) ( x ^ y ^ z ) /* Rounds 60-79 */
/* The SHA Mysterious Constants */
#define K1 0x5A827999L /* Rounds 0-19 */
#define K2 0x6ED9EBA1L /* Rounds 20-39 */
#define K3 0x8F1BBCDCL /* Rounds 40-59 */
#define K4 0xCA62C1D6L /* Rounds 60-79 */
#define S(n,X) ( ( ((uint32)X) << n ) | ( ((uint32)X) >> ( 32 - n ) ) )
/* The initial expanding function */
#define expand(count) W[ count ] = S(1,(W[ count - 3 ] ^ W[ count - 8 ] ^ W[ count - 14 ] ^ W[ count - 16 ])) /* to make this SHA-1 */
/* The four SHA sub-rounds */
#define subRound1(count) \
{ \
temp = S( 5, A ) + f1( B, C, D ) + E + W[ count ] + K1; \
E = D; \
D = C; \
C = S( 30, B ); \
B = A; \
A = temp; \
}
#define subRound2(count) \
{ \
temp = S( 5, A ) + f2( B, C, D ) + E + W[ count ] + K2; \
E = D; \
D = C; \
C = S( 30, B ); \
B = A; \
A = temp; \
}
#define subRound3(count) \
{ \
temp = S( 5, A ) + f3( B, C, D ) + E + W[ count ] + K3; \
E = D; \
D = C; \
C = S( 30, B ); \
B = A; \
A = temp; \
}
#define subRound4(count) \
{ \
temp = S( 5, A ) + f4( B, C, D ) + E + W[ count ] + K4; \
E = D; \
D = C; \
C = S( 30, B ); \
B = A; \
A = temp; \
}
}//namespace
class SHA1:public Hash
{
enum
{
BLOCK_SIZE = 64,
DIGEST_SIZE = 20
};
uint32 digest[5]; // Message digest
uint32 countLo; // 64-bit bit count
uint32 countHi;
uint32 data[16]; // SHA data buffer
uint32 slop; // # of bytes saved in data[]
uint32 W[80];
private:
void sha1_transform()
{
uint32 temp;
uint32 A, B, C, D, E;
/* Step A. Copy the data buffer into the local work buffer */
hgl_cpy(W,data,16);
/* Step B. Expand the 16 words into 64 temporary data words */
expand( 16 ); expand( 17 ); expand( 18 ); expand( 19 ); expand( 20 );
expand( 21 ); expand( 22 ); expand( 23 ); expand( 24 ); expand( 25 );
expand( 26 ); expand( 27 ); expand( 28 ); expand( 29 ); expand( 30 );
expand( 31 ); expand( 32 ); expand( 33 ); expand( 34 ); expand( 35 );
expand( 36 ); expand( 37 ); expand( 38 ); expand( 39 ); expand( 40 );
expand( 41 ); expand( 42 ); expand( 43 ); expand( 44 ); expand( 45 );
expand( 46 ); expand( 47 ); expand( 48 ); expand( 49 ); expand( 50 );
expand( 51 ); expand( 52 ); expand( 53 ); expand( 54 ); expand( 55 );
expand( 56 ); expand( 57 ); expand( 58 ); expand( 59 ); expand( 60 );
expand( 61 ); expand( 62 ); expand( 63 ); expand( 64 ); expand( 65 );
expand( 66 ); expand( 67 ); expand( 68 ); expand( 69 ); expand( 70 );
expand( 71 ); expand( 72 ); expand( 73 ); expand( 74 ); expand( 75 );
expand( 76 ); expand( 77 ); expand( 78 ); expand( 79 );
/* Step C. Set up first buffer */
A = digest[ 0 ];
B = digest[ 1 ];
C = digest[ 2 ];
D = digest[ 3 ];
E = digest[ 4 ];
/* Step D. Serious mangling, divided into four sub-rounds */
subRound1( 0 ); subRound1( 1 ); subRound1( 2 ); subRound1( 3 );
subRound1( 4 ); subRound1( 5 ); subRound1( 6 ); subRound1( 7 );
subRound1( 8 ); subRound1( 9 ); subRound1( 10 ); subRound1( 11 );
subRound1( 12 ); subRound1( 13 ); subRound1( 14 ); subRound1( 15 );
subRound1( 16 ); subRound1( 17 ); subRound1( 18 ); subRound1( 19 );
subRound2( 20 ); subRound2( 21 ); subRound2( 22 ); subRound2( 23 );
subRound2( 24 ); subRound2( 25 ); subRound2( 26 ); subRound2( 27 );
subRound2( 28 ); subRound2( 29 ); subRound2( 30 ); subRound2( 31 );
subRound2( 32 ); subRound2( 33 ); subRound2( 34 ); subRound2( 35 );
subRound2( 36 ); subRound2( 37 ); subRound2( 38 ); subRound2( 39 );
subRound3( 40 ); subRound3( 41 ); subRound3( 42 ); subRound3( 43 );
subRound3( 44 ); subRound3( 45 ); subRound3( 46 ); subRound3( 47 );
subRound3( 48 ); subRound3( 49 ); subRound3( 50 ); subRound3( 51 );
subRound3( 52 ); subRound3( 53 ); subRound3( 54 ); subRound3( 55 );
subRound3( 56 ); subRound3( 57 ); subRound3( 58 ); subRound3( 59 );
subRound4( 60 ); subRound4( 61 ); subRound4( 62 ); subRound4( 63 );
subRound4( 64 ); subRound4( 65 ); subRound4( 66 ); subRound4( 67 );
subRound4( 68 ); subRound4( 69 ); subRound4( 70 ); subRound4( 71 );
subRound4( 72 ); subRound4( 73 ); subRound4( 74 ); subRound4( 75 );
subRound4( 76 ); subRound4( 77 ); subRound4( 78 ); subRound4( 79 );
/* Step E. Build message digest */
digest[ 0 ] += A;
digest[ 1 ] += B;
digest[ 2 ] += C;
digest[ 3 ] += D;
digest[ 4 ] += E;
}
public:
void GetName(UTF8String &str)const override{str="SHA1";}
void GetName(UTF16String &str)const override{str=U16_TEXT("SHA1");}
const int GetHashBytes()const override{return DIGEST_SIZE;}
void Init()override
{
digest[0] = 0x67452301L;
digest[1] = 0xEFCDAB89L;
digest[2] = 0x98BADCFEL;
digest[3] = 0x10325476L;
digest[4] = 0xC3D2E1F0L;
countLo = 0;
countHi = 0;
slop = 0;
memset(data, 0, sizeof(data));
}
void Update(const void *input,uint count)override
{
const uint8 *buffer=(const uint8 *)input;
uint size;
/* Update bitcount */
if ((countLo + ((uint32) count << 3)) < countLo)
countHi++; /* Carry from low to high bitCount */
countLo += ((uint32) count << 3);
countHi += ((uint32 ) count >> 29);
/* Process data in BLOCK_SIZE chunks */
while (count > 0)
{
size=BLOCK_SIZE-slop;
if(size>count)
size=count;
memcpy(data,buffer,size);
slop+=size;
buffer+=size;
count-=size;
if (slop == BLOCK_SIZE)
{
/* transform this one block */
ToBigEndian<uint32>(data, BLOCK_SIZE>>2);
sha1_transform();
slop = 0 ; /* no slop left */
}
}
}
void Final(void *result)override
{
int count;
uint32 lowBitcount = countLo;
uint32 highBitcount = countHi;
/* Compute number of bytes mod 64 */
count = (int) ((countLo >> 3) & 0x3F);
/* Set the first char of padding to 0x80. This is safe since there is
always at least one byte free */
((uint8*) data)[count++] = 0x80;
/* Pad out to 56 mod 64 */
if (count > 56)
{
/* Two lots of padding: Pad the first block to 64 bytes */
memset((uint8*) &data + count, 0, 64 - count);
ToBigEndian<uint32>(data, BLOCK_SIZE>>2);
sha1_transform();
/* Now fill the next block with 56 bytes */
memset(&data, 0, 56);
}
else
{
/* Pad block to 56 bytes */
memset((uint8*) &data + count, 0, 56 - count);
}
ToBigEndian<uint32>(data, BLOCK_SIZE>>2);
/* Append length in bits and transform */
data[14] = highBitcount;
data[15] = lowBitcount;
sha1_transform();
ToBigEndian<uint32>(data, BLOCK_SIZE>>2);
uint8 *hash=(uint8 *)result;
for (count = 0; count < DIGEST_SIZE; count++)
hash[count] = (uint8) ((digest[count>>2]) >> (8*(3-(count & 0x3)))) & 0xff;
}
};//class SHA1
Hash *CreateSHA1Hash(){return(new SHA1);}
}//namespace util
}//namespace hgl

227
src/hash/sha1le.cpp Normal file
View File

@ -0,0 +1,227 @@
#include<hgl/util/hash/SHA1LE.h>
namespace hgl
{
namespace util
{
namespace
{
/* The SHA f()-functions */
#define f1(x,y,z) ( ( x & y ) | ( ~x & z ) ) /* Rounds 0-19 */
#define f2(x,y,z) ( x ^ y ^ z ) /* Rounds 20-39 */
#define f3(x,y,z) ( ( x & y ) | ( x & z ) | ( y & z ) ) /* Rounds 40-59 */
#define f4(x,y,z) ( x ^ y ^ z ) /* Rounds 60-79 */
#define S(n,X) ( ( ((uint32)X) << n ) | ( ((uint32)X) >> ( 32 - n ) ) )
/* The initial expanding function */
#define expand(count) W[ count ] = S(1,(W[ count - 3 ] ^ W[ count - 8 ] ^ W[ count - 14 ] ^ W[ count - 16 ])) /* to make this SHA-1 */
/* The four SHA sub-rounds */
#define subRound1(count) \
{ \
temp = S( 5, A ) + f1( B, C, D ) + E + W[ count ] + K[0]; \
E = D; \
D = C; \
C = S( 30, B ); \
B = A; \
A = temp; \
}
#define subRound2(count) \
{ \
temp = S( 5, A ) + f2( B, C, D ) + E + W[ count ] + K[1]; \
E = D; \
D = C; \
C = S( 30, B ); \
B = A; \
A = temp; \
}
#define subRound3(count) \
{ \
temp = S( 5, A ) + f3( B, C, D ) + E + W[ count ] + K[2]; \
E = D; \
D = C; \
C = S( 30, B ); \
B = A; \
A = temp; \
}
#define subRound4(count) \
{ \
temp = S( 5, A ) + f4( B, C, D ) + E + W[ count ] + K[3]; \
E = D; \
D = C; \
C = S( 30, B ); \
B = A; \
A = temp; \
}
}//namespace
void SHA1LE::sha1_transform()
{
uint32 temp;
uint32 A, B, C, D, E;
/* Step A. Copy the data buffer into the local work buffer */
hgl_cpy(W,data,16);
/* Step B. Expand the 16 words into 64 temporary data words */
expand( 16 ); expand( 17 ); expand( 18 ); expand( 19 ); expand( 20 );
expand( 21 ); expand( 22 ); expand( 23 ); expand( 24 ); expand( 25 );
expand( 26 ); expand( 27 ); expand( 28 ); expand( 29 ); expand( 30 );
expand( 31 ); expand( 32 ); expand( 33 ); expand( 34 ); expand( 35 );
expand( 36 ); expand( 37 ); expand( 38 ); expand( 39 ); expand( 40 );
expand( 41 ); expand( 42 ); expand( 43 ); expand( 44 ); expand( 45 );
expand( 46 ); expand( 47 ); expand( 48 ); expand( 49 ); expand( 50 );
expand( 51 ); expand( 52 ); expand( 53 ); expand( 54 ); expand( 55 );
expand( 56 ); expand( 57 ); expand( 58 ); expand( 59 ); expand( 60 );
expand( 61 ); expand( 62 ); expand( 63 ); expand( 64 ); expand( 65 );
expand( 66 ); expand( 67 ); expand( 68 ); expand( 69 ); expand( 70 );
expand( 71 ); expand( 72 ); expand( 73 ); expand( 74 ); expand( 75 );
expand( 76 ); expand( 77 ); expand( 78 ); expand( 79 );
/* Step C. Set up first buffer */
A = digest[ 0 ];
B = digest[ 1 ];
C = digest[ 2 ];
D = digest[ 3 ];
E = digest[ 4 ];
/* Step D. Serious mangling, divided into four sub-rounds */
subRound1( 0 ); subRound1( 1 ); subRound1( 2 ); subRound1( 3 );
subRound1( 4 ); subRound1( 5 ); subRound1( 6 ); subRound1( 7 );
subRound1( 8 ); subRound1( 9 ); subRound1( 10 ); subRound1( 11 );
subRound1( 12 ); subRound1( 13 ); subRound1( 14 ); subRound1( 15 );
subRound1( 16 ); subRound1( 17 ); subRound1( 18 ); subRound1( 19 );
subRound2( 20 ); subRound2( 21 ); subRound2( 22 ); subRound2( 23 );
subRound2( 24 ); subRound2( 25 ); subRound2( 26 ); subRound2( 27 );
subRound2( 28 ); subRound2( 29 ); subRound2( 30 ); subRound2( 31 );
subRound2( 32 ); subRound2( 33 ); subRound2( 34 ); subRound2( 35 );
subRound2( 36 ); subRound2( 37 ); subRound2( 38 ); subRound2( 39 );
subRound3( 40 ); subRound3( 41 ); subRound3( 42 ); subRound3( 43 );
subRound3( 44 ); subRound3( 45 ); subRound3( 46 ); subRound3( 47 );
subRound3( 48 ); subRound3( 49 ); subRound3( 50 ); subRound3( 51 );
subRound3( 52 ); subRound3( 53 ); subRound3( 54 ); subRound3( 55 );
subRound3( 56 ); subRound3( 57 ); subRound3( 58 ); subRound3( 59 );
subRound4( 60 ); subRound4( 61 ); subRound4( 62 ); subRound4( 63 );
subRound4( 64 ); subRound4( 65 ); subRound4( 66 ); subRound4( 67 );
subRound4( 68 ); subRound4( 69 ); subRound4( 70 ); subRound4( 71 );
subRound4( 72 ); subRound4( 73 ); subRound4( 74 ); subRound4( 75 );
subRound4( 76 ); subRound4( 77 ); subRound4( 78 ); subRound4( 79 );
/* Step E. Build message digest */
digest[ 0 ] += A;
digest[ 1 ] += B;
digest[ 2 ] += C;
digest[ 3 ] += D;
digest[ 4 ] += E;
}
void SHA1LE::SetMark(const uint32 *mysterious_constants)
{
hgl_cpy(K,mysterious_constants,4);
}
void SHA1LE::Init(const uint32 *_start_digest,const uint32 *mysterious_constants)
{
hgl_cpy(digest,_start_digest,5);
SetMark(mysterious_constants);
countLo = 0;
countHi = 0;
slop = 0;
memset(data, 0, sizeof(data));
}
void SHA1LE::Init()
{
constexpr uint32 d[5]={0x01234567L,0x89ABCDEFL,0xFEDCBA98L,0x76543210L,0x0F1E2D3CL};
constexpr uint32 k[4]={0x5A827999L,0x6ED9EBA1L,0x8F1BBCDCL,0xCA62C1D6L};
Init(d,k);
}
void SHA1LE::Update(const void *input,uint count)
{
const uint8 *buffer=(const uint8 *)input;
uint size;
/* Update bitcount */
if ((countLo + ((uint32) count << 3)) < countLo)
countHi++; /* Carry from low to high bitCount */
countLo += ((uint32) count << 3);
countHi += ((uint32 ) count >> 29);
/* Process data in BLOCK_SIZE chunks */
while (count > 0)
{
size=BLOCK_SIZE-slop;
if(size>count)
size=count;
memcpy(data,buffer,size);
slop+=size;
buffer+=size;
count-=size;
if (slop == BLOCK_SIZE)
{
/* transform this one block */
sha1_transform();
slop = 0 ; /* no slop left */
}
}
}
void SHA1LE::Final(void *result)
{
int count;
uint32 lowBitcount = countLo;
uint32 highBitcount = countHi;
/* Compute number of bytes mod 64 */
count = (int) ((countLo >> 3) & 0x3F);
/* Set the first char of padding to 0x80. This is safe since there is
always at least one byte free */
((uint8*) data)[count++] = 0x80;
/* Pad out to 56 mod 64 */
if (count > 56)
{
/* Two lots of padding: Pad the first block to 64 bytes */
memset((uint8*) &data + count, 0, 64 - count);
sha1_transform();
/* Now fill the next block with 56 bytes */
memset(&data, 0, 56);
}
else
{
/* Pad block to 56 bytes */
memset((uint8*) &data + count, 0, 56 - count);
}
/* Append length in bits and transform */
data[14] = highBitcount;
data[15] = lowBitcount;
sha1_transform();
uint8 *hash=(uint8 *)result;
for (count = 0; count < DIGEST_SIZE; count++)
hash[count] = (uint8) ((digest[count>>2]) >> (8*(3-(count & 0x3)))) & 0xff;
}
Hash *CreateSHA1LEHash(){return(new SHA1LE);}
}//namespace util
}//namespace hgl

198
src/hash/sha256.cpp Normal file
View File

@ -0,0 +1,198 @@
#include<hgl/util/hash/Hash.h>
namespace hgl
{
namespace util
{
namespace
{
#define ROTLEFT(a,b) (((a) << (b)) | ((a) >> (32-(b))))
#define ROTRIGHT(a,b) (((a) >> (b)) | ((a) << (32-(b))))
#define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z)))
#define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
#define EP0(x) (ROTRIGHT(x,2) ^ ROTRIGHT(x,13) ^ ROTRIGHT(x,22))
#define EP1(x) (ROTRIGHT(x,6) ^ ROTRIGHT(x,11) ^ ROTRIGHT(x,25))
#define SIG0(x) (ROTRIGHT(x,7) ^ ROTRIGHT(x,18) ^ ((x) >> 3))
#define SIG1(x) (ROTRIGHT(x,17) ^ ROTRIGHT(x,19) ^ ((x) >> 10))
/**************************** VARIABLES *****************************/
constexpr uint32 k[64] =
{
0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
};
}//namespace
class SHA256:public Hash
{
enum
{
BLOCK_SIZE = 64,
DIGEST_SIZE = 32
};
uint32 state[8];
uint8 data[64]; // SHA data buffer
uint64 bitlen;
uint32 datalen;
uint32 m[64];
private:
void sha256_transform()
{
uint32 a, b, c, d, e, f, g, h, i, j, t1, t2;
for (i = 0, j = 0; i < 16; ++i, j += 4)
m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]);
for ( ; i < 64; ++i)
m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
f = state[5];
g = state[6];
h = state[7];
for (i = 0; i < 64; ++i) {
t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i];
t2 = EP0(a) + MAJ(a,b,c);
h = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
}
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
state[5] += f;
state[6] += g;
state[7] += h;
}
public:
void GetName(UTF8String &str)const override{str="SHA256";}
void GetName(UTF16String &str)const override{str=U16_TEXT("SHA256");}
const int GetHashBytes()const override{return DIGEST_SIZE;}
void Init()override
{
state[0] = 0x6a09e667;
state[1] = 0xbb67ae85;
state[2] = 0x3c6ef372;
state[3] = 0xa54ff53a;
state[4] = 0x510e527f;
state[5] = 0x9b05688c;
state[6] = 0x1f83d9ab;
state[7] = 0x5be0cd19;
bitlen=0;
datalen=0;
memset(data, 0, sizeof(data));
}
void Update(const void *input,uint count)override
{
const uint8 *u8input=(const uint8 *)input;
uint32 size;
while(count>0)
{
size=BLOCK_SIZE-datalen;
if(size>count)
size=count;
memcpy(data+datalen,u8input,size);
datalen+=size;
count-=size;
u8input+=size;
if (datalen == BLOCK_SIZE)
{
sha256_transform();
bitlen += 512;
datalen = 0;
}
}
}
void Final(void *result)override
{
uint32 i;
i = datalen;
// Pad whatever data is left in the buffer.
if (datalen < 56)
{
data[i++] = 0x80;
memset(data+i,0,56-i);
}
else
{
data[i++] = 0x80;
memset(data+i,0,64-i);
sha256_transform();
memset(data, 0, 56);
}
// Append to the padding the total message's length in bits and transform.
bitlen += datalen * 8;
data[63] = bitlen;
data[62] = bitlen >> 8;
data[61] = bitlen >> 16;
data[60] = bitlen >> 24;
data[59] = bitlen >> 32;
data[58] = bitlen >> 40;
data[57] = bitlen >> 48;
data[56] = bitlen >> 56;
sha256_transform();
// Since this implementation uses little endian byte ordering and SHA uses big endian,
// reverse all the bytes when copying the final state to the output hash.
uint8 *hash=(uint8 *)result;
for (i = 0; i < 4; ++i)
{
hash[i] = (state[0] >> (24 - i * 8)) & 0x000000ff;
hash[i + 4] = (state[1] >> (24 - i * 8)) & 0x000000ff;
hash[i + 8] = (state[2] >> (24 - i * 8)) & 0x000000ff;
hash[i + 12] = (state[3] >> (24 - i * 8)) & 0x000000ff;
hash[i + 16] = (state[4] >> (24 - i * 8)) & 0x000000ff;
hash[i + 20] = (state[5] >> (24 - i * 8)) & 0x000000ff;
hash[i + 24] = (state[6] >> (24 - i * 8)) & 0x000000ff;
hash[i + 28] = (state[7] >> (24 - i * 8)) & 0x000000ff;
}
}
};//class SHA256
Hash *CreateSHA256Hash(){return(new SHA256);}
}//namespace util
}//namespace hgl

244
src/hash/sha512.cpp Normal file
View File

@ -0,0 +1,244 @@
#include<hgl/util/hash/Hash.h>
namespace hgl
{
namespace util
{
namespace
{
#define SHA2_SHFR(x, n) (x >> n)
#define SHA2_ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
#define SHA2_ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
#define SHA2_CH(x, y, z) ((x & y) ^ (~x & z))
#define SHA2_MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
#define SHA512_F1(x) (SHA2_ROTR(x, 28) ^ SHA2_ROTR(x, 34) ^ SHA2_ROTR(x, 39))
#define SHA512_F2(x) (SHA2_ROTR(x, 14) ^ SHA2_ROTR(x, 18) ^ SHA2_ROTR(x, 41))
#define SHA512_F3(x) (SHA2_ROTR(x, 1) ^ SHA2_ROTR(x, 8) ^ SHA2_SHFR(x, 7))
#define SHA512_F4(x) (SHA2_ROTR(x, 19) ^ SHA2_ROTR(x, 61) ^ SHA2_SHFR(x, 6))
#define SHA2_UNPACK32(x, str) \
{ \
*((str) + 3) = (uint8) ((x) ); \
*((str) + 2) = (uint8) ((x) >> 8); \
*((str) + 1) = (uint8) ((x) >> 16); \
*((str) + 0) = (uint8) ((x) >> 24); \
}
#define SHA2_UNPACK64(x, str) \
{ \
*((str) + 7) = (uint8) ((x) ); \
*((str) + 6) = (uint8) ((x) >> 8); \
*((str) + 5) = (uint8) ((x) >> 16); \
*((str) + 4) = (uint8) ((x) >> 24); \
*((str) + 3) = (uint8) ((x) >> 32); \
*((str) + 2) = (uint8) ((x) >> 40); \
*((str) + 1) = (uint8) ((x) >> 48); \
*((str) + 0) = (uint8) ((x) >> 56); \
}
#define SHA2_PACK64(str, x) \
{ \
*(x) = ((uint64) *((str) + 7) ) \
| ((uint64) *((str) + 6) << 8) \
| ((uint64) *((str) + 5) << 16) \
| ((uint64) *((str) + 4) << 24) \
| ((uint64) *((str) + 3) << 32) \
| ((uint64) *((str) + 2) << 40) \
| ((uint64) *((str) + 1) << 48) \
| ((uint64) *((str) + 0) << 56); \
}
constexpr uint SHA384_512_BLOCK_SIZE = (1024/8);
constexpr uint64 K[80] =
{
0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
};
}//namespace
class SHA512:public Hash
{
enum
{
BLOCK_SIZE = 64,
DIGEST_SIZE = 64
};
uint m_tot_len;
uint m_len;
uint8 m_block[2 * SHA384_512_BLOCK_SIZE];
uint64 m_h[8];
uint64 w[80];
uint64 wv[8];
private:
void transform(const unsigned char *message, unsigned int block_nb)
{
uint64 t1, t2;
const unsigned char *sub_block;
int i, j;
for (i = 0; i < (int) block_nb; i++)
{
sub_block = message + (i << 7);
for (j = 0; j < 16; j++)
{
SHA2_PACK64(&sub_block[j << 3], &w[j]);
}
for (j = 16; j < 80; j++)
{
w[j] = SHA512_F4(w[j - 2]) + w[j - 7] + SHA512_F3(w[j - 15]) + w[j - 16];
}
for (j = 0; j < 8; j++)
{
wv[j] = m_h[j];
}
for (j = 0; j < 80; j++)
{
t1 = wv[7] + SHA512_F2(wv[4]) + SHA2_CH(wv[4], wv[5], wv[6]) + K[j] + w[j];
t2 = SHA512_F1(wv[0]) + SHA2_MAJ(wv[0], wv[1], wv[2]);
wv[7] = wv[6];
wv[6] = wv[5];
wv[5] = wv[4];
wv[4] = wv[3] + t1;
wv[3] = wv[2];
wv[2] = wv[1];
wv[1] = wv[0];
wv[0] = t1 + t2;
}
for (j = 0; j < 8; j++)
{
m_h[j] += wv[j];
}
}
}
public:
void GetName(UTF8String &str)const override{str="SHA512";}
void GetName(UTF16String &str)const override{str=U16_TEXT("SHA512");}
const int GetHashBytes()const override{return DIGEST_SIZE;}
void Init()override
{
m_h[0] = 0x6a09e667f3bcc908ULL;
m_h[1] = 0xbb67ae8584caa73bULL;
m_h[2] = 0x3c6ef372fe94f82bULL;
m_h[3] = 0xa54ff53a5f1d36f1ULL;
m_h[4] = 0x510e527fade682d1ULL;
m_h[5] = 0x9b05688c2b3e6c1fULL;
m_h[6] = 0x1f83d9abfb41bd6bULL;
m_h[7] = 0x5be0cd19137e2179ULL;
m_len = 0;
m_tot_len = 0;
}
void Update(const void *input,uint len)override
{
uint8 *message=(uint8 *)input;
uint block_nb;
uint new_len, rem_len, tmp_len;
const uint8 *shifted_message;
tmp_len = SHA384_512_BLOCK_SIZE - m_len;
rem_len = len < tmp_len ? len : tmp_len;
memcpy(&m_block[m_len], message, rem_len);
if (m_len + len < SHA384_512_BLOCK_SIZE)
{
m_len += len;
return;
}
new_len = len - rem_len;
block_nb = new_len / SHA384_512_BLOCK_SIZE;
shifted_message = message + rem_len;
transform(m_block, 1);
transform(shifted_message, block_nb);
rem_len = new_len % SHA384_512_BLOCK_SIZE;
memcpy(m_block, &shifted_message[block_nb << 7], rem_len);
m_len = rem_len;
m_tot_len += (block_nb + 1) << 7;
}
void Final(void *result)override
{
uint block_nb;
uint pm_len;
uint len_b;
int i;
block_nb = 1 + ((SHA384_512_BLOCK_SIZE - 17)
< (m_len % SHA384_512_BLOCK_SIZE));
len_b = (m_tot_len + m_len) << 3;
pm_len = block_nb << 7;
memset(m_block + m_len, 0, pm_len - m_len);
m_block[m_len] = 0x80;
SHA2_UNPACK32(len_b, m_block + pm_len - 4);
transform(m_block, block_nb);
uint8 *digest=(uint8 *)result;
for (i = 0 ; i < 8; i++) {
SHA2_UNPACK64(m_h[i], &digest[i << 3]);
}
}
};//class SHA512
Hash *CreateSHA512Hash(){return(new SHA512);}
}//namespace util
}//namespace hgl