ECDSA算法实现源码

本文档提供了基于opensslECDSA算法实现  提供了密钥对生成,签名,验签,获得椭圆曲线的值,设置椭圆曲线的值等接口。亲测可用

源码包括两个文件EccTest.h EccTest.cpp文件

 

EccTest.h文件内容如下:

#include "stdafx.h"

#include <openssl/crypto.h>

#include <openssl/evp.h>

#include <openssl/ecdsa.h>

#include <openssl/sha.h>

 

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值,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<size;i++)

{

if (((i%16)==0) && (i!=0)) printf("\n");

printf("%02x ", (unsigned char)buffer[i]);

}

printf("\n");

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值