SHA-512的完整实现我总结下来,总共分三步,一是填充补充位和长度;二是初始化8个变量;三是循环计算这8个变量最终输出.
1. 填充位和长度信息
整个需要SHA-512的消息块必须是1024位的整数倍,需要补足还要有真实的长度信息.所以消息长度模896,有余数补充一个1和N个0组成;最后加上128位里表示消息的真实长度.这个处理也可以在处理最后一块1024的时候来处理.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30int SHA512_Final(unsigned char *md, SHA512_CTX *c) {
// 省略...
// 在需要填充的部分先填充一个0x80
// #define SHA512_PADDING_PATTERN 0x80
// #define HASH_PADDING_PATTERN SHA512_PADDING_PATTERN
c->last.buf[c->last.used] = HASH_PADDING_PATTERN;
c->last.used++;
// 余下的部分全部填0
// #define SHA512_BLOCK_SIZE 128 /* 1024 bits = 128 bytes */
// #define HASH_BLOCK_SIZE SHA512_BLOCK_SIZE
// #define SHA512_LEN_SIZE 16 /* 128 bits = 16 bytes */
// #define HASH_LEN_SIZE SHA512_LEN_SIZE
memset(&c->last.buf[c->last.used], 0,
HASH_BLOCK_SIZE - HASH_LEN_SIZE - c->last.used);
// 在把真实长度补上
// #define SHA512_LEN_OFFSET (SHA512_BLOCK_SIZE - SHA512_LEN_SIZE)
// SHA512_SaveTotal(&c->last.buf[HASH_LEN_OFFSET], &c->total);
temp = (uint64_t *)&(c->last.buf[HASH_LEN_OFFSET]);
temp[0] = htobe64(c->total.high);
temp[1] = htobe64(c->total.low);
SHA512_ProcessBlock(c, &c->last.buf);
// 省略...
}
2. 初始化8个变量
自然数前8个素数开平方根,取小数部分的前64位.
计算开平方根,平方根的计算这篇文章讲的非常好.
1 | int SHA512_Init(SHA512_CTX *c) { |
3. 单组1024位摘要信息计算
单轮函数的计算公式参考SHA-512算法2-轮函数计算
1 | int SHA512_ProcessBlock(SHA512_CTX *ctx, const void *block) { |
4. 总的计算过程
1 | int SHA512_Update(SHA512_CTX *c, const void *data, size_t len) { |
代码详情:https://gitee.com/korra/lib3rd.git
git checkout sha512分支。或者 点击下载
结果比对工具:https://1024tools.com/hash