# 2          SHA1和MD5的算法说明

SHA1和MD5的算法都是从MD4算法改进而来的2种算法，基本思路都是将信息分成N个分组，每组64个字节，每个分组都进行摘要运算。当一个分组的摘要运算完毕后，将上一个分组的结果也用于下一个分组的运算。

MD5最后生成的摘要信息是16个字节，SHA1是20个字节。

MD5和SHA1的分组信息运算，分组里面的的数据都会被视为16个DWORD，而MD5算法认为这些DWORD的字节序列是LITTLE-ENDIAN,而SHA1的算法认为DWORD是BIG-ENDIAN的。所以在不同字节序的主机上要进行转换。

61 62 63 80 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 18 00 00 00 00 00 00 00

61 62 63 80 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 18

31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36

37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32

33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38

39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34

35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30

80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 80 02 00 00 00 00 00 00

# 3          上源码

  1 #include <stdio.h>
2 #include <stdint.h>
3 #include <string.h>
4 #include <assert.h>
5
6 //字节序的小头和大头的问题
7 #define ZEN_LITTLE_ENDIAN  0x0123
8 #define ZEN_BIG_ENDIAN     0x3210
9
10 //目前所有的代码都是为了小头党服务的，不知道有生之年这套代码是否还会为大头党服务一次？
11 #ifndef ZEN_BYTES_ORDER
12 #define ZEN_BYTES_ORDER    ZEN_LITTLE_ENDIAN
13 #endif
14
15 #ifndef ZEN_SWAP_UINT16
16 #define ZEN_SWAP_UINT16(x)  ((((x) & 0xff00) >>  8) | (((x) & 0x00ff) <<  8))
17 #endif
18 #ifndef ZEN_SWAP_UINT32
19 #define ZEN_SWAP_UINT32(x)  ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >>  8) | \
20     (((x) & 0x0000ff00) <<  8) | (((x) & 0x000000ff) << 24))
21 #endif
22 #ifndef ZEN_SWAP_UINT64
23 #define ZEN_SWAP_UINT64(x)  ((((x) & 0xff00000000000000) >> 56) | (((x) & 0x00ff000000000000) >>  40) | \
24     (((x) & 0x0000ff0000000000) >> 24) | (((x) & 0x000000ff00000000) >>  8) | \
25     (((x) & 0x00000000ff000000) << 8 ) | (((x) & 0x0000000000ff0000) <<  24) | \
26     (((x) & 0x000000000000ff00) << 40 ) | (((x) & 0x00000000000000ff) <<  56))
27 #endif
28
29 //将一个（字符串）数组，拷贝到另外一个uint32_t数组，同时每个uint32_t反字节序
30 void *swap_uint32_memcpy(void *to, const void *from, size_t length)
31 {
32     memcpy(to, from, length);
33     size_t remain_len =  (4 - (length & 3)) & 3;
34
35     //数据不是4字节的倍数,补充0
36     if (remain_len)
37     {
38         for (size_t i = 0; i < remain_len; ++i)
39         {
40             *((char *)(to) + length + i) = 0;
41         }
42         //调整成4的倍数
43         length += remain_len;
44     }
45
46     //所有的数据反转
47     for (size_t i = 0; i < length / 4; ++i)
48     {
49         ((uint32_t *)to)[i] = ZEN_SWAP_UINT32(((uint32_t *)to)[i]);
50     }
51
53 }
54
55 ///MD5的结果数据长度
56 static const size_t ZEN_MD5_HASH_SIZE   = 16;
57 ///SHA1的结果数据长度
58 static const size_t ZEN_SHA1_HASH_SIZE  = 20;
59
60
61
62 namespace ZEN_LIB
63 {
64
65
66 /*!
67 @brief      求某个内存块的MD5，
68 @return     unsigned char* 返回的的结果，
69 @param[in]  buf    求MD5的内存BUFFER指针
70 @param[in]  size   BUFFER长度
71 @param[out] result 结果
72 */
73 unsigned char *md5(const unsigned char *buf,
74                    size_t size,
75                    unsigned char result[ZEN_MD5_HASH_SIZE]);
76
77
78 /*!
79 @brief      求内存块BUFFER的SHA1值
80 @return     unsigned char* 返回的的结果
81 @param[in]  buf    求SHA1的内存BUFFER指针
82 @param[in]  size   BUFFER长度
83 @param[out] result 结果
84 */
85 unsigned char *sha1(const unsigned char *buf,
86                     size_t size,
87                     unsigned char result[ZEN_SHA1_HASH_SIZE]);
88 };
89
90
91 //================================================================================================
92 //MD5的算法
93
94 //每次处理的BLOCK的大小
95 static const size_t ZEN_MD5_BLOCK_SIZE = 64;
96
97 //md5算法的上下文，保存一些状态，中间数据，结果
98 typedef struct md5_ctx
99 {
100     //处理的数据的长度
101     uint64_t length_;
102     //还没有处理的数据长度
103     uint64_t unprocessed_;
104     //取得的HASH结果（中间数据）
105     uint32_t  hash_[4];
106 } md5_ctx;
107
108
109 #define ROTL32(dword, n) ((dword) << (n) ^ ((dword) >> (32 - (n))))
110 #define ROTR32(dword, n) ((dword) >> (n) ^ ((dword) << (32 - (n))))
111 #define ROTL64(qword, n) ((qword) << (n) ^ ((qword) >> (64 - (n))))
112 #define ROTR64(qword, n) ((qword) >> (n) ^ ((qword) << (64 - (n))))
113
114
115 /*!
116 @brief      内部函数，初始化MD5的context，内容
117 @param      ctx
118 */
119 static void zen_md5_init(md5_ctx *ctx)
120 {
121     ctx->length_ = 0;
122     ctx->unprocessed_ = 0;
123
124     /* initialize state */
125     ctx->hash_[0] = 0x67452301;
126     ctx->hash_[1] = 0xefcdab89;
128     ctx->hash_[3] = 0x10325476;
129 }
130
131 /* First, define four auxiliary functions that each take as input
132  * three 32-bit words and returns a 32-bit word.*/
133
134 /* F(x,y,z) = ((y XOR z) AND x) XOR z - is faster then original version */
135 #define MD5_F(x, y, z) ((((y) ^ (z)) & (x)) ^ (z))
136 #define MD5_G(x, y, z) (((x) & (z)) | ((y) & (~z)))
137 #define MD5_H(x, y, z) ((x) ^ (y) ^ (z))
138 #define MD5_I(x, y, z) ((y) ^ ((x) | (~z)))
139
140 /* transformations for rounds 1, 2, 3, and 4. */
141 #define MD5_ROUND1(a, b, c, d, x, s, ac) { \
142         (a) += MD5_F((b), (c), (d)) + (x) + (ac); \
143         (a) = ROTL32((a), (s)); \
144         (a) += (b); \
145     }
146 #define MD5_ROUND2(a, b, c, d, x, s, ac) { \
147         (a) += MD5_G((b), (c), (d)) + (x) + (ac); \
148         (a) = ROTL32((a), (s)); \
149         (a) += (b); \
150     }
151 #define MD5_ROUND3(a, b, c, d, x, s, ac) { \
152         (a) += MD5_H((b), (c), (d)) + (x) + (ac); \
153         (a) = ROTL32((a), (s)); \
154         (a) += (b); \
155     }
156 #define MD5_ROUND4(a, b, c, d, x, s, ac) { \
157         (a) += MD5_I((b), (c), (d)) + (x) + (ac); \
158         (a) = ROTL32((a), (s)); \
159         (a) += (b); \
160     }
161
162
163 /*!
164 @brief      内部函数，将64个字节，16个uint32_t的数组进行摘要（杂凑）处理，处理的数据自己序是小头数据
165 @param      state 存放处理的hash数据结果
166 @param      block 要处理的block，64个字节，16个uint32_t的数组
167 */
168 static void zen_md5_process_block(uint32_t state[4], const uint32_t block[ZEN_MD5_BLOCK_SIZE / 4])
169 {
170     register unsigned a, b, c, d;
171     a = state[0];
172     b = state[1];
173     c = state[2];
174     d = state[3];
175
176     const uint32_t *x = NULL;
177
178     //MD5里面计算的数据都是小头数据.大头党的数据要处理
179 #if ZEN_BYTES_ORDER == ZEN_LITTLE_ENDIAN
180     x = block;
181 #else
182     uint32_t swap_block[ZEN_MD5_BLOCK_SIZE / 4];
183     swap_uint32_memcpy(swap_block, block, 64);
184     x = swap_block;
185 #endif
186
187
188     MD5_ROUND1(a, b, c, d, x[ 0],  7, 0xd76aa478);
189     MD5_ROUND1(d, a, b, c, x[ 1], 12, 0xe8c7b756);
190     MD5_ROUND1(c, d, a, b, x[ 2], 17, 0x242070db);
191     MD5_ROUND1(b, c, d, a, x[ 3], 22, 0xc1bdceee);
192     MD5_ROUND1(a, b, c, d, x[ 4],  7, 0xf57c0faf);
193     MD5_ROUND1(d, a, b, c, x[ 5], 12, 0x4787c62a);
194     MD5_ROUND1(c, d, a, b, x[ 6], 17, 0xa8304613);
195     MD5_ROUND1(b, c, d, a, x[ 7], 22, 0xfd469501);
196     MD5_ROUND1(a, b, c, d, x[ 8],  7, 0x698098d8);
197     MD5_ROUND1(d, a, b, c, x[ 9], 12, 0x8b44f7af);
198     MD5_ROUND1(c, d, a, b, x[10], 17, 0xffff5bb1);
199     MD5_ROUND1(b, c, d, a, x[11], 22, 0x895cd7be);
200     MD5_ROUND1(a, b, c, d, x[12],  7, 0x6b901122);
201     MD5_ROUND1(d, a, b, c, x[13], 12, 0xfd987193);
202     MD5_ROUND1(c, d, a, b, x[14], 17, 0xa679438e);
203     MD5_ROUND1(b, c, d, a, x[15], 22, 0x49b40821);
204
205     MD5_ROUND2(a, b, c, d, x[ 1],  5, 0xf61e2562);
206     MD5_ROUND2(d, a, b, c, x[ 6],  9, 0xc040b340);
207     MD5_ROUND2(c, d, a, b, x[11], 14, 0x265e5a51);
208     MD5_ROUND2(b, c, d, a, x[ 0], 20, 0xe9b6c7aa);
209     MD5_ROUND2(a, b, c, d, x[ 5],  5, 0xd62f105d);
210     MD5_ROUND2(d, a, b, c, x[10],  9,  0x2441453);
211     MD5_ROUND2(c, d, a, b, x[15], 14, 0xd8a1e681);
212     MD5_ROUND2(b, c, d, a, x[ 4], 20, 0xe7d3fbc8);
213     MD5_ROUND2(a, b, c, d, x[ 9],  5, 0x21e1cde6);
214     MD5_ROUND2(d, a, b, c, x[14],  9, 0xc33707d6);
215     MD5_ROUND2(c, d, a, b, x[ 3], 14, 0xf4d50d87);
216     MD5_ROUND2(b, c, d, a, x[ 8], 20, 0x455a14ed);
217     MD5_ROUND2(a, b, c, d, x[13],  5, 0xa9e3e905);
218     MD5_ROUND2(d, a, b, c, x[ 2],  9, 0xfcefa3f8);
219     MD5_ROUND2(c, d, a, b, x[ 7], 14, 0x676f02d9);
220     MD5_ROUND2(b, c, d, a, x[12], 20, 0x8d2a4c8a);
221
222     MD5_ROUND3(a, b, c, d, x[ 5],  4, 0xfffa3942);
223     MD5_ROUND3(d, a, b, c, x[ 8], 11, 0x8771f681);
224     MD5_ROUND3(c, d, a, b, x[11], 16, 0x6d9d6122);
225     MD5_ROUND3(b, c, d, a, x[14], 23, 0xfde5380c);
226     MD5_ROUND3(a, b, c, d, x[ 1],  4, 0xa4beea44);
227     MD5_ROUND3(d, a, b, c, x[ 4], 11, 0x4bdecfa9);
228     MD5_ROUND3(c, d, a, b, x[ 7], 16, 0xf6bb4b60);
229     MD5_ROUND3(b, c, d, a, x[10], 23, 0xbebfbc70);
230     MD5_ROUND3(a, b, c, d, x[13],  4, 0x289b7ec6);
231     MD5_ROUND3(d, a, b, c, x[ 0], 11, 0xeaa127fa);
232     MD5_ROUND3(c, d, a, b, x[ 3], 16, 0xd4ef3085);
233     MD5_ROUND3(b, c, d, a, x[ 6], 23,  0x4881d05);
234     MD5_ROUND3(a, b, c, d, x[ 9],  4, 0xd9d4d039);
235     MD5_ROUND3(d, a, b, c, x[12], 11, 0xe6db99e5);
236     MD5_ROUND3(c, d, a, b, x[15], 16, 0x1fa27cf8);
237     MD5_ROUND3(b, c, d, a, x[ 2], 23, 0xc4ac5665);
238
239     MD5_ROUND4(a, b, c, d, x[ 0],  6, 0xf4292244);
240     MD5_ROUND4(d, a, b, c, x[ 7], 10, 0x432aff97);
241     MD5_ROUND4(c, d, a, b, x[14], 15, 0xab9423a7);
242     MD5_ROUND4(b, c, d, a, x[ 5], 21, 0xfc93a039);
243     MD5_ROUND4(a, b, c, d, x[12],  6, 0x655b59c3);
244     MD5_ROUND4(d, a, b, c, x[ 3], 10, 0x8f0ccc92);
245     MD5_ROUND4(c, d, a, b, x[10], 15, 0xffeff47d);
246     MD5_ROUND4(b, c, d, a, x[ 1], 21, 0x85845dd1);
247     MD5_ROUND4(a, b, c, d, x[ 8],  6, 0x6fa87e4f);
248     MD5_ROUND4(d, a, b, c, x[15], 10, 0xfe2ce6e0);
249     MD5_ROUND4(c, d, a, b, x[ 6], 15, 0xa3014314);
250     MD5_ROUND4(b, c, d, a, x[13], 21, 0x4e0811a1);
251     MD5_ROUND4(a, b, c, d, x[ 4],  6, 0xf7537e82);
252     MD5_ROUND4(d, a, b, c, x[11], 10, 0xbd3af235);
253     MD5_ROUND4(c, d, a, b, x[ 2], 15, 0x2ad7d2bb);
254     MD5_ROUND4(b, c, d, a, x[ 9], 21, 0xeb86d391);
255
256     state[0] += a;
257     state[1] += b;
258     state[2] += c;
259     state[3] += d;
260 }
261
262
263 /*!
264 @brief      内部函数，处理数据的前面部分(>64字节的部分)，每次组成一个64字节的block就进行杂凑处理
265 @param[out] ctx  算法的context，用于记录一些处理的上下文和结果
266 @param[in]  buf  处理的数据，
267 @param[in]  size 处理的数据长度
268 */
269 static void zen_md5_update(md5_ctx *ctx, const unsigned char *buf, size_t size)
270 {
271     //为什么不是=，因为在某些环境下，可以多次调用zen_md5_update，但这种情况，必须保证前面的调用，每次都没有unprocessed_
272     ctx->length_ += size;
273
274     //每个处理的块都是64字节
275     while (size >= ZEN_MD5_BLOCK_SIZE)
276     {
277         zen_md5_process_block(ctx->hash_, reinterpret_cast<const uint32_t *>(buf));
278         buf  += ZEN_MD5_BLOCK_SIZE;
279         size -= ZEN_MD5_BLOCK_SIZE;
280     }
281
282     ctx->unprocessed_ = size;
283 }
284
285
286 /*!
287 @brief      内部函数，处理数据的末尾部分，我们要拼出最后1个（或者两个）要处理的BLOCK，加上0x80，加上长度进行处理
288 @param[in]  ctx    算法的context，用于记录一些处理的上下文和结果
289 @param[in]  buf    处理的数据
290 @param[in]  size   处理buffer的长度
291 @param[out] result 返回的结果，
292 */
293 static void zen_md5_final(md5_ctx *ctx, const unsigned char *buf, size_t size, unsigned char *result)
294 {
295     uint32_t message[ZEN_MD5_BLOCK_SIZE / 4];
296
297     //保存剩余的数据，我们要拼出最后1个（或者两个）要处理的块，前面的算法保证了，最后一个块肯定小于64个字节
298     if (ctx->unprocessed_)
299     {
300         memcpy(message, buf + size - ctx->unprocessed_, static_cast<size_t>( ctx->unprocessed_));
301     }
302
303     //得到0x80要添加在的位置（在uint32_t 数组中），
304     uint32_t index = ((uint32_t)ctx->length_ & 63) >> 2;
305     uint32_t shift = ((uint32_t)ctx->length_ & 3) * 8;
306
307     //添加0x80进去，并且把余下的空间补充0
308     message[index]   &= ~(0xFFFFFFFF << shift);
309     message[index++] ^= 0x80 << shift;
310
311     //如果这个block还无法处理，其后面的长度无法容纳长度64bit，那么先处理这个block
312     if (index > 14)
313     {
314         while (index < 16)
315         {
316             message[index++] = 0;
317         }
318
319         zen_md5_process_block(ctx->hash_, message);
320         index = 0;
321     }
322
323     //补0
324     while (index < 14)
325     {
326         message[index++] = 0;
327     }
328
329     //保存长度，注意是bit位的长度,这个问题让我看着郁闷了半天，
330     uint64_t data_len = (ctx->length_) << 3;
331
332     //注意MD5算法要求的64bit的长度是小头LITTLE-ENDIAN编码，注意下面的比较是!=
333 #if ZEN_BYTES_ORDER != ZEN_LITTLE_ENDIAN
334     data_len = ZEN_SWAP_UINT64(data_len);
335 #endif
336
337     message[14] = (uint32_t) (data_len & 0x00000000FFFFFFFF);
338     message[15] = (uint32_t) ((data_len & 0xFFFFFFFF00000000ULL) >> 32);
339
340     zen_md5_process_block(ctx->hash_, message);
341
342     //注意结果是小头党的，在大头的世界要进行转换
343 #if ZEN_BYTES_ORDER == ZEN_LITTLE_ENDIAN
344     memcpy(result, &ctx->hash_, ZEN_MD5_HASH_SIZE);
345 #else
346     swap_uint32_memcpy(result, &ctx->hash_, ZEN_MD5_HASH_SIZE);
347 #endif
348
349 }
350
351
352 //计算一个内存数据的MD5值
353 unsigned char *ZEN_LIB::md5(const unsigned char *buf,
354                             size_t size,
355                             unsigned char result[ZEN_MD5_HASH_SIZE])
356 {
357     assert(result != NULL);
358
359     md5_ctx ctx;
360     zen_md5_init(&ctx);
361     zen_md5_update(&ctx, buf, size);
362     zen_md5_final(&ctx, buf, size, result);
363     return result;
364 }
365
366
367
368
369 //================================================================================================
370 //SHA1的算法
371
372 //每次处理的BLOCK的大小
373 static const size_t ZEN_SHA1_BLOCK_SIZE = 64;
374
375 //SHA1算法的上下文，保存一些状态，中间数据，结果
376 typedef struct sha1_ctx
377 {
378
379     //处理的数据的长度
380     uint64_t length_;
381     //还没有处理的数据长度
382     uint64_t unprocessed_;
383     /* 160-bit algorithm internal hashing state */
384     uint32_t hash_[5];
385 } sha1_ctx;
386
387 //内部函数，SHA1算法的上下文的初始化
388 static void zen_sha1_init(sha1_ctx *ctx)
389 {
390     ctx->length_ = 0;
391     ctx->unprocessed_ = 0;
392     // 初始化算法的几个常量，魔术数
393     ctx->hash_[0] = 0x67452301;
394     ctx->hash_[1] = 0xefcdab89;
396     ctx->hash_[3] = 0x10325476;
397     ctx->hash_[4] = 0xc3d2e1f0;
398 }
399
400
401 /*!
402 @brief      内部函数，对一个64bit内存块进行摘要(杂凑)处理，
403 @param      hash  存放计算hash结果的的数组
404 @param      block 要计算的处理得内存块
405 */
406 static void zen_sha1_process_block(uint32_t hash[5],
407                                    const uint32_t block[ZEN_SHA1_BLOCK_SIZE / 4])
408 {
409     size_t        t;
410     uint32_t      wblock[80];
411     register uint32_t      a, b, c, d, e, temp;
412
413     //SHA1算法处理的内部数据要求是大头党的，在小头的环境转换
414 #if ZEN_BYTES_ORDER == ZEN_LITTLE_ENDIAN
415     swap_uint32_memcpy(wblock, block, ZEN_SHA1_BLOCK_SIZE);
416 #else
417     ::memcpy(wblock, block, ZEN_SHA1_BLOCK_SIZE);
418 #endif
419
420     //处理
421     for (t = 16; t < 80; t++)
422     {
423         wblock[t] = ROTL32(wblock[t - 3] ^ wblock[t - 8] ^ wblock[t - 14] ^ wblock[t - 16], 1);
424     }
425
426     a = hash[0];
427     b = hash[1];
428     c = hash[2];
429     d = hash[3];
430     e = hash[4];
431
432     for (t = 0; t < 20; t++)
433     {
434         /* the following is faster than ((B & C) | ((~B) & D)) */
435         temp =  ROTL32(a, 5) + (((c ^ d) & b) ^ d)
436                 + e + wblock[t] + 0x5A827999;
437         e = d;
438         d = c;
439         c = ROTL32(b, 30);
440         b = a;
441         a = temp;
442     }
443
444     for (t = 20; t < 40; t++)
445     {
446         temp = ROTL32(a, 5) + (b ^ c ^ d) + e + wblock[t] + 0x6ED9EBA1;
447         e = d;
448         d = c;
449         c = ROTL32(b, 30);
450         b = a;
451         a = temp;
452     }
453
454     for (t = 40; t < 60; t++)
455     {
456         temp = ROTL32(a, 5) + ((b & c) | (b & d) | (c & d))
457                + e + wblock[t] + 0x8F1BBCDC;
458         e = d;
459         d = c;
460         c = ROTL32(b, 30);
461         b = a;
462         a = temp;
463     }
464
465     for (t = 60; t < 80; t++)
466     {
467         temp = ROTL32(a, 5) + (b ^ c ^ d) + e + wblock[t] + 0xCA62C1D6;
468         e = d;
469         d = c;
470         c = ROTL32(b, 30);
471         b = a;
472         a = temp;
473     }
474
475     hash[0] += a;
476     hash[1] += b;
477     hash[2] += c;
478     hash[3] += d;
479     hash[4] += e;
480 }
481
482
483 /*!
484 @brief      内部函数，处理数据的前面部分(>64字节的部分)，每次组成一个64字节的block就进行杂凑处理
485 @param      ctx  算法的上下文，记录中间数据，结果等
486 @param      msg  要进行计算的数据buffer
487 @param      size 长度
488 */
489 static void zen_sha1_update(sha1_ctx *ctx,
490                             const unsigned char *buf,
491                             size_t size)
492 {
493     //为了让zen_sha1_update可以多次进入，长度可以累计
494     ctx->length_ += size;
495
496     //每个处理的块都是64字节
497     while (size >= ZEN_SHA1_BLOCK_SIZE)
498     {
499         zen_sha1_process_block(ctx->hash_, reinterpret_cast<const uint32_t *>(buf));
500         buf  += ZEN_SHA1_BLOCK_SIZE;
501         size -= ZEN_SHA1_BLOCK_SIZE;
502     }
503
504     ctx->unprocessed_ = size;
505 }
506
507
508 /*!
509 @brief      内部函数，处理数据的最后部分，添加0x80,补0，增加长度信息
510 @param      ctx    算法的上下文，记录中间数据，结果等
511 @param      msg    要进行计算的数据buffer
512 @param      result 返回的结果
513 */
514 static void zen_sha1_final(sha1_ctx *ctx,
515                            const unsigned char *msg,
516                            size_t size,
517                            unsigned char *result)
518 {
519
520     uint32_t message[ZEN_SHA1_BLOCK_SIZE / 4];
521
522     //保存剩余的数据，我们要拼出最后1个（或者两个）要处理的块，前面的算法保证了，最后一个块肯定小于64个字节
523     if (ctx->unprocessed_)
524     {
525         memcpy(message, msg + size - ctx->unprocessed_, static_cast<size_t>( ctx->unprocessed_));
526     }
527
528     //得到0x80要添加在的位置（在uint32_t 数组中），
529     uint32_t index = ((uint32_t)ctx->length_ & 63) >> 2;
530     uint32_t shift = ((uint32_t)ctx->length_ & 3) * 8;
531
532     //添加0x80进去，并且把余下的空间补充0
533     message[index]   &= ~(0xFFFFFFFF << shift);
534     message[index++] ^= 0x80 << shift;
535
536     //如果这个block还无法处理，其后面的长度无法容纳长度64bit，那么先处理这个block
537     if (index > 14)
538     {
539         while (index < 16)
540         {
541             message[index++] = 0;
542         }
543
544         zen_sha1_process_block(ctx->hash_, message);
545         index = 0;
546     }
547
548     //补0
549     while (index < 14)
550     {
551         message[index++] = 0;
552     }
553
554     //保存长度，注意是bit位的长度,这个问题让我看着郁闷了半天，
555     uint64_t data_len = (ctx->length_) << 3;
556
557     //注意SHA1算法要求的64bit的长度是大头BIG-ENDIAN，在小头的世界要进行转换
558 #if ZEN_BYTES_ORDER == ZEN_LITTLE_ENDIAN
559     data_len = ZEN_SWAP_UINT64(data_len);
560 #endif
561
562     message[14] = (uint32_t) (data_len & 0x00000000FFFFFFFF);
563     message[15] = (uint32_t) ((data_len & 0xFFFFFFFF00000000ULL) >> 32);
564
565     zen_sha1_process_block(ctx->hash_, message);
566
567     //注意结果是大头党的，在小头的世界要进行转换
568 #if ZEN_BYTES_ORDER == ZEN_LITTLE_ENDIAN
569     swap_uint32_memcpy(result, &ctx->hash_, ZEN_SHA1_HASH_SIZE);
570 #else
571     memcpy(result, &ctx->hash_, ZEN_SHA1_HASH_SIZE);
572 #endif
573 }
574
575
576
577 //计算一个内存数据的SHA1值
578 unsigned char *ZEN_LIB::sha1(const unsigned char *msg,
579                              size_t size,
580                              unsigned char result[ZEN_SHA1_HASH_SIZE])
581 {
582     assert(result != NULL);
583
584     sha1_ctx ctx;
585     zen_sha1_init(&ctx);
586     zen_sha1_update(&ctx, msg, size);
587     zen_sha1_final(&ctx, msg, size, result);
588     return result;
589 }
590
591 int main(int /*argc*/, char * /*argv*/[])
592 {
593
594     int ret = 0;
595     static unsigned char test_buf[7][81] =
596     {
597         { "" },
598         { "a" },
599         { "abc" },
600         { "message digest" },
601         { "abcdefghijklmnopqrstuvwxyz" },
602         { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
603         { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" }
604     };
605
606     static const size_t test_buflen[7] =
607     {
608         0, 1, 3, 14, 26, 62, 80
609     };
610
611     static const unsigned char md5_test_sum[7][16] =
612     {
613         { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,  0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E },
614         { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8,  0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 },
615         { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0,  0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 },
616         { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D,  0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 },
617         { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00,  0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B },
618         { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5,  0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F },
619         { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55,  0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A }
620     };
621     unsigned char result[32] ={0};
622
623     for(size_t i=0;i<7;++i)
624     {
625         ZEN_LIB::md5(test_buf[i],test_buflen[i],result);
626         ret = memcmp(result,md5_test_sum[i],16);
627         if (ret != 0)
628         {
629             assert(false);
630         }
631     }
632
633     static const unsigned char sha1_test_sum[7][20] =
634     {
635         { 0xda,0x39,0xa3,0xee,0x5e,0x6b,0x4b,0x0d,0x32,0x55,0xbf,0xef,0x95,0x60,0x18,0x90,0xaf,0xd8,0x07,0x09 },
636         { 0x86,0xf7,0xe4,0x37,0xfa,0xa5,0xa7,0xfc,0xe1,0x5d,0x1d,0xdc,0xb9,0xea,0xea,0xea,0x37,0x76,0x67,0xb8 },
637         { 0xa9,0x99,0x3e,0x36,0x47,0x06,0x81,0x6a,0xba,0x3e,0x25,0x71,0x78,0x50,0xc2,0x6c,0x9c,0xd0,0xd8,0x9d },
638         { 0xc1,0x22,0x52,0xce,0xda,0x8b,0xe8,0x99,0x4d,0x5f,0xa0,0x29,0x0a,0x47,0x23,0x1c,0x1d,0x16,0xaa,0xe3 },
639         { 0x32,0xd1,0x0c,0x7b,0x8c,0xf9,0x65,0x70,0xca,0x04,0xce,0x37,0xf2,0xa1,0x9d,0x84,0x24,0x0d,0x3a,0x89 },
640         { 0x76,0x1c,0x45,0x7b,0xf7,0x3b,0x14,0xd2,0x7e,0x9e,0x92,0x65,0xc4,0x6f,0x4b,0x4d,0xda,0x11,0xf9,0x40 },
641         { 0x50,0xab,0xf5,0x70,0x6a,0x15,0x09,0x90,0xa0,0x8b,0x2c,0x5e,0xa4,0x0f,0xa0,0xe5,0x85,0x55,0x47,0x32 },
642     };
643     for(size_t i=0;i<7;++i)
644     {
645         ZEN_LIB::sha1(test_buf[i],test_buflen[i],result);
646         ret = memcmp(result,sha1_test_sum[i],20);
647         if (ret != 0)
648         {
649             assert(false);
650         }
651     }
652     return 0;
653 }

rhashlib采用的协议是MIT，在此再次感谢原来的作者，另外维基上面的伪代码帮助非常大。

【本文作者是雁渡寒潭，本着自由的精神，你可以在无盈利的情况完整转载此文 档，转载时请附上BLOG链接:http://www.cnblogs.com/fullsail/，否则每字一元，每图一百不讲价。对Baidu文库和360doc加价一倍】

posted @ 2013-02-22 03:12 fullsail 阅读(...) 评论(...) 编辑 收藏