SM2-Sign-With-SM3 ANSI C 实现

开发实践过程中,需要实现 SM2-Sign-With-SM3

要点

利用的库

  • openssl-1.1.1w
  • gmssl-3.1

签名

if (sm2_sign_init(&sign_ctx, &sm2_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) == 1 &&
sm2_sign_update(&sign_ctx, data, data_len) == 1 &&
sm2_sign_finish(&sign_ctx, signature, &siglen) == 1) {
printf("Success.\n");
} else {
printf("Failure.\n");
}

验签

if (sm2_verify_init(&veri_ctx, &sm2_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) == 1 &&
sm2_verify_update(&veri_ctx, data, data_len) == 1 &&
sm2_verify_finish(&veri_ctx, signature.data(), siglen) == 1) {
printf("Success.\n");
} else {
printf("Failure.\n");
}

验证是否有效

利用验签工具:SM2 在线验签工具

但这个验签工具需要提供的不是 BASE64 编码的签名,而是需要提供的 r, s,所以需要将待签名的数据、公钥的key、签名得到的 r, s 都拆解为 HEX 字符串(%02x)传入。

uint8_t prikey[32];
uint8_t pubkey[65];
/** 获取私钥 */
sm2_z256_to_bytes(sm2_key.private_key, prikey);

/** 获取公钥 */
sm2_z256_point_to_uncompressed_octets(&(sm2_key.public_key), pubkey);

printf("prikey:");
print_hex(prikey, 32);

printf("pubkey:");
print_hex(pubkey + 1, 64); // 此处需注意,`public_key` 需要加 1,因为第一个字节是表示 `uncompressed` 格式的。

extract_sm2_der(signature, siglen); // signature, 为签名后得到的 DER 签名,该函数用于从 DER 签名中获取 `r, s` 数据。

extract_sm2_der 函数用于从 DER 签名中获取 r, s 数据。

void extract_sm2_der(const uint8_t *der_sig, size_t der_len) {
SM2_SIGNATURE sm2_sig;

// 从DER解码
if (sm2_signature_from_der(&sm2_sig, &der_sig, &der_len) != 1) {
// 错误处理
return;
}

// 直接访问结构体成员
uint8_t *r = sm2_sig.r; // 32字节
uint8_t *s = sm2_sig.s; // 32字节

printf("sig r:");
print_hex(r, 32);
printf("sig s:");
print_hex(s, 32);
}