123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428 |
- /************************************************************************/
- /* Copyright (C), 2016-2020, [IT], 保留所有权利;
- /* 模 块 名:;
- /* 描 述:;
- /*
- /* 版 本:[V];
- /* 作 者:[IT];
- /* 日 期:[7/11/2016];
- /*
- /*
- /* 注 意:;
- /*
- /* 修改记录:[IT];
- /* 修改日期:;
- /* 修改版本:;
- /* 修改内容:;
- /************************************************************************/
- #ifndef __SHA1_HEADER__
- #define __SHA1_HEADER__
- #include <assert.h>
- typedef unsigned int uint32_t;
- typedef unsigned long long uint64_t;
- // 字节序的小头和大头的问题;
- #define LITTLE_ENDIAN 0x0123
- #define BIG_ENDIAN 0x3210
- #ifndef BYTES_ORDER
- #define BYTES_ORDER LITTLE_ENDIAN
- #endif
- #ifndef SWAP_UINT16
- #define SWAP_UINT16(x) ((((x) & 0xff00) >> 8) | (((x) & 0x00ff) << 8))
- #endif
- #ifndef SWAP_UINT32
- #define SWAP_UINT32(x) ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
- (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
- #endif
- #ifndef SWAP_UINT64
- #define SWAP_UINT64(x) ((((x) & 0xff00000000000000) >> 56) | (((x) & 0x00ff000000000000) >> 40) | \
- (((x) & 0x0000ff0000000000) >> 24) | (((x) & 0x000000ff00000000) >> 8) | \
- (((x) & 0x00000000ff000000) << 8 ) | (((x) & 0x0000000000ff0000) << 24) | \
- (((x) & 0x000000000000ff00) << 40 ) | (((x) & 0x00000000000000ff) << 56))
- #endif
- #define ROTL32(dword, n) ((dword) << (n) ^ ((dword) >> (32 - (n))))
- #define ROTR32(dword, n) ((dword) >> (n) ^ ((dword) << (32 - (n))))
- #define ROTL64(qword, n) ((qword) << (n) ^ ((qword) >> (64 - (n))))
- #define ROTR64(qword, n) ((qword) >> (n) ^ ((qword) << (64 - (n))))
- // SHA1的结果数据长度;
- static const size_t SHA1_HASH_SIZE = 20;
- // SHA1每次处理的BLOCK的大小;
- static const size_t SHA1_BLOCK_SIZE = 64;
- /************************************************************************/
- /* 函数:ByteTrun2Hex[7/11/2016 IT];
- /* 描述:将每个字节转化成由2个十六进制字符表示的字符串;
- /* 参数:;
- /* [IN] szMsg:要被转换的字节数组;
- /* [IN] nCount:要被转换的字节数组长度;
- /* [IN/OUT] szConvMsg:转换成2个十六进制字符表示的字符串;
- /* 返回:void;
- /* 注意:;
- /* 示例:;
- /*
- /* 修改:;
- /* 日期:;
- /* 内容:;
- /************************************************************************/
- void ByteTrun2Hex( unsigned char *szMsg, int nCount, unsigned char *szConvMsg )
- {
- unsigned char lh[2];
- for (int i = 0; i < nCount; i++)
- {
- lh[0] = szMsg[i] >> 4;
- lh[1] = szMsg[i] & 0x0f;
- for ( int j = 0; j < 2; j++ )
- {
- if ( lh[j] <= 9 )
- szConvMsg[i*2 + j] = lh[j] + '0';
- else
- {
- switch ( lh[j] )
- {
- case 10:
- szConvMsg[i*2 + j] = 'a';
- break;
- case 11:
- szConvMsg[i*2 + j] = 'b';
- break;
- case 12:
- szConvMsg[i*2 + j] = 'c';
- break;
- case 13:
- szConvMsg[i*2 + j] = 'd';
- break;
- case 14:
- szConvMsg[i*2 + j] = 'e';
- break;
- case 15:
- szConvMsg[i*2 + j] = 'f';
- break;
- default:
- break;
- }
- }
- }
- }
- }
- /************************************************************************/
- /* 函数:swap_uint32_memcpy[7/11/2016 IT];
- /* 描述:将一个(字符串)数组,拷贝到另外一个uint32_t数组,同时每个uint32_t反字节序;
- /* 参数:;
- /* [IN] :;
- /* [OUT] :;
- /* [IN/OUT] :;
- /* 返回:void;
- /* 注意:;
- /* 示例:;
- /*
- /* 修改:;
- /* 日期:;
- /* 内容:;
- /************************************************************************/
- void *swap_uint32_memcpy(void *to, const void *from, size_t length)
- {
- memcpy(to, from, length);
- size_t remain_len = (4 - (length & 3)) & 3;
- // 数据不是4字节的倍数,补充0;
- if (remain_len)
- {
- for (size_t i = 0; i < remain_len; ++i)
- {
- *((char *)(to) + length + i) = 0;
- }
- //调整成4的倍数;
- length += remain_len;
- }
- // 所有的数据反转;
- for (size_t i = 0; i < length / 4; ++i)
- {
- ((uint32_t *)to)[i] = SWAP_UINT32(((uint32_t *)to)[i]);
- }
- return to;
- }
- //SHA1算法的上下文,保存一些状态,中间数据,结果;
- typedef struct sha1_ctx
- {
- // 处理的数据的长度;
- uint64_t length_;
- // 还没有处理的数据长度;
- uint64_t unprocessed_;
- /* 160-bit algorithm internal hashing state */
- uint32_t hash_[5];
- } sha1_ctx;
- //内部函数,SHA1算法的上下文的初始化;
- static void sha1_init(sha1_ctx *ctx)
- {
- ctx->length_ = 0;
- ctx->unprocessed_ = 0;
- // 初始化算法的几个常量,魔术数;
- ctx->hash_[0] = 0x67452301;
- ctx->hash_[1] = 0xefcdab89;
- ctx->hash_[2] = 0x98badcfe;
- ctx->hash_[3] = 0x10325476;
- ctx->hash_[4] = 0xc3d2e1f0;
- }
- /************************************************************************/
- /* 函数:sha1_process_block[7/12/2016 IT];
- /* 描述:内部函数,对一个64bit内存块进行摘要(杂凑)处理;
- /* 参数:;
- /* [IN] hash:存放计算hash结果的的数组;
- /* [IN] block:要计算的处理得内存块;
- /* 返回:void;
- /* 注意:;
- /* 示例:;
- /*
- /* 修改:;
- /* 日期:;
- /* 内容:;
- /************************************************************************/
- static void sha1_process_block(uint32_t hash[5],const uint32_t block[SHA1_BLOCK_SIZE / 4])
- {
- size_t t;
- uint32_t wblock[80];
- register uint32_t a, b, c, d, e, temp;
- //SHA1算法处理的内部数据要求是大头党的,在小头的环境转换;
- #if BYTES_ORDER == LITTLE_ENDIAN
- swap_uint32_memcpy(wblock, block, SHA1_BLOCK_SIZE);
- #else
- ::memcpy(wblock, block, SHA1_BLOCK_SIZE);
- #endif
- //处理
- for (t = 16; t < 80; t++)
- {
- wblock[t] = ROTL32(wblock[t - 3] ^ wblock[t - 8] ^ wblock[t - 14] ^ wblock[t - 16], 1);
- }
- a = hash[0];
- b = hash[1];
- c = hash[2];
- d = hash[3];
- e = hash[4];
- for (t = 0; t < 20; t++)
- {
- /* the following is faster than ((B & C) | ((~B) & D)) */
- temp = ROTL32(a, 5) + (((c ^ d) & b) ^ d) + e + wblock[t] + 0x5A827999;
- e = d;
- d = c;
- c = ROTL32(b, 30);
- b = a;
- a = temp;
- }
- for (t = 20; t < 40; t++)
- {
- temp = ROTL32(a, 5) + (b ^ c ^ d) + e + wblock[t] + 0x6ED9EBA1;
- e = d;
- d = c;
- c = ROTL32(b, 30);
- b = a;
- a = temp;
- }
- for (t = 40; t < 60; t++)
- {
- temp = ROTL32(a, 5) + ((b & c) | (b & d) | (c & d)) + e + wblock[t] + 0x8F1BBCDC;
- e = d;
- d = c;
- c = ROTL32(b, 30);
- b = a;
- a = temp;
- }
- for (t = 60; t < 80; t++)
- {
- temp = ROTL32(a, 5) + (b ^ c ^ d) + e + wblock[t] + 0xCA62C1D6;
- e = d;
- d = c;
- c = ROTL32(b, 30);
- b = a;
- a = temp;
- }
- hash[0] += a;
- hash[1] += b;
- hash[2] += c;
- hash[3] += d;
- hash[4] += e;
- }
- /************************************************************************/
- /* 函数:sha1_update[7/12/2016 IT];
- /* 描述:内部函数,处理数据的前面部分(>64字节的部分),每次组成一个64字节的block就进行杂凑处理;
- /* 参数:;
- /* [IN] ctx:算法的上下文,记录中间数据,结果等;
- /* [IN] msg:要进行计算的数据buffer;
- /* [IN] size:长度;
- /* 返回:void;
- /* 注意:;
- /* 示例:;
- /*
- /* 修改:;
- /* 日期:;
- /* 内容:;
- /************************************************************************/
- static void sha1_update(sha1_ctx *ctx,const unsigned char *buf, size_t size)
- {
- //为了让zen_sha1_update可以多次进入,长度可以累计;
- ctx->length_ += size;
- //每个处理的块都是64字节;
- while (size >= SHA1_BLOCK_SIZE)
- {
- sha1_process_block(ctx->hash_, reinterpret_cast<const uint32_t *>(buf));
- buf += SHA1_BLOCK_SIZE;
- size -= SHA1_BLOCK_SIZE;
- }
- ctx->unprocessed_ = size;
- }
- /************************************************************************/
- /* 函数:sha1_final[7/12/2016 IT];
- /* 描述:内部函数,处理数据的最后部分,添加0x80,补0,增加长度信息;
- /* 参数:;
- /* [IN] ctx:算法的上下文,记录中间数据,结果等;
- /* [IN] msg:要进行计算的数据buffer;
- /* [IN] result:返回的结果;
- /* 返回:void;
- /* 注意:;
- /* 示例:;
- /*
- /* 修改:;
- /* 日期:;
- /* 内容:;
- /************************************************************************/
- static void sha1_final(sha1_ctx *ctx, const unsigned char *msg,size_t size, unsigned char *result)
- {
- uint32_t message[SHA1_BLOCK_SIZE / 4];
- //保存剩余的数据,我们要拼出最后1个(或者两个)要处理的块,前面的算法保证了,最后一个块肯定小于64个字节;
- if (ctx->unprocessed_)
- {
- memcpy(message, msg + size - ctx->unprocessed_, static_cast<size_t>( ctx->unprocessed_));
- }
- //得到0x80要添加在的位置(在uint32_t 数组中);
- uint32_t index = ((uint32_t)ctx->length_ & 63) >> 2;
- uint32_t shift = ((uint32_t)ctx->length_ & 3) * 8;
- //添加0x80进去,并且把余下的空间补充0;
- message[index] &= ~(0xFFFFFFFF << shift);
- message[index++] ^= 0x80 << shift;
- //如果这个block还无法处理,其后面的长度无法容纳长度64bit,那么先处理这个block;
- if (index > 14)
- {
- while (index < 16)
- {
- message[index++] = 0;
- }
- sha1_process_block(ctx->hash_, message);
- index = 0;
- }
- //补0;
- while (index < 14)
- {
- message[index++] = 0;
- }
- // 保存长度,注意是bit位的长度,这个问题让我看着郁闷了半天;
- uint64_t data_len = (ctx->length_) << 3;
- //注意SHA1算法要求的64bit的长度是大头BIG-ENDIAN,在小头的世界要进行转换;
- #if BYTES_ORDER == LITTLE_ENDIAN
- data_len = SWAP_UINT64(data_len);
- #endif
- message[14] = (uint32_t) (data_len & 0x00000000FFFFFFFF);
- message[15] = (uint32_t) ((data_len & 0xFFFFFFFF00000000ULL) >> 32);
- sha1_process_block(ctx->hash_, message);
- // 注意结果是大头党的,在小头的世界要进行转换;
- #if BYTES_ORDER == LITTLE_ENDIAN
- swap_uint32_memcpy(result, &ctx->hash_, SHA1_HASH_SIZE);
- #else
- memcpy(result, &ctx->hash_, SHA1_HASH_SIZE);
- #endif
- }
- /************************************************************************/
- /* 函数:sha1[7/12/2016 IT];
- /* 描述:求内存块BUFFER的SHA1值;
- /* 参数:;
- /* [IN] msg:求SHA1的内存BUFFER指针;
- /* [OUT] size:BUFFER长度;
- /* [IN/OUT] result:结果;
- /* 返回:void;
- /* 注意:;
- /* 示例:;
- /*
- /* 修改:;
- /* 日期:;
- /* 内容:;
- /************************************************************************/
- unsigned char *sha1(const unsigned char *msg,size_t size,unsigned char result[SHA1_HASH_SIZE])
- {
- assert(result != NULL);
- sha1_ctx ctx;
- sha1_init(&ctx);
- sha1_update(&ctx, msg, size);
- sha1_final(&ctx, msg, size, result);
- return result;
- }
- /************************************************************************/
- /* 函数:sha1Hex[7/12/2016 IT];
- /* 描述:求内存块BUFFER的SHA1值的十六进制字符表示的字符串值;
- /* 参数:;
- /* [IN] msg:求SHA1的内存BUFFER指针;
- /* [OUT] size:BUFFER长度;
- /* [IN/OUT] szHexResult:十六进制字符结果;
- /* 返回:void;
- /* 注意:;
- /* 示例:;
- /*
- /* 修改:;
- /* 日期:;
- /* 内容:;
- /************************************************************************/
- unsigned char *sha1Hex(const unsigned char *msg, size_t size, unsigned char szHexResult[41])
- {
- assert(szHexResult != NULL);
- sha1_ctx ctx;
- unsigned char result[21] = {0};
- sha1_init(&ctx);
- sha1_update(&ctx, msg, size);
- sha1_final(&ctx, msg, size, result);
- ByteTrun2Hex(result, 20, szHexResult);
- return szHexResult;
- }
- #endif
|