最近在做windows TPM2.0下的的ECC算法相关工作,需要验证下ECC签名,用到了openssl的ECDSA_do_verify函数,整理了下分享出来…
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/ec.h>
#include <openssl/ecdsa.h>
#include <openssl/obj_mac.h>
#include <openssl/sha.h>
typedef struct {
uint8_t x[32];
uint8_t y[32];
} EcPubKey;
typedef struct {
uint8_t r[32];
uint8_t s[32];
} EcSig;
int main() {
// 待验证原始数据
const char *message = “123456”;
size_t message_len = strlen(message);
// 签名数据(r 和 s 组成的字节数组)
unsigned char signature_r[] = {
// 请插入你的 r 值的字节数据(32字节)
0x41,0x88,0x17,0x28,0xC4,0x61,0x5A,0x90,0x44,0x9F,0xA4,0xC1,0xB6,0x12,0x72,0xC2,0xD8,0x9F,0x5E,0x10,0xB2,0x61,0x01,0xA7,0x7F,0xFA,0x2A,0xBF,0xE1,0x1E,0x86,0x01
};
unsigned char signature_s[] = {
// 请插入你的 s 值的字节数据(32字节)
0x83,0x28,0x52,0xA7,0xF2,0x41,0x73,0x67,0xCF,0x5A,0x88,0x25,0xAD,0xD4,0x4A,0x0A,0x6A,0xAA,0x6D,0x42,0xDB,0xD2,0x9E,0xF4,0xDD,0x80,0x6F,0x31,0x97,0x07,0x68,0x4D
};
// 公钥数据(64字节)
unsigned char public_key[] = {
// 请插入你的公钥字节数据(64字节)
0x42,0x26,0x7d,0xdb,0xfe,0xf0,0xbf,0x47,0x1c,0xb1,0x91,0x5a,0x24,0x8b,0xe5,0x89,0xca,0x3b,0x67,0x5b,0xed,0xec,0x7b,0x97,0x16,0xe9,0x4d,0x96,0x19,0xaa,0xec,0xb6,0x64,0xfc,0xfb,0xf8,0xd9,0xdc,0x69,0x6a,0xc4,0x22,0x88,0x4e,0x50,0x00,0xbb,0x94,0x91,0x70,0x1c,0xfd,0xa5,0x20,0x19,0xbd,0x46,0x70,0xc5,0x88,0x89,0x20,0xf5,0x3f
};
EC_GROUP* ecGroup = NULL;
//NID_ecdsa_with_SHA256
ecGroup = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
if(ecGroup == NULL){
printf("====[%d]\n",__LINE__);
return -1;
}
EC_KEY* ecKey = NULL;
ecKey = EC_KEY_new();
if(ecKey == NULL){
printf("====[%d]\n",__LINE__);
return -1;
}
if(EC_KEY_set_group(ecKey, ecGroup) != 1){
printf("====[%d]\n",__LINE__);
return -1;
}
EcPubKey eccpubKey = {0};
memcpy(eccpubKey.x,public_key,32);
memcpy(eccpubKey.y,public_key+32,32);
BIGNUM *bnX = NULL;
BIGNUM *bnY = NULL;
bnX = BN_bin2bn(eccpubKey.x, 32, NULL);
if(bnX == NULL){
printf("====[%d]\n",__LINE__);
return -1;
}
bnY = BN_bin2bn(eccpubKey.y, 32, NULL);
if(bnY == NULL){
printf("====[%d]\n",__LINE__);
return -1;
}
if(EC_KEY_set_public_key_affine_coordinates(ecKey, bnX, bnY) != 1){
printf("====[%d]\n",__LINE__);
return -1;
}
EVP_PKEY *pkey = NULL;
pkey = EVP_PKEY_new();
if(pkey == NULL){
printf("====[%d]\n",__LINE__);
return -1;
}
/*
// 创建EC_KEY结构体并设置椭圆曲线参数
EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
if (ec_key == NULL) {
fprintf(stderr, “Error creating EC_KEY\n”);
return 1;
}
// 设置公钥
const EC_GROUP *ec_group = EC_KEY_get0_group(ec_key);
EC_POINT *ec_point = EC_POINT_new(ec_group);
if (EC_POINT_oct2point(ec_group, ec_point, public_key, sizeof(public_key), NULL) != 1) {
fprintf(stderr, "Error setting public key\n");
EC_KEY_free(ec_key);
return 1;
}
if (EC_KEY_set_public_key(ec_key, ec_point) != 1) {
fprintf(stderr, "Error setting public key\n");
EC_KEY_free(ec_key);
EC_POINT_free(ec_point);
return 1;
}
*/
// 创建ECDSA_SIG结构体并设置签名数据
ECDSA_SIG *sign= ECDSA_SIG_new();
if (sign== NULL) {
fprintf(stderr, "Error creating ECDSA_SIG\n");
EC_KEY_free(ecKey);
return 1;
}
/*
if (BN_bin2bn(signature_r, sizeof(signature_r), sign->r) == NULL ||
BN_bin2bn(signature_s, sizeof(signature_s), sign->s) == NULL) {
fprintf(stderr, “Error setting signature\n”);
EC_KEY_free(ec_key);
EC_POINT_free(ec_point);
ECDSA_SIG_free(sign);
return 1;
}
*/
EcSig ecSig = {0};
memcpy(ecSig.r,signature_r,32);
memcpy(ecSig.s,signature_s,32);
BIGNUM* bnR = NULL;
BIGNUM* bnS = NULL;
bnR = BN_bin2bn(ecSig.r, 32, NULL);
if(bnR == NULL){
printf("====[%d]\n",__LINE__);
return -1;
}
bnS = BN_bin2bn(ecSig.s, 32, NULL);
if(bnS == NULL){
printf("====[%d]\n",__LINE__);
return -1;
}
if(ECDSA_SIG_set0(sign, bnR, bnS) != 1){
printf("====[%d]\n",__LINE__);
return -1;
}
// 创建SHA-256哈希
unsigned char digest[SHA256_DIGEST_LENGTH];
SHA256((const unsigned char *)message, message_len, digest);
// 验证签名
int result = ECDSA_do_verify(digest, SHA256_DIGEST_LENGTH, sign, ecKey);
if (result == 1) {
printf("Signature verification succeeded.\n");
} else if (result == 0) {
printf("Signature verification failed.\n");
} else {
fprintf(stderr, "Error in signature verification.\n");
}
// 释放资源
EC_KEY_free(ecKey);
ECDSA_SIG_free(sign);
return 0;
}