实现了SM3算法后,就可以来完善一下SM2的签名算法,回顾一下签名算法的定义
int gm_do_sign(const gm_bn_t key, const gm_bn_t dgst, unsigned char *sig);
int gm_do_verify(const gm_point_t *key, const gm_bn_t dgst, const unsigned char *sig);
1
2
2
dgst是消息的摘要值,摘要值的计算:
其中
接下来就是利用实现好的SM3算法,来实现ZA和dgst的计算
# ZA计算
static const unsigned char GM_ECC_A[] = {
0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC
};
static const unsigned char GM_ECC_B[] = {
0x28, 0xE9, 0xFA, 0x9E, 0x9D, 0x9F, 0x5E, 0x34,
0x4D, 0x5A, 0x9E, 0x4B, 0xCF, 0x65, 0x09, 0xA7,
0xF3, 0x97, 0x89, 0xF5, 0x15, 0xAB, 0x8F, 0x92,
0xDD, 0xBC, 0xBD, 0x41, 0x4D, 0x94, 0x0E, 0x93
};
static const unsigned char GM_ECC_G_X[] = {
0x32, 0xC4, 0xAE, 0x2C, 0x1F, 0x19, 0x81, 0x19,
0x5F, 0x99, 0x04, 0x46, 0x6A, 0x39, 0xC9, 0x94,
0x8F, 0xE3, 0x0B, 0xBF, 0xF2, 0x66, 0x0B, 0xE1,
0x71, 0x5A, 0x45, 0x89, 0x33, 0x4C, 0x74, 0xC7
};
static const unsigned char GM_ECC_G_Y[] = {
0xBC, 0x37, 0x36, 0xA2, 0xF4, 0xF6, 0x77, 0x9C,
0x59, 0xBD, 0xCE, 0xE3, 0x6B, 0x69, 0x21, 0x53,
0xD0, 0xA9, 0x87, 0x7C, 0xC6, 0x2A, 0x47, 0x40,
0x02, 0xDF, 0x32, 0xE5, 0x21, 0x39, 0xF0, 0xA0
};
void gm_sm2_compute_z_digest(const unsigned char * id_bytes, unsigned int idLen, const gm_point_t * pub_key,
unsigned char * output) {
gm_sm3_context _ctx;
gm_sm3_context * ctx = &_ctx;
gm_bn_t x, y;
gm_sm3_init(ctx);
// update idlen,这里的idlen是比特长度,所以移位注意一下
ctx->buf[0] = ((idLen >> 5) & 0x0FF);
ctx->buf[1] = ((idLen << 3) & 0x0FF);
ctx->cur_buf_len = 2;
// update id
gm_sm3_update(ctx, id_bytes, idLen);
// update a
gm_sm3_update(ctx, GM_ECC_A, 32);
// update b
gm_sm3_update(ctx, GM_ECC_B, 32);
// update Gx
gm_sm3_update(ctx, GM_ECC_G_X, 32);
// update Gy
gm_sm3_update(ctx, GM_ECC_G_Y, 32);
gm_point_get_xy(pub_key, x, y);
// update Px
gm_bn_to_bytes(x, output); // 借用output当缓冲区
gm_sm3_update(ctx, output, 32);
// update Py
gm_bn_to_bytes(y, output); // 借用output当缓冲区
gm_sm3_update(ctx, output, 32);
gm_sm3_done(ctx, output);
}
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
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
# dgst计算
void gm_sm2_compute_msg_hash(const unsigned char * input, unsigned iLen,
const unsigned char * id_bytes, unsigned int idLen,
const gm_point_t * pub_key, unsigned char * output) {
gm_sm3_context _ctx;
gm_sm3_context * ctx = &_ctx;
gm_sm3_init(ctx);
// compute z digest
gm_sm2_compute_z_digest(id_bytes, idLen, pub_key, output);
gm_sm3_update(ctx, output, 32);
gm_sm3_update(ctx, input, iLen);
gm_sm3_done(ctx, output);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 单元测试
改造一下test_gm_sv函数,增加一个const unsigned char * dgst_bytes
参数,用于传入计算好的dgst,然后再修改一下dgst的初始化
if(dgst_bytes == NULL) {
gm_bn_from_hex(dgst, key_hex);
}else {
gm_bn_from_bytes(dgst, dgst_bytes);
}
1
2
3
4
5
2
3
4
5
增加test_sm2_sv函数:
void test_sm2_sv(const char * key_hex, const char * pubKey_hex, const char * sig_hex,
const char * input, unsigned int iLen,
int algType) {
unsigned char buf[32] = {0};
gm_bn_t key;
gm_point_t _P, *P = &_P;
gm_bn_from_hex(key, key_hex);
// 从私钥中计算公钥
gm_point_mul(P, key, GM_MONT_G);
gm_sm2_compute_msg_hash(input, iLen, "1234567812345678", 16, P, buf);
test_gm_sv(key_hex, pubKey_hex, sig_hex, buf, algType);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
main函数增加:
if(strcmp(argv[1], "sm2_sv") == 0) {
test_sm2_sv("6B8B4567327B23C6643C98696633487374B0DC5119495CFF2AE8944A625558EC",
"0148E6AF89A0E132E4E7CDA26DF2C2AEB53B741FD00AE85C78CF6EBA13E939B12F58B1E8A661EBF3395459F28945D381259BEEDA76B4886FABF5EE0A55ADEEB2",
"E85863FA584DEBE05D573D655DF82B889284189B15D1559E577B0E67500BDF14885066A6176A5D12B5DADC52CB11C84F72AEA157F9E7D0878E988A39BCCBB3B7",
"abc", 3,
0);
}
if(strcmp(argv[1], "sm2_sign") == 0) {
test_sm2_sv("6B8B4567327B23C6643C98696633487374B0DC5119495CFF2AE8944A625558EC",
"0148E6AF89A0E132E4E7CDA26DF2C2AEB53B741FD00AE85C78CF6EBA13E939B12F58B1E8A661EBF3395459F28945D381259BEEDA76B4886FABF5EE0A55ADEEB2",
"E85863FA584DEBE05D573D655DF82B889284189B15D1559E577B0E67500BDF14885066A6176A5D12B5DADC52CB11C84F72AEA157F9E7D0878E988A39BCCBB3B7",
"abc", 3,
1);
}
if(strcmp(argv[1], "sm2_verify") == 0) {
test_sm2_sv("6B8B4567327B23C6643C98696633487374B0DC5119495CFF2AE8944A625558EC",
"0148E6AF89A0E132E4E7CDA26DF2C2AEB53B741FD00AE85C78CF6EBA13E939B12F58B1E8A661EBF3395459F28945D381259BEEDA76B4886FABF5EE0A55ADEEB2",
"0EB2C35EB35943C3964116BD3AB589E3AC7EAA526422A3B4F6488B16BF5B2B5F1B803696DB30BBABAEFDEAD134B18AF9F5A14062929412BAE95BE1D90C9A2DA0",
"abc", 3,
2);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
算法效率:
saintdeMacBook-Pro:bn saint$ time ./a.out sm2_sv
r = E85863FA584DEBE05D573D655DF82B889284189B15D1559E577B0E67500BDF14885066A6176A5D12B5DADC52CB11C84F72AEA157F9E7D0878E988A39BCCBB3B7
test result: ok
real 0m18.408s
user 0m18.059s
sys 0m0.098s
saintdeMacBook-Pro:bn saint$ time ./a.out sm2_sign
r = E85863FA584DEBE05D573D655DF82B889284189B15D1559E577B0E67500BDF14885066A6176A5D12B5DADC52CB11C84F72AEA157F9E7D0878E988A39BCCBB3B7
test result: ok
real 0m6.546s
user 0m6.401s
sys 0m0.043s
saintdeMacBook-Pro:bn saint$ time ./a.out sm2_verify
r = 0EB2C35EB35943C3964116BD3AB589E3AC7EAA526422A3B4F6488B16BF5B2B5F1B803696DB30BBABAEFDEAD134B18AF9F5A14062929412BAE95BE1D90C9A2DA0
test result: ok
real 0m12.130s
user 0m11.897s
sys 0m0.077s
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
未经本人同意,禁止转载!
← ECB及CBC加解密 点的压缩与解压缩 →