DALISTUDIO.NETECDSA签名与验证基于OpenSSL库DaliWangwangdali@qq.com2014/1/11/19目录一、密钥对的生成...........................................................................................................................21、生成密钥对.........................................................................................................................22、导出私钥.............................................................................................................................23、导出公钥.............................................................................................................................34、生成密钥源代码.................................................................................................................3二、对数据的签名...........................................................................................................................81、导入私钥.............................................................................................................................82、数据签名.............................................................................................................................83、数据签名源代码.................................................................................................................8三、对签名的验证.........................................................................................................................141、导入公钥...........................................................................................................................142、验证签名...........................................................................................................................143、验证签名源代码...............................................................................................................142/19一、密钥对的生成1、生成密钥对①首先声明EC_KEY*ec_key;结构,椭圆曲线的参数;私钥和公钥都保存在这个结构中。②声明EC_GROUP*ec_group;结构,这个结构保存着椭圆曲线的参数。③使用ec_key=EC_KEY_new();生成一个新的EC_KEY结构。④使用下面代码选择一条曲线参数,填充EC_GROUP结构:ec_group=EC_GROUP_new_by_curve_name(NID_secp256k1);NID_secp256k1为椭圆曲线,在obj.mac.h中定义。⑤使用intret=EC_KEY_set_group(ec_key,ec_group);将EC_GROUP结构的内容填充到EC_KEY结构中。⑥使用intret=EC_KEY_generate_key(ec_key);生成私钥和公钥对,并填充到EC_KEY结构中。通过上面六个步骤,EC_KEY结构已经填充完成,可以用于签名和验证了。2、导出私钥使用intlen=i2d_ECPrivateKey(ec_key,&PrivateKey);将ec_key结构中的私钥数据导出到PrivateKey指向的空间。len返回私钥数据的长度。导出的私钥数据包含有曲线参数,公3/19钥和私钥的所有数据。在导出私钥的时候可以使用AES256或RC4等对称算法加密,以保证私钥的安全,每次使用私钥时,必须要输入密码解密后才可以使用。3、导出公钥使用intlen=i2o_ECPublicKey(ec_key,&PublicKey);将ec_key结构中的公钥数据导出到PublicKey指向的空间。len返回公钥数据的长度。4、生成密钥源代码#includestdio.h#includeopenssl/crypto.h#includeopenssl/evp.h#includeopenssl/ecdsa.h#definePRIVKEYstaticunsignedcharprivkey[%d]={#definePUBKEYstaticconstunsignedcharpubkey[%d]={#defineENDKEY\n};\nintmain(intargc,char*argv[]){4/19EC_KEY*ec_key;EC_GROUP*ec_group;unsignedcharbuf[1024];unsignedchar*pp;inti,len;if((ec_key=EC_KEY_new())==NULL){printf(Error:EC_KEY_new()\n);return0;}/*选择一条椭圆曲线*/if((ec_group=EC_GROUP_new_by_curve_name(NID_secp256k1))==NULL){printf(Error:EC_GROUP_new_by_curve_name()\n);EC_KEY_free(ec_key);return-1;}/*设置密钥参数*/5/19intret;ret=EC_KEY_set_group(ec_key,ec_group);if(ret!=1){printf(Error:EC_KEY_set_group()\n);return-1;}/*生成密钥对*/if(!EC_KEY_generate_key(ec_key)){printf(Error:EC_KEY_generate_key()\n);EC_KEY_free(ec_key);return-1;}/*导出私钥*/pp=buf;len=i2d_ECPrivateKey(ec_key,&pp);if(!len){printf(Error:i2d_ECPrivateKey()\n);6/19EC_KEY_free(ec_key);return-1;}printf(PRIVKEY,len);for(i=0;ilen;i++){if(!(i%8))printf(\n);if(i==len-1)printf(0x%02X,buf[i]);elseprintf(0x%02X,,buf[i]);}printf(ENDKEY);/*导出公钥*/pp=buf;len=i2o_ECPublicKey(ec_key,&pp);if(!len){7/19printf(Error:i2o_ECPublicKey()\n);EC_KEY_free(ec_key);return-1;}printf(PUBKEY,len);for(i=0;ilen;i++){if(!(i%8))printf(\n);if(i==len-1)printf(0x%02X,buf[i]);elseprintf(0x%02X,,buf[i]);}printf(ENDKEY);EC_KEY_free(ec_key);return0;}8/19二、对数据的签名1、导入私钥使用EC_KEY*ec_key=NULL;定义一个空结构,然后使用下面代码导入私钥:ec_key=d2i_ECPrivateKey(&ec_key,&PrivateKey,sizeof(PrivateKey));2、数据签名使用ECDSA_sign(0,data,data_len,sign,&sign_len,ec_key);对数据data进行签名,并将签名返回到sign中。通常这里的data是要签名数据的散列值,可以使用SHA1、SHA256等散列算法。3、数据签名源代码#includestdio.h#includestdlib.h#includestring.h#includeopenssl/crypto.h#includeopenssl/evp.h#includeopenssl/ecdsa.h#includeopenssl/sha.h9/19#defineSIGNstaticunsignedcharsignature[%d]={#defineENDKEY\n};\n#defineMAXSIGLEN128/*私钥数据*/staticunsignedcharprivkey[279]={0x30,0x82,0x01,0x13,0x02,0x01,0x01,0x04,0x20,0xE8,0x01,0x44,0xD9,0x98,0x71,0x41,0x54,0x2B,0x4D,0xDF,0x50,0x7E,0x4D,0xB3,0xCA,0x5F,0x30,0x39,0xA0,0x51,0x82,0x76,0x39,0xFF,0xC4,0x63,0x38,0x0E,0xDB,0x2A,0xB9,0xA0,0x81,0xA5,0x30,0x81,0xA2,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04,0x41,0x04,0x79,0xBE,0x66,0x7E,0xF9,10/190xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87,0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x