本文档提供了基于openssl的ECDSA算法实现 提供了密钥对生成,签名,验签,获得椭圆曲线的值,设置椭圆曲线的值等接口。亲测可用
源码包括两个文件EccTest.h 和EccTest.cpp文件
EccTest.h文件内容如下:
#include "stdafx.h"
#include
#include
#include
#include
typedef unsigned char u8;
typedef unsigned char boolean;
typedef unsigned short u16;
typedef signed char s8;
typedef signed short s16;
u8 EC_SetDefaultPara(u16 keybitsize);
u8 EC_SetPara(u16 keybitsize,short K,u8 *A, u8 *B,u8* Field,u8 *G,u8* R,short a_len,short b_len,short r_len);
u8 EC_GenkeyPairIml(u16 keybitsize,u8*W,u8 *S);
boolean EC_VerifyIml(u16 keybitsize,u8 *W,u8 * msgDig, u8 *sigBuff,short sigLen);
short EC_SignIml(u16 keybitsize, u8 *S, u8 * msgDig, u8 *sigBuff);
void printf_buffer(char* title, int size, unsigned char* buffer);
u8 EC_SetParaforCard(u16 keybitsize);
EccTest.cpp文件内容如下:
#include "stdafx.h"
#include "EccTest.h"
//abc hex 0x61,0x62,0x63 digest[20]={0xA9,0x99,0x3e,0x36,0x47,0x06,0x81,0x6a,0xba,0x3e,0x25,0x71,0x78,0x50,0xc2,0x6c,0x9c,0xd0,0xd8,0x9d};
u8 *msgDig=NULL;
u8 msgDig160[]={0xA9,0x99,0x3e,0x36,0x47,0x06,0x81,0x6a,0xba,0x3e,0x25,0x71,0x78,0x50,0xc2,0x6c,0x9c,0xd0,0xd8,0x9d};
u8 msgDig192[]={0x00,0x00,0x00,0x00,0xA9,0x99,0x3e,0x36,0x47,0x06,0x81,0x6a,0xba,0x3e,0x25,0x71,0x78,0x50,0xc2,0x6c,0x9c,0xd0,0xd8,0x9d};
u8 msgDig256[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA9,0x99,0x3e,0x36,0x47,0x06,0x81,0x6a,0xba,0x3e,0x25,0x71,0x78,0x50,0xc2,0x6c,0x9c,0xd0,0xd8,0x9d};
/* 128的值
TEMP priKey Field: fffffffdffffffffffffffffffffffff 16
TEMP priKey A: fffffffdfffffffffffffffffffffffc 16
TEMP priKey B: e87579c11079f43dd824993c2cee5ed3 16
TEMP priKey K: 0001 1
TEMP priKey R: fffffffe0000000075a30d1b9038a115 16
TEMP priKey G: 04161ff7528b899b2d0c28607ca52c5b86cf5ac8395bafeb13c02da292dded7a83 33
TEMP priKey S: 60629708161e6bebdb782afce1b25e3e 16
*/
/* 160的值
TEMP priKey Field: fffffffffffffffffffffffffffffffffffff48b 20
TEMP priKey A: fffffffffffffffffffffffffffffffffffff488 20
TEMP priKey B: 417f0e7c2825000c838b7c9515d1fff369b50e16 20
TEMP priKey K: 0001 1
TEMP priKey R: fffffffffffffffffffea8c895f76785fc179171 20
TEMP priKey G: 044f3a609aec06de6e466e2db52f0ed536c1ff87f48559ef2adda20056c4be54e3065de5fe3952ff22 41
TEMP priKey S: f8d22503247efedc5762a0df887874c2f8d22503 20
*/
/* 192的值
TEMP priKey Field: fffffffffffffffffffffffffffffffeffffffffffffffff 24
TEMP priKey A: fffffffffffffffffffffffffffffffefffffffffffffffc
TEMP priKey B: 64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1
TEMP priKey K: 0001
TEMP priKey R: ffffffffffffffffffffffff99def836146bc9b1b4d22831
TEMP priKey G: 04188da80eb03090f67cbf20eb43a18800f4ff0afd82ff101207192b95ffc8da78631011ed6b24cdd573f977a11e794811 49
TEMP priKey S: 4f897cdc28ec27bddb913183c21ae6fe4f897cdc28ec27bd
*/
/* 256的值
TEMP priKey Field: ffffffff00000001000000000000000000000000ffffffffffffffffffffffff 32
TEMP priKey A: ffffffff00000001000000000000000000000000fffffffffffffffffffffffc
TEMP priKey B: 5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b
TEMP priKey K: 0001
TEMP priKey R: ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551
TEMP priKey G: 046b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5 65
TEMP priKey S: 0fdaa2163811b8533a54e5c337cb60eb0fdaa2163811b8533a54e5c337cb60eb
*/
// 卡片的值
u8 Field128[]={0xff,0xff,0xff,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
u8 A128[]={0xff,0xff,0xff,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc};
u8 B128[]={0xe8,0x75,0x79,0xc1,0x10,0x79,0xf4,0x3d,0xd8,0x24,0x99,0x3c,0x2c,0xee,0x5e,0xd3};
u8 R128[]={0xff,0xff,0xff,0xfe,0x00,0x00,0x00,0x00,0x75,0xa3,0x0d,0x1b,0x90,0x38,0xa1,0x15};
u8 G128[]={0x04,0x16,0x1f,0xf7,0x52,0x8b,0x89,0x9b,0x2d,0x0c,0x28,0x60,0x7c,0xa5,0x2c,0x5b,0x86,0xcf,0x5a,0xc8,0x39,0x5b,0xaf,0xeb,0x13,0xc0,0x2d,0xa2,0x92,0xdd,0xed,0x7a,0x83};
u8 Field160[]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf4,0x8b};
u8 A160[]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf4,0x88};
u8 B160[]={0x41,0x7f,0x0e,0x7c,0x28,0x25,0x00,0x0c,0x83,0x8b,0x7c,0x95,0x15,0xd1,0xff,0xf3,0x69,0xb5,0x0e,0x16};
u8 R160[]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xa8,0xc8,0x95,0xf7,0x67,0x85,0xfc,0x17,0x91,0x71};
u8 G160[]={0x04,0x4f,0x3a,0x60,0x9a,0xec,0x06,0xde,0x6e,0x46,0x6e,0x2d,0xb5,0x2f,0x0e,0xd5,0x36,0xc1,0xff,0x87,0xf4,0x85,0x59,0xef,0x2a,0xdd,0xa2,0x00,0x56,0xc4,0xbe,0x54,0xe3,0x06,0x5d,0xe5,0xfe,0x39,0x52,0xff,0x22};
u8 Field192[]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
u8 A192[]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc};
u8 B192[]={0x64,0x21,0x05,0x19,0xe5,0x9c,0x80,0xe7,0x0f,0xa7,0xe9,0xab,0x72,0x24,0x30,0x49,0xfe,0xb8,0xde,0xec,0xc1,0x46,0xb9,0xb1};
u8 R192[]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x99,0xde,0xf8,0x36,0x14,0x6b,0xc9,0xb1,0xb4,0xd2,0x28,0x31};
u8 G192[]={0x04,0x18,0x8d,0xa8,0x0e,0xb0,0x30,0x90,0xf6,0x7c,0xbf,0x20,0xeb,0x43,0xa1,0x88,0x00,0xf4,0xff,0x0a,0xfd,0x82,0xff,0x10,0x12,0x07,0x19,0x2b,0x95,0xff,0xc8,0xda,0x78,0x63,0x10,0x11,0xed,0x6b,0x24,0xcd,0xd5,0x73,0xf9,0x77,0xa1,0x1e,0x79,0x48,0x11};
u8 Field256[]={0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
u8 A256[]={0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc};
u8 B256[]={0x5a,0xc6,0x35,0xd8,0xaa,0x3a,0x93,0xe7,0xb3,0xeb,0xbd,0x55,0x76,0x98,0x86,0xbc,0x65,0x1d,0x06,0xb0,0xcc,0x53,0xb0,0xf6,0x3b,0xce,0x3c,0x3e,0x27,0xd2,0x60,0x4b};
u8 R256[]={0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbc,0xe6,0xfa,0xad,0xa7,0x17,0x9e,0x84,0xf3,0xb9,0xca,0xc2,0xfc,0x63,0x25,0x51};
u8 G256[]={0x04,0x6b,0x17,0xd1,0xf2,0xe1,0x2c,0x42,0x47,0xf8,0xbc,0xe6,0xe5,0x63,0xa4,0x40,0xf2,0x77,0x03,0x7d,0x81,0x2d,0xeb,0x33,0xa0,0xf4,0xa1,0x39,0x45,0xd8,0x98,0xc2,0x96,0x4f,0xe3,0x42,0xe2,0xfe,0x1a,0x7f,0x9b,0x8e,0xe7,0xeb,0x4a,0x7c,0x0f,0x9e,0x16,0x2b,0xce,0x33,0x57,0x6b,0x31,0x5e,0xce,0xcb,0xb6,0x40,0x68,0x37,0xbf,0x51,0xf5};
EC_GROUP *group1;
u8 EC_SetDefaultPara(u16 keybitsize){
int ret,nid;
EC_builtin_curve *curves;
int crv_len;
const EC_POINT *ptG;
u8 P[32];
u8 A[32];
u8 B[32];
u8 R[32];
u8 K[32];
char *G;
BIGNUM *binp=BN_new();
BIGNUM *bina=BN_new();
BIGNUM *binb=BN_new();
BIGNUM *binR=BN_new();
BIGNUM *binK=BN_new();
// 获取实现的椭圆曲线个数
crv_len = EC_get_builtin_curves(NULL, 0);
curves = (EC_builtin_curve *)malloc(sizeof(EC_builtin_curve) * crv_len);
// 获取椭圆曲线列表
ret=EC_get_builtin_curves(curves, crv_len);
//nid=curves[0].nid;会有错误,原因是密钥太短
// 选取一种椭圆曲线
switch (keybitsize){
case 112:
nid=curves[1].nid;
break;
case 128:
nid=curves[2].nid;//2,3
break;
case 160:
nid=curves[6].nid;//4,5,6
break;
case 192:
nid=curves[13].nid;//7,13,14,15
break;
case 256:
nid=curves[19].nid;//19
break;
default: //use 128
nid=curves[2].nid;
break;
}
free(curves);
// 根据选择的椭圆曲线生成密钥参数group
group1=EC_GROUP_new_by_curve_name(nid);
if(group1==NULL)
{
printf("EC_GROUP_new_by_curve_name err!\n");
return -1;
}
ptG=EC_POINT_new(group1);
EC_GROUP_get_curve_GFp(group1,binp,bina,binb,NULL); //获得 Field(P) A B
EC_GROUP_get_order(group1,binR,NULL); //获得R
EC_GROUP_get_cofactor(group1,binK,NULL); //获得K
ptG=EC_GROUP_get0_generator(group1);
G=EC_POINT_point2hex(group1,ptG,POINT_CONVERSION_UNCOMPRESSED,NULL); //获得G
int p_len=BN_bn2bin(binp,P);
int a_len=BN_bn2bin(bina,A);
int b_len=BN_bn2bin(binb,B);
int r_len=BN_bn2bin(binR,R);
int k_len=BN_bn2bin(binK,K);
printf_buffer("P",p_len,P);
printf_buffer("A",a_len,A);
printf_buffer("B",b_len,B);
printf_buffer("R",r_len,R);
printf_buffer("K",k_len,K);
printf_buffer("G",strlen(G),(u8 *)G);
BN_free(binp);
BN_free(bina);
BN_free(binb);
BN_free(binR);
BN_free(binK);
free(G);
// EC_POINT_free(ptG);
return 0;
}
u8 EC_SetPara(u16 keybitsize,short K,u8 *A, u8 *B,u8* Field,u8 *G,u8* R,short a_len,short b_len,short r_len){
BIGNUM *p=BN_new();
BIGNUM *a=BN_new();
BIGNUM *b=BN_new();
BIGNUM *order=BN_new();
BIGNUM *cofactor=BN_new();
EC_POINT *ptG;
u16 keyByteSize=keybitsize>>3;
printf_buffer("Field",keyByteSize,Field);
printf_buffer("A",a_len,A);
printf_buffer("B",b_len,B);
printf_buffer("R",r_len,R);
printf_buffer("K",2,(u8*)&K);
printf_buffer("G",keyByteSize*2+1,G);
BN_bin2bn(Field,keyByteSize,p);
BN_bin2bn(A,a_len,a);
BN_bin2bn(B,b_len,b);
group1=EC_GROUP_new_curve_GFp(p,a,b,NULL);
//EC_GROUP_set_curve_GFp(group1,&p,&a,&b,NULL);
BN_bin2bn(R,r_len,order);
BN_set_word(cofactor,K);
ptG=EC_POINT_new(group1);
EC_POINT_oct2point(group1,ptG,G,keyByteSize*2+1,NULL);
EC_GROUP_set_generator(group1,ptG,order,cofactor);
BN_free(p);
BN_free(a);
BN_free(b);
BN_free(order);
BN_free(cofactor);
EC_POINT_free(ptG);
//EC_GROUP_free(group1);
return 0;
}
// 特定的
u8 EC_SetParaforCard(u16 keybitsize){
short K=1;
u8 *A;
u8 *B;
u8 *Field;
u8 *G=NULL;
u8 *R;
short a_len;
if(keybitsize==128){
A=A128;
Field=Field128;
B=B128;
R=R128;
G=G128;
a_len=16;
}
else if(keybitsize==160){
A=A160;
Field=Field160;
B=B160;
R=R160;
G=G160;
a_len=20;
}
else if(keybitsize==192){
Field=Field192;
A=A192;
B=B192;
R=R192;
G=G192;
a_len=24;
}
else if(keybitsize==256){
Field=Field256;
A=A256;
B=B256;
R=R256;
G=G256;
a_len=32;
}
return EC_SetPara( keybitsize,K,A, B, Field, G, R, a_len, a_len, a_len);
}
/*int sslen=0;*/
// keybitsize 密钥长度,W密钥指针,msgDig原数据,sigBuff,签名数据,siglen签名长度
boolean EC_VerifyIml(u16 keybitsize,u8 *W,u8 * msgDig, u8 *sigBuff,short sigLen){
EC_KEY *key1;
EC_POINT *pubkey1=EC_POINT_new(group1);
int ret;
u16 keyByteSize=keybitsize>>3;
key1=EC_KEY_new();
ret=EC_KEY_set_group(key1,group1);
EC_POINT_oct2point(group1,pubkey1,W,keyByteSize*2+1,NULL);
ret=EC_KEY_set_public_key(key1, pubkey1);
ret=ECDSA_verify(0,msgDig,keyByteSize,sigBuff,sigLen,key1);
if (ret!=TRUE)
{
printf("Error: ECDSA_verify() \n");
}else{
printf("success: ECDSA_verify() \n");
}
EC_KEY_free(key1);
EC_POINT_free(pubkey1);
EC_GROUP_free(group1);
if(ret == 1)
return TRUE;
else
return FALSE;
}
// keybitsize密钥长度, S 私钥S值,msgDig源数据,sigBuff签名结果
short EC_SignIml(u16 keybitsize, u8 *S, u8 * msgDig, u8 *sigBuff){
EC_KEY *key1;
BIGNUM *prikey;
int ret;
unsigned int sig_len;
u16 keyByteSize=keybitsize>>3;
key1=EC_KEY_new();
ret=EC_KEY_set_group(key1,group1);
prikey=BN_bin2bn(S,keyByteSize,NULL);
ret=EC_KEY_set_private_key(key1, prikey);
/*memset(msgDig,0x18,keyByteSize);*/
ret=ECDSA_sign(0,msgDig,keyByteSize,sigBuff,&sig_len,key1);
if (ret!=TRUE)
{
printf("Error: ECDSA_sign() \n");
}
else{
printf("success: ECDSA_sign() \n");
}
EC_KEY_free(key1);
BN_free(prikey);
//EC_POINT_free(pubkey);
// EC_GROUP_free(group1);
return sig_len;
}
//u8 EC_GenkeyPairIml(boolean bKeyInit, u16 keybitsize,u8 *A, u8 *B,u8* Field,u8 *G,short *K,u8* R,u8*W,u8 *S,short*a_len,short*b_len,short*r_len){
u8 EC_GenkeyPairIml(u16 keybitsize,u8*W,u8 *S){
EC_KEY *ec_key;
const BIGNUM *prikey;
const EC_POINT *pubkey1;
int ret;
int len ,i;
u16 keyByteSize=keybitsize/8;
/* 构造EC_KEY数据结构 */
ec_key=EC_KEY_new();
if(ec_key==NULL)
{
printf("EC_KEY_new err!\n");
return -1;
}
/* 设置密钥参数 */
ret=EC_KEY_set_group(ec_key,group1);
if(ret!=1)
{
printf("EC_KEY_set_group err.\n");
return -1;
}
/* 生成密钥 */
ret=EC_KEY_generate_key(ec_key);
if(ret!=1)
{
printf("EC_KEY_generate_key err.\n");
return -1;
}
{
u8 digest[48];
u8 signature[100];
unsigned int sig_len;
memset(digest,0x18,48);
ret=ECDSA_sign(0,digest,keyByteSize,signature,&sig_len,ec_key);
ret=ECDSA_verify(0,digest,keyByteSize,signature,sig_len,ec_key);
}
// 导出私钥
prikey=EC_KEY_get0_private_key(ec_key);
ret=BN_bn2bin(prikey,S);
printf_buffer("S",ret,S);
//导出公钥
pubkey1 = EC_KEY_get0_public_key(ec_key);
// ret=BN_bn2bin(pubkey1,W);
ret=EC_POINT_point2oct(group1,pubkey1,POINT_CONVERSION_UNCOMPRESSED,W,keyByteSize*2+1,NULL);
printf_buffer("W",keyByteSize*2+1,W);
EC_KEY_free(ec_key);
// BN_free(prikey);
// EC_POINT_free(pubkey1);
// EC_GROUP_free(group1);
return 0;
}
void printf_buffer(char* title, int size, unsigned char* buffer)
{
int i;
printf("==========================================================\n");
printf("%s:\n", title);
for(i=0;i { if (((i%16)==0) && (i!=0)) printf("\n"); printf("%02x ", (unsigned char)buffer[i]); } printf("\n"); }