OpenSSL入门-杂凑函数

SM3

实现:

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
30
31
32
33
34
35
36
37
38
39
40
#include <stdio.h>
#include <string.h>
#include "openssl/evp.h"
int sm3_hash(const unsigned char* message, size_t len, unsigned char* hash, unsigned int* hash_len) {
EVP_MD_CTX* md_ctx;
const EVP_MD* md;
md = EVP_sm3();
md_ctx = EVP_MD_CTX_new();
EVP_DigestInit_ex(md_ctx, md, NULL);
EVP_DigestUpdate(md_ctx, message, len);
EVP_DigestFinal_ex(md_ctx, hash, hash_len);
EVP_MD_CTX_free(md_ctx);
return 0;
}
int main(void) {
const unsigned char sample1[] = { 'a', 'b', 'c', 0 };
unsigned int sample1_len = strlen((char*)sample1);
const unsigned char sample2[] = { 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64,0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64,0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64,0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64,0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64,0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64,0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64,0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64 };
unsigned int sample2_len = sizeof(sample2);
unsigned char hash_value[64];
unsigned int i, hash_len;
sm3_hash(sample1, sample1_len, hash_value, &hash_len);
printf("raw data: %s\n", sample1);
printf("hash length: %d bytes.\n", hash_len);
printf("hash value:\n");
for (i = 0; i < hash_len; i++)
printf("0x%x ", hash_value[i]);
printf("\n\n");
sm3_hash(sample2, sample2_len, hash_value, &hash_len);
printf("raw data:\n");
for (i = 0; i < sample2_len; i++)
printf("0x%x ", sample2[i]);
printf("\n");
printf("hash length: %d bytes.\n", hash_len);
printf("hash value:\n");
for (i = 0; i < hash_len; i++)
printf("0x%x ", hash_value[i]);
printf("\n");
return 0;
}

C语言版:

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#include <stdio.h>
#include <memory>
unsigned char IV[256 / 8] = { 0x73,0x80,0x16,0x6f,0x49,0x14,0xb2,0xb9,0x17,0x24,0x42,0xd7,0xda,0x8a,0x06,0x00,0xa9,0x6f,0x30,0xbc,0x16,0x31,0x38,0xaa,0xe3,0x8d,0xee,0x4d,0xb0,0xfb,0x0e,0x4e };
// 循环左移
unsigned long SL(unsigned long X, int n){
unsigned __int64 x = X;
x = x << (n % 32);
unsigned long l = (unsigned long)(x >> 32);
return x | l;
}
unsigned long Tj(int j){
if (j <= 15)
return 0x79cc4519;
else
return 0x7a879d8a;
}
unsigned long FFj(int j, unsigned long X, unsigned long Y, unsigned long Z){
if (j <= 15)
return X ^ Y ^ Z;
else
return (X & Y) | (X & Z) | (Y & Z);
}
unsigned long GGj(int j, unsigned long X, unsigned long Y, unsigned long Z){
if (j <= 15)
return X ^ Y ^ Z;
else
return (X & Y) | (~X & Z);
}
unsigned long P0(unsigned long X){
return X ^ SL(X, 9) ^ SL(X, 17);
}
unsigned long P1(unsigned long X){
return X ^ SL(X, 15) ^ SL(X, 23);
}
// 扩展
void EB(unsigned char Bi[512 / 8], unsigned long W[68], unsigned long W1[64]){
// Bi 分为W0~W15
for (int i = 0; i < 16; ++i)
W[i] = Bi[i * 4] << 24 | Bi[i * 4 + 1] << 16 | Bi[i * 4 + 2] << 8 | Bi[i * 4 + 3];
for (int j = 16; j <= 67; ++j)
W[j] = P1(W[j - 16] ^ W[j - 9] ^ SL(W[j - 3], 15)) ^ SL(W[j - 13], 7) ^ W[j - 6];
for (int j = 0; j <= 63; ++j)
W1[j] = W[j] ^ W[j + 4];
}
// 压缩函数
void CF(unsigned char Vi[256 / 8], unsigned char Bi[512 / 8], unsigned char Vi1[256 / 8]){
// Bi 扩展为132个字
unsigned long W[68] = { 0 };
unsigned long W1[64] = { 0 };
EB(Bi, W, W1);
// 串联 ABCDEFGH = Vi
unsigned long R[8] = { 0 };
for (int i = 0; i < 8; ++i)
R[i] = ((unsigned long)Vi[i * 4]) << 24 | ((unsigned long)Vi[i * 4 + 1]) << 16 | ((unsigned long)Vi[i * 4 + 2]) << 8 | ((unsigned long)Vi[i * 4 + 3]);
unsigned long A = R[0], B = R[1], C = R[2], D = R[3], E = R[4], F = R[5], G = R[6], H = R[7];
unsigned long SS1, SS2, TT1, TT2;
for (int j = 0; j <= 63; ++j){
SS1 = SL(SL(A, 12) + E + SL(Tj(j), j), 7);
SS2 = SS1 ^ SL(A, 12);
TT1 = FFj(j, A, B, C) + D + SS2 + W1[j];
TT2 = GGj(j, E, F, G) + H + SS1 + W[j];
D = C;
C = SL(B, 9);
B = A;
A = TT1;
H = G;
G = SL(F, 19);
F = E;
E = P0(TT2);
}
// Vi1 = ABCDEFGH 串联
R[0] = A, R[1] = B, R[2] = C, R[3] = D, R[4] = E, R[5] = F, R[6] = G, R[7] = H;
for (int i = 0; i < 8; ++i){
Vi1[i * 4] = (R[i] >> 24) & 0xFF;
Vi1[i * 4 + 1] = (R[i] >> 16) & 0xFF;
Vi1[i * 4 + 2] = (R[i] >> 8) & 0xFF;
Vi1[i * 4 + 3] = (R[i]) & 0xFF;
}
// Vi1 = ABCDEFGH ^ Vi
for (int i = 0; i < 256 / 8; ++i)
Vi1[i] ^= Vi[i];
}
//参数 m 是原始数据,ml 是数据长度,r 是输出参数,存放hash结果
void SM3Hash(unsigned char* m, int ml, unsigned char r[32]){
int l = ml * 8;
int k = 448 - 1 - l % 512;// 添加k个0,k 是满足 l + 1 + k ≡ 448mod512 的最小的非负整数
if (k <= 0)
k += 512;
int n = (l + k + 65) / 512;
int m1l = n * 512 / 8; // 填充后的长度,512位的倍数
unsigned char* m1 = new unsigned char[m1l];
memset(m1, 0, m1l);
memcpy(m1, m, l / 8);
m1[l / 8] = 0x80; // 消息后补1
// 再添加一个64位比特串,该比特串是长度l的二进制表示
unsigned long l1 = l;
for (int i = 0; i < 64 / 8 && l1 > 0; ++i){
m1[m1l - 1 - i] = l1 & 0xFF;
l1 = l1 >> 8;
}
//将填充后的消息m′按512比特进行分组:m′ = B(0)B(1)· · · B(n−1),其中n=(l+k+65)/512。
unsigned char** B = new unsigned char* [n];
for (int i = 0; i < n; ++i){
B[i] = new unsigned char[512 / 8];
memcpy(B[i], m1 + (512 / 8) * i, 512 / 8);
}
delete[] m1;
unsigned char** V = new unsigned char* [n + 1];
for (int i = 0; i <= n; ++i){
V[i] = new unsigned char[256 / 8];
memset(V[i], 0, 256 / 8);
}
// 初始化 V0 = VI
memcpy(V[0], IV, 256 / 8);
// 压缩函数,V 与扩展的B
for (int i = 0; i < n; ++i)
CF(V[i], B[i], V[i + 1]);
for (int i = 0; i < n; ++i)
delete[] B[i];
delete[] B;
// V[n]是结果
memcpy(r, V[n], 32);
for (int i = 0; i < n + 1; ++i)
delete[] V[i];
delete[] V;
}
void dumpbuf(unsigned char* buf, int len){
int i, line = 32;
printf("len=%d\n", len);
for (i = 0; i < len; i++) {
printf("%02x ", buf[i]);
if (i > 0 && (1 + i) % 16 == 0)
putchar('\n');
}
return;
}
void main(){
unsigned char data[] = "abc", r[32];
printf("消息:%s\nHash结果:\n", data);
SM3Hash(data, 3, r);
dumpbuf(r, 32);
}

