C语言---基于Openssl的ECC验签算法

最近在做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;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值