SHA256

实现:

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#include <stdio.h>
#include <memory.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#define SHA256_BLOCK_SIZE 32 // SHA256 outputs a 32 byte digest
typedef unsigned char BYTE; // 8-bit byte
typedef unsigned int WORD; // 32-bit word, change to "long" for 16-bit machines
typedef struct {
BYTE data[64]; // current 512-bit chunk of message data, just like a buffer
WORD datalen; // sign the data length of current chunk
unsigned long long bitlen; // the bit length of the total message
WORD state[8]; // store the middle state of hash abstract
} SHA256_CTX;
void sha256_init(SHA256_CTX* ctx);
void sha256_update(SHA256_CTX* ctx, const BYTE data[], size_t len);
void sha256_final(SHA256_CTX* ctx, BYTE hash[]);
#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))
static const WORD 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
};
void sha256_transform(SHA256_CTX* ctx, const BYTE data[]){
WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64];
// initialization
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 = ctx->state[0];
b = ctx->state[1];
c = ctx->state[2];
d = ctx->state[3];
e = ctx->state[4];
f = ctx->state[5];
g = ctx->state[6];
h = ctx->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;
}
ctx->state[0] += a;
ctx->state[1] += b;
ctx->state[2] += c;
ctx->state[3] += d;
ctx->state[4] += e;
ctx->state[5] += f;
ctx->state[6] += g;
ctx->state[7] += h;
}
void sha256_init(SHA256_CTX* ctx){
ctx->datalen = 0;
ctx->bitlen = 0;
ctx->state[0] = 0x6a09e667;
ctx->state[1] = 0xbb67ae85;
ctx->state[2] = 0x3c6ef372;
ctx->state[3] = 0xa54ff53a;
ctx->state[4] = 0x510e527f;
ctx->state[5] = 0x9b05688c;
ctx->state[6] = 0x1f83d9ab;
ctx->state[7] = 0x5be0cd19;
}
void sha256_update(SHA256_CTX* ctx, const BYTE data[], size_t len){
WORD i;
for (i = 0; i < len; ++i) {
ctx->data[ctx->datalen] = data[i];
ctx->datalen++;
if (ctx->datalen == 64) {
// 64 byte = 512 bit means the buffer ctx->data has fully stored one chunk of message
// so do the sha256 hash map for the current chunk
sha256_transform(ctx, ctx->data);
ctx->bitlen += 512;
ctx->datalen = 0;
}
}
}
void sha256_final(SHA256_CTX* ctx, BYTE hash[]){
WORD i;
i = ctx->datalen;
// Pad whatever data is left in the buffer.
if (ctx->datalen < 56) {
ctx->data[i++] = 0x80; // pad 10000000 = 0x80
while (i < 56)
ctx->data[i++] = 0x00;
}
else {
ctx->data[i++] = 0x80;
while (i < 64)
ctx->data[i++] = 0x00;
sha256_transform(ctx, ctx->data);
memset(ctx->data, 0, 56);
}
// Append to the padding the total message's length in bits and transform.
ctx->bitlen += ctx->datalen * 8;
ctx->data[63] = ctx->bitlen;
ctx->data[62] = ctx->bitlen >> 8;
ctx->data[61] = ctx->bitlen >> 16;
ctx->data[60] = ctx->bitlen >> 24;
ctx->data[59] = ctx->bitlen >> 32;
ctx->data[58] = ctx->bitlen >> 40;
ctx->data[57] = ctx->bitlen >> 48;
ctx->data[56] = ctx->bitlen >> 56;
sha256_transform(ctx, ctx->data);
// copying the final state to the output hash(use big endian).
for (i = 0; i < 4; ++i) {
hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff;
hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff;
hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff;
hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff;
hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff;
hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff;
hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff;
hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff;
}
}
int sha256_test(){
// test data
BYTE text2[] = { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" };
BYTE text3[] = { "aaaaaaaaaa" };
// the true SHA256 result of test data
// get from the online varify website
BYTE hash2[SHA256_BLOCK_SIZE] = { 0x24,0x8d,0x6a,0x61,0xd2,0x06,0x38,0xb8,0xe5,0xc0,0x26,0x93,0x0c,0x3e,0x60,0x39,0xa3,0x3c,0xe4,0x59,0x64,0xff,0x21,0x67,0xf6,0xec,0xed,0xd4,0x19,0xdb,0x06,0xc1 };
BYTE hash3[SHA256_BLOCK_SIZE] = { 0xcd,0xc7,0x6e,0x5c,0x99,0x14,0xfb,0x92,0x81,0xa1,0xc7,0xe2,0x84,0xd7,0x3e,0x67,0xf1,0x80,0x9a,0x48,0xa4,0x97,0x20,0x0e,0x04,0x6d,0x39,0xcc,0xc7,0x11,0x2c,0xd0 };
BYTE buf[SHA256_BLOCK_SIZE];
SHA256_CTX ctx;
int idx, len;
int pass = 1;
sha256_init(&ctx);
sha256_update(&ctx, text2, strlen((char*)text2));
sha256_final(&ctx, buf);
pass = pass && !memcmp(hash2, buf, SHA256_BLOCK_SIZE);
sha256_init(&ctx);
for (idx = 0; idx < 100000; ++idx)
sha256_update(&ctx, text3, strlen((char*)text3));
sha256_final(&ctx, buf);
pass = pass && !memcmp(hash3, buf, SHA256_BLOCK_SIZE);
return(pass);
}
int main(){
printf("SHA-256 tests: %s\n", sha256_test() ? "SUCCEEDED" : "FAILED");
return(0);
}

OpenSSL实现:

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
30
31
32
33
34
35
36
37
38
39
40
41
#include <stdio.h>
#include <string.h>
#include "openssl/evp.h"
int sha256_hash(const unsigned char* message, size_t len, unsigned char* hash, unsigned int* hash_len){
EVP_MD_CTX* md_ctx;
const EVP_MD* md;
md = EVP_sha256();
md_ctx = EVP_MD_CTX_new();
EVP_DigestInit_ex(md_ctx, md, NULL);
EVP_DigestUpdate(md_ctx, message, len);
EVP_DigestFinal_ex(md_ctx, hash, hash_len);
EVP_MD_CTX_free(md_ctx);
return 0;
}
int main(void){
const unsigned char sample1[] = { 'a', 'b', 'c', 0 };
unsigned int sample1_len = strlen((char*)sample1);
const unsigned char sample2[] = { 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64,0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64,0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64,
0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64,0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64,0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64,0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64,0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64 };
unsigned int sample2_len = sizeof(sample2);
unsigned char hash_value[64];
unsigned int i, hash_len;
sha256_hash(sample1, sample1_len, hash_value, &hash_len);
printf("raw data: %s\n", sample1);
printf("hash length: %d bytes.\n", hash_len);
printf("hash value:\n");
for (i = 0; i < hash_len; i++)
printf("0x%x ", hash_value[i]);
printf("\n\n");
sha256_hash(sample2, sample2_len, hash_value, &hash_len);
printf("raw data:\n");
for (i = 0; i < sample2_len; i++)
printf("0x%x ", sample2[i]);
printf("\n");
printf("hash length: %d bytes.\n", hash_len);
printf("hash value:\n");
for (i = 0; i < hash_len; i++)
printf("0x%x ", hash_value[i]);
printf("\n");
return 0;
}

SHA384/SHA512

C语言实现:

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
#include <stdio.h>
#include <stdint.h>
typedef struct sha512_ctx_tag {
uint32_t is_sha384;
/*SHA512 process the data by one block:1024 bits*/
uint8_t block[128];
/*SHA512 will fill 128 bits length field: unit:bit*/
uint64_t len[2];
/*Hash values*/
uint64_t val[8];
/*Payload address to hash*/
uint8_t* payload_addr;
/*Payload length*/
uint64_t payload_len;
} sha512_ctx_t;
#define LSR(x,n) (x >> n)
#define ROR(x,n) (LSR(x,n) | (x << (64 - n)))
#define MA(x,y,z) ((x & y) | (z & (x | y)))
#define CH(x,y,z) (z ^ (x & (y ^ z)))
#define GAMMA0(x) (ROR(x, 1) ^ ROR(x, 8) ^ LSR(x, 7))
#define GAMMA1(x) (ROR(x,19) ^ ROR(x,61) ^ LSR(x, 6))
#define SIGMA0(x) (ROR(x,28) ^ ROR(x,34) ^ ROR(x,39))
#define SIGMA1(x) (ROR(x,14) ^ ROR(x,18) ^ ROR(x,41))
#define INIT_COMPRESSOR() uint64_t tmp0 = 0, tmp1 = 0
#define COMPRESS( a, b, c, d, e, f, g, h, x, k) tmp0 = h + SIGMA1(e) + CH(e,f,g) + k + x;tmp1 = SIGMA0(a) + MA(a,b,c); d += tmp0; h = tmp0 + tmp1;
typedef uint32_t crypto_status_t;
#define CRYPTO_FAIL 0x5A5A5A5AUL
#define CRYPTO_SUCCESS 0xA5A5A5A5UL
extern crypto_status_t easy_sha512(uint8_t* payload, uint64_t payaload_len, uint8_t hash[64]);
extern crypto_status_t easy_sha384(uint8_t* payload, uint64_t payaload_len, uint8_t hash[64]);
#define TEST_VEC_NUM 3
//Predefined sha512 padding bytes
static const uint8_t sha512_padding[128] = {
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,
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, 0
};
//K byte array used for iteration
static const uint64_t 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
};
static void inline sha512_encode(uint64_t input, uint8_t* output, uint32_t idx){
output[idx + 0] = (uint8_t)(input >> 56);
output[idx + 1] = (uint8_t)(input >> 48);
output[idx + 2] = (uint8_t)(input >> 40);
output[idx + 3] = (uint8_t)(input >> 32);
output[idx + 4] = (uint8_t)(input >> 24);
output[idx + 5] = (uint8_t)(input >> 16);
output[idx + 6] = (uint8_t)(input >> 8);
output[idx + 7] = (uint8_t)(input >> 0);
}
static inline void sha512_decode(uint64_t* output, uint8_t* input, uint32_t idx){
*output = ((uint64_t)input[idx + 0] << 56)| ((uint64_t)input[idx + 1] << 48)| ((uint64_t)input[idx + 2] << 40)| ((uint64_t)input[idx + 3] << 32)| ((uint64_t)input[idx + 4] << 24)| ((uint64_t)input[idx + 5] << 16)| ((uint64_t)input[idx + 6] << 8)| ((uint64_t)input[idx + 7] << 0);
}
static inline void sha512_memcpy(uint8_t* src, uint8_t* dst, uint32_t size){
uint32_t i = 0;
for (; i < size; i++)
*dst++ = *src++;
}
static inline void sha512_memclr(uint8_t* dst, uint32_t size){
uint32_t i = 0;
for (; i < size; i++)
*dst++ = 0;
}
static crypto_status_t sha512_init(sha512_ctx_t* sha512_ctx, uint8_t* payload_addr, uint64_t payload_len, uint32_t is_sha384){
crypto_status_t ret = CRYPTO_FAIL;
if (payload_len == 0 || payload_addr == NULL)
goto cleanup;
sha512_memclr((uint8_t*)sha512_ctx, sizeof(sha512_ctx_t));
if (1 == is_sha384) {
sha512_ctx->val[0] = 0xCBBB9D5DC1059ED8ULL;
sha512_ctx->val[1] = 0x629A292A367CD507ULL;
sha512_ctx->val[2] = 0x9159015A3070DD17ULL;
sha512_ctx->val[3] = 0x152FECD8F70E5939ULL;
sha512_ctx->val[4] = 0x67332667FFC00B31ULL;
sha512_ctx->val[5] = 0x8EB44A8768581511ULL;
sha512_ctx->val[6] = 0xDB0C2E0D64F98FA7ULL;
sha512_ctx->val[7] = 0x47B5481DBEFA4FA4ULL;
}
else {
sha512_ctx->val[0] = 0x6A09E667F3BCC908ULL;
sha512_ctx->val[1] = 0xBB67AE8584CAA73BULL;
sha512_ctx->val[2] = 0x3C6EF372FE94F82BULL;
sha512_ctx->val[3] = 0xA54FF53A5F1D36F1ULL;
sha512_ctx->val[4] = 0x510E527FADE682D1ULL;
sha512_ctx->val[5] = 0x9B05688C2B3E6C1FULL;
sha512_ctx->val[6] = 0x1F83D9ABFB41BD6BULL;
sha512_ctx->val[7] = 0x5BE0CD19137E2179ULL;
}
sha512_ctx->is_sha384 = is_sha384;
sha512_ctx->payload_addr = payload_addr;
sha512_ctx->payload_len = (uint64_t)payload_len;
sha512_ctx->len[0] = payload_len << 3;
sha512_ctx->len[1] = payload_len >> 61;
ret = CRYPTO_SUCCESS;
cleanup:
return ret;
}
static crypto_status_t sha512_hash_factory(sha512_ctx_t* ctx, uint8_t data[128]){
uint32_t i = 0;
uint64_t W[80];
uint64_t v[8];
INIT_COMPRESSOR();
/* 1. Calculate the W[80] */
for (i = 0; i < 16; i++)
sha512_decode(&W[i], data, i << 3);
for (; i < 80; i++)
W[i] = GAMMA1(W[i - 2]) + W[i - 7] + GAMMA0(W[i - 15]) + W[i - 16];
/* 2.Init the vectors */
for (i = 0; i < 8; i++)
v[i] = ctx->val[i];
/* 3. Iteration to do the SHA-2 family compression. */
for (i = 0; i < 80;) {
COMPRESS(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], W[i], K[i]); i++;
COMPRESS(v[7], v[0], v[1], v[2], v[3], v[4], v[5], v[6], W[i], K[i]); i++;
COMPRESS(v[6], v[7], v[0], v[1], v[2], v[3], v[4], v[5], W[i], K[i]); i++;
COMPRESS(v[5], v[6], v[7], v[0], v[1], v[2], v[3], v[4], W[i], K[i]); i++;
COMPRESS(v[4], v[5], v[6], v[7], v[0], v[1], v[2], v[3], W[i], K[i]); i++;
COMPRESS(v[3], v[4], v[5], v[6], v[7], v[0], v[1], v[2], W[i], K[i]); i++;
COMPRESS(v[2], v[3], v[4], v[5], v[6], v[7], v[0], v[1], W[i], K[i]); i++;
COMPRESS(v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[0], W[i], K[i]); i++;
}
/* 4. Move the vectors to hash output */
for (i = 0; i < 8; i++)
ctx->val[i] += v[i];
return CRYPTO_SUCCESS;
}
static crypto_status_t sha512_stage1(sha512_ctx_t* sha512_ctx){
while (sha512_ctx->payload_len >= 128) {
sha512_hash_factory(sha512_ctx, sha512_ctx->payload_addr);
sha512_ctx->payload_addr += 128;
sha512_ctx->payload_len -= 128;
}
return CRYPTO_SUCCESS;
}
static crypto_status_t sha512_stage2(sha512_ctx_t* sha512_ctx,uint8_t output[64]){
uint32_t block_pos = sha512_ctx->payload_len;
uint32_t padding_bytes = 0;
uint8_t temp_data[128] = { 0 };
uint8_t* temp_data_p = (uint8_t*)&temp_data[0];
uint8_t len_be[16] = { 0 };
uint8_t i = 0;
/*Copy the last byte to the temp buffer*/
sha512_memcpy(sha512_ctx->payload_addr, temp_data_p, sha512_ctx->payload_len);
padding_bytes = 112 - block_pos;
temp_data_p += block_pos;
/*Copy the padding byte to the temp buffer*/
sha512_memcpy((uint8_t*)sha512_padding, temp_data_p, padding_bytes);
temp_data_p += padding_bytes;
/*Append the length*/
sha512_encode(sha512_ctx->len[1], len_be, 0);
sha512_encode(sha512_ctx->len[0], len_be, 8);
sha512_memcpy(len_be, temp_data_p, 16);
sha512_hash_factory(sha512_ctx, temp_data);
/*encode the hash val to big endian byte array*/
for (i = 0; i < 6; i++)
sha512_encode(sha512_ctx->val[i], output, i * 8);
/*No need to encode the last 16 bytes for SHA384*/
for (; (i < 8) && (sha512_ctx->is_sha384 == 0); i++)
sha512_encode(sha512_ctx->val[i], output, i * 8);
return CRYPTO_SUCCESS;
}
crypto_status_t easy_sha512_impl(uint8_t* payload, uint64_t payload_len,uint8_t output[64], uint32_t is_sha384){
crypto_status_t ret = CRYPTO_FAIL;
sha512_ctx_t g_sha512_ctx;
ret = sha512_init(&g_sha512_ctx, payload, payload_len, is_sha384);
if (ret != CRYPTO_SUCCESS)
goto cleanup;
ret = sha512_stage1(&g_sha512_ctx);
if (ret != CRYPTO_SUCCESS)
goto cleanup;
ret = sha512_stage2(&g_sha512_ctx, output);
cleanup:
return ret;
}
crypto_status_t easy_sha512(uint8_t* payload, uint64_t payload_len, uint8_t hash[64]){
return easy_sha512_impl(payload, payload_len, hash, 0);
}
crypto_status_t easy_sha384(uint8_t* payload, uint64_t payload_len, uint8_t hash[64]){
return easy_sha512_impl(payload, payload_len, hash, 1);
}
static const uint8_t sha384_res0[TEST_VEC_NUM][48] = {
{0x0a,0x98,0x9e,0xbc,0x4a,0x77,0xb5,0x6a,0x6e,0x2b,0xb7,0xb1,
0x9d,0x99,0x5d,0x18,0x5c,0xe4,0x40,0x90,0xc1,0x3e,0x29,0x84,
0xb7,0xec,0xc6,0xd4,0x46,0xd4,0xb6,0x1e,0xa9,0x99,0x1b,0x76,
0xa4,0xc2,0xf0,0x4b,0x1b,0x4d,0x24,0x48,0x41,0x44,0x94,0x54,},
{0xf9,0x32,0xb8,0x9b,0x67,0x8d,0xbd,0xdd,0xb5,0x55,0x80,0x77,
0x03,0xb3,0xe4,0xff,0x99,0xd7,0x08,0x2c,0xc4,0x00,0x8d,0x3a,
0x62,0x3f,0x40,0x36,0x1c,0xaa,0x24,0xf8,0xb5,0x3f,0x7b,0x11,
0x2e,0xd4,0x6f,0x02,0x7f,0xf6,0x6e,0xf8,0x42,0xd2,0xd0,0x8c,},
{0x4e,0x72,0xf4,0x07,0x66,0xcd,0x1b,0x2f,0x23,0x1b,0x9c,0x14,
0x9a,0x40,0x04,0x6e,0xcc,0xc7,0x2d,0xa9,0x1d,0x5a,0x02,0x42,
0xf6,0xab,0x49,0xfe,0xea,0x4e,0xfd,0x55,0x43,0x9b,0x7e,0xd7,
0x82,0xe0,0x3d,0x69,0x0f,0xb9,0x78,0xc3,0xdb,0xce,0x91,0xc1},
};
static const uint8_t sha512_res0[TEST_VEC_NUM][64] = {
{0xba,0x32,0x53,0x87,0x6a,0xed,0x6b,0xc2,0x2d,0x4a,0x6f,0xf5,
0x3d,0x84,0x06,0xc6,0xad,0x86,0x41,0x95,0xed,0x14,0x4a,0xb5,
0xc8,0x76,0x21,0xb6,0xc2,0x33,0xb5,0x48,0xba,0xea,0xe6,0x95,
0x6d,0xf3,0x46,0xec,0x8c,0x17,0xf5,0xea,0x10,0xf3,0x5e,0xe3,
0xcb,0xc5,0x14,0x79,0x7e,0xd7,0xdd,0xd3,0x14,0x54,0x64,0xe2,
0xa0,0xba,0xb4,0x13},
{0x45,0x1e,0x75,0x99,0x6b,0x89,0x39,0xbc,0x54,0x0b,0xe7,0x80,
0xb3,0x3d,0x2e,0x5a,0xb2,0x0d,0x6e,0x2a,0x2b,0x89,0x44,0x2c,
0x9b,0xfe,0x6b,0x47,0x97,0xf6,0x44,0x0d,0xac,0x65,0xc5,0x8b,
0x6a,0xff,0x10,0xa2,0xca,0x34,0xc3,0x77,0x35,0x00,0x8d,0x67,
0x10,0x37,0xfa,0x40,0x81,0xbf,0x56,0xb4,0xee,0x24,0x37,0x29,
0xfa,0x5e,0x76,0x8e},
{0x51,0x33,0x35,0xc0,0x7d,0x10,0xed,0x85,0xe7,0xdc,0x3c,0xa9,
0xb9,0xf1,0x1a,0xe7,0x59,0x1e,0x5b,0x36,0xf9,0xb3,0x71,0xfb,
0x66,0x21,0xb4,0xec,0x6f,0xc8,0x05,0x57,0xfe,0x1e,0x7b,0x9e,
0x1c,0xc1,0x12,0x32,0xb0,0xb2,0xdd,0x92,0x1d,0x80,0x56,0xbf,
0x09,0x7a,0x91,0xc3,0x6d,0xd7,0x28,0x46,0x71,0xfc,0x46,0x8e,
0x06,0x17,0x49,0xf4},
};
static const char* test_vectors[TEST_VEC_NUM] = {
"123456",
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef123456",
};
static uint32_t vector_len[TEST_VEC_NUM] = { 6, 128, 134 };
int main(){
uint8_t output[64];
uint32_t i = 0, j = 0;
for (i = 0; i < TEST_VEC_NUM; i++) {
easy_sha384((uint8_t*)test_vectors[i], vector_len[i], output);
for (j = 0; j < 48; j++)
if (output[j] != sha384_res0[i][j]) {
printf("SHA384 Test %d Failed\n", i);
printf("hash should be %x, calu:%x\n", sha384_res0[i][j], output[j]);
break;
}
if (j == 48)
printf("SHA384 Test %d Passed\n", i);
}
for (i = 0; i < TEST_VEC_NUM; i++) {
easy_sha512((uint8_t*)test_vectors[i], vector_len[i], output);
for (j = 0; j < 64; j++)
if (output[j] != sha512_res0[i][j]) {
printf("SHA512 Test %d Failed\n", i);
printf("hash should be %x, calu:%x\n", sha512_res0[i][j], output[j]);
break;
}
if (j == 64)
printf("SHA512 Test %d Passed\n", i);
}
}

SHA384的OpenSSL实现:

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include "openssl/evp.h"
int sha384_hash(const unsigned char* message, size_t len, unsigned char* hash, unsigned int* hash_len){
EVP_MD_CTX* md_ctx;
const EVP_MD* md;
md = EVP_sha384();
md_ctx = EVP_MD_CTX_new();
EVP_DigestInit_ex(md_ctx, md, NULL);
EVP_DigestUpdate(md_ctx, message, len);
EVP_DigestFinal_ex(md_ctx, hash, hash_len);
EVP_MD_CTX_free(md_ctx);
return 0;
}
#define TEST_VEC_NUM 3
static const unsigned char sha384_res0[TEST_VEC_NUM][48] = {
{0x0a,0x98,0x9e,0xbc,0x4a,0x77,0xb5,0x6a,0x6e,0x2b,0xb7,0xb1,
0x9d,0x99,0x5d,0x18,0x5c,0xe4,0x40,0x90,0xc1,0x3e,0x29,0x84,
0xb7,0xec,0xc6,0xd4,0x46,0xd4,0xb6,0x1e,0xa9,0x99,0x1b,0x76,
0xa4,0xc2,0xf0,0x4b,0x1b,0x4d,0x24,0x48,0x41,0x44,0x94,0x54,},
{0xf9,0x32,0xb8,0x9b,0x67,0x8d,0xbd,0xdd,0xb5,0x55,0x80,0x77,
0x03,0xb3,0xe4,0xff,0x99,0xd7,0x08,0x2c,0xc4,0x00,0x8d,0x3a,
0x62,0x3f,0x40,0x36,0x1c,0xaa,0x24,0xf8,0xb5,0x3f,0x7b,0x11,
0x2e,0xd4,0x6f,0x02,0x7f,0xf6,0x6e,0xf8,0x42,0xd2,0xd0,0x8c,},
{0x4e,0x72,0xf4,0x07,0x66,0xcd,0x1b,0x2f,0x23,0x1b,0x9c,0x14,
0x9a,0x40,0x04,0x6e,0xcc,0xc7,0x2d,0xa9,0x1d,0x5a,0x02,0x42,
0xf6,0xab,0x49,0xfe,0xea,0x4e,0xfd,0x55,0x43,0x9b,0x7e,0xd7,
0x82,0xe0,0x3d,0x69,0x0f,0xb9,0x78,0xc3,0xdb,0xce,0x91,0xc1},
};
static const char* test_vectors[TEST_VEC_NUM] = {
"123456",
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef123456",
};
static uint32_t vector_len[TEST_VEC_NUM] = { 6, 128, 134 };
int main(){
uint8_t output[64];
unsigned int hashlen;
uint32_t i = 0, j = 0;
for (i = 0; i < TEST_VEC_NUM; i++) {
sha384_hash((uint8_t*)test_vectors[i], vector_len[i], output, &hashlen);
if (hashlen != 48){
printf("sha384_hash failed\n");
return -1;
}
for (j = 0; j < 48; j++)
if (output[j] != sha384_res0[i][j]) {
printf("SHA384 Test %d Failed\n", i);
printf("hash should be %x, calu:%x\n", sha384_res0[i][j], output[j]);
break;
}
if (j == 48)
printf("SHA384 Test %d Passed\n", i);
}
}

SHA512的OpenSSL实现:

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include "openssl/evp.h"
#include <stdio.h>
#include <stdint.h>
#define TEST_VEC_NUM 3
static const uint8_t sha512_res0[TEST_VEC_NUM][64] = {
{0xba,0x32,0x53,0x87,0x6a,0xed,0x6b,0xc2,0x2d,0x4a,0x6f,0xf5,
0x3d,0x84,0x06,0xc6,0xad,0x86,0x41,0x95,0xed,0x14,0x4a,0xb5,
0xc8,0x76,0x21,0xb6,0xc2,0x33,0xb5,0x48,0xba,0xea,0xe6,0x95,
0x6d,0xf3,0x46,0xec,0x8c,0x17,0xf5,0xea,0x10,0xf3,0x5e,0xe3,
0xcb,0xc5,0x14,0x79,0x7e,0xd7,0xdd,0xd3,0x14,0x54,0x64,0xe2,
0xa0,0xba,0xb4,0x13},
{0x45,0x1e,0x75,0x99,0x6b,0x89,0x39,0xbc,0x54,0x0b,0xe7,0x80,
0xb3,0x3d,0x2e,0x5a,0xb2,0x0d,0x6e,0x2a,0x2b,0x89,0x44,0x2c,
0x9b,0xfe,0x6b,0x47,0x97,0xf6,0x44,0x0d,0xac,0x65,0xc5,0x8b,
0x6a,0xff,0x10,0xa2,0xca,0x34,0xc3,0x77,0x35,0x00,0x8d,0x67,
0x10,0x37,0xfa,0x40,0x81,0xbf,0x56,0xb4,0xee,0x24,0x37,0x29,
0xfa,0x5e,0x76,0x8e},
{0x51,0x33,0x35,0xc0,0x7d,0x10,0xed,0x85,0xe7,0xdc,0x3c,0xa9,
0xb9,0xf1,0x1a,0xe7,0x59,0x1e,0x5b,0x36,0xf9,0xb3,0x71,0xfb,
0x66,0x21,0xb4,0xec,0x6f,0xc8,0x05,0x57,0xfe,0x1e,0x7b,0x9e,
0x1c,0xc1,0x12,0x32,0xb0,0xb2,0xdd,0x92,0x1d,0x80,0x56,0xbf,
0x09,0x7a,0x91,0xc3,0x6d,0xd7,0x28,0x46,0x71,0xfc,0x46,0x8e,
0x06,0x17,0x49,0xf4},
};
static const char* test_vectors[TEST_VEC_NUM] = {
"123456",
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef123456",
};
static uint32_t vector_len[TEST_VEC_NUM] = { 6, 128, 134 };
int sha512_hash(const unsigned char* message, size_t len, unsigned char* hash, unsigned int* hash_len){
EVP_MD_CTX* md_ctx;
const EVP_MD* md;
md = EVP_sha512();
md_ctx = EVP_MD_CTX_new();
EVP_DigestInit_ex(md_ctx, md, NULL);
EVP_DigestUpdate(md_ctx, message, len);
EVP_DigestFinal_ex(md_ctx, hash, hash_len);
EVP_MD_CTX_free(md_ctx);
return 0;
}
int main(){
uint8_t output[64];
uint32_t i = 0, j = 0;
unsigned int hashlen;
for (i = 0; i < TEST_VEC_NUM; i++) {
sha512_hash((uint8_t*)test_vectors[i], vector_len[i], output, &hashlen);
if (hashlen != 64){
puts("sha512_hash failed");
return -1;
}
for (j = 0; j < 64; j++)
if (output[j] != sha512_res0[i][j]) {
printf("SHA512 Test %d Failed\n", i);
printf("hash should be %x, calu:%x\n", sha512_res0[i][j], output[j]);
break;
}
if (j == 64)
printf("SHA512 Test %d Passed\n", i);
}
}

OpenSSL哈希运算通用

使用算法前要调用OpenSSL_add_all_algorithms函数。

EVP_get_digestbyname根据字符串获取摘要算法:

1
2
3
const EVP_MD* EVP_get_digestbyname(
const char* name //哈希算法名称字符串 如sha256、sha384、sha512等
); //失败NULL

EVP_MD_CTX_create分配结构体所需内存空间,进行初始化,并返回摘要上下文结构体指针。

1
EVP_MD_CTX* EVP_MD_CTX_create();

EVP_MD_CTX结构体为:

1
2
3
4
5
6
7
8
9
10
11
12
struct env_md_ctx_st{
const EVP_MD* digest;
ENGINE* engine;
unsigned long flags;
void* md_data;
EVP_PKEY_CTX* pctx;
int (*update)(
EVP_MD_CTX* ctx,
const void* data,
size_t count
);
};

EVP_MD_CTX_destroy销毁摘要上下文:

1
2
3
void EVP_MD_CTX_destroy(
EVP_MD_CTX* ctx
);

EVP_DigestInit_ex设置摘要算法、算法引擎等:

1
2
3
4
5
int EVP_DigestInit_ex(
EVP_MD_CTX* ctx,
const EVP_MD* type,
ENGINE* impl
);

上面type参数可用EVP_get_digestbyname,也可用这些函数:

1
2
3
4
5
6
EVP_md2();
EVP_md4();
EVP_sha1();
EVP_sha256();
EVP_sha384();
EVP_sha512();

摘要更新函数为EVP_DigestUpdate,可多次调用以计算大数据:

1
2
3
4
5
int EVP_DigestUpdate(
EVP_MD_CTX* ctx,
const void* d, //源数据缓冲区
size_t cnt //源数据长度 单位字节
); //成功1 失败0

摘要结束函数为EVP_Digest_Final_ex,只调用一次:

1
2
3
4
5
int EVP_DigestFinal_ex(
EVP_MD_CTX* ctx,
unsigned char* md, //输出的哈希结果
unsigned int* s //哈希结果长度
); //成功1 失败0

对于小长度的数据,可直接独立用EVP_Digest进行单包摘要计算,直接输出哈希结果:

1
2
3
4
5
6
7
8
int EVP_Digest(
const void* data, //源数据缓冲区
size_t count, //源数据长度 单位字节
unsigned char* md, //哈希结果
unsigned int* size, //哈希结果长度
const EVP_MD* type, //摘要算法
ENGINE* impl //引擎 默认NULL
); //成功1 失败0