C语言利用openssl实现的ECDH问题
ECDH意思是通信双方各自产生一对密钥对,将公钥发送给彼此,然后双方各自利用对方的公钥和自己的私密钥产生共享密钥。现在的问题是,openssl实现的公钥是EC_POINT格式,要传输给对方就必须转化其格式。Openssl提供的函数有EC_KEY *o2i_ECPublicKey(EC_KEY **a, const unsigned char **in, long len)和int i2o_ECPublicKey(EC_KEY *a, unsigned char **out); 后者用于将公钥转换为字符型,牵着用于将字符型在转换成EC_KEY格式,最后利用EC_KEY_get0_public_key(EC_KEY *a)获得对方公钥。但是我在做的时候,将公钥转化后,out中的数据很异常。看下面程序段
int main()
{
EC_KEY *key1,*key2;
EC_KEY *key3;
const EC_POINT *pubkey1,*pubkey2;
// EC_POINT *pubkey3,*pubkey4;
EC_GROUP *group1,*group2;
int ret,nid,size;
EC_builtin_curve *curves;
int crv_len;
char shareKey1[128],shareKey2[128];
int len1,len2;
unsigned char *out;
/* 构造EC_KEY 数据结构 */
key1=EC_KEY_new();
if(key1==NULL)
{
printf("EC_KEY_new err!\n");
return -1;
}
key2=EC_KEY_new();
if(key2==NULL)
{
printf("EC_KEY_new err!\n");
return -1;
}
/* 获取实现的椭圆曲线个数 */
crv_len = EC_get_builtin_curves(NULL, 0);
curves = (EC_builtin_curve *)malloc(sizeof(EC_builtin_curve) * crv_len);
/* 获取椭圆曲线列表 */
EC_get_builtin_curves(curves, crv_len);
/*
nid=curves[0].nid;会有错误,原因是密钥太短
*/
/* 选取一种椭圆曲线 */
nid=curves[25].nid;
/* 根据选择的椭圆曲线生成密钥参数group */
group1=EC_GROUP_new_by_curve_name(nid);
if(group1==NULL)
{
printf("EC_GROUP_new_by_curve_name err!\n");
return -1;
}
group2=EC_GROUP_new_by_curve_name(nid);
if(group2==NULL)
{
printf("EC_GROUP_new_by_curve_name err!\n");
return -1;
}
if(group1==group2)
printf("xiang tong qun");
/* 设置密钥参数 */
ret=EC_KEY_set_group(key1,group1);
if(ret!=1)
{
printf("EC_KEY_set_group err.\n");
return -1;
}
ret=EC_KEY_set_group(key2,group2);
if(ret!=1)
{
printf("EC_KEY_set_group err.\n");
return -1;
}
/* 生成密钥 */
ret=EC_KEY_generate_key(key1);
if(ret!=1)
{
printf("EC_KEY_generate_key err.\n");
return -1;
}
ret=EC_KEY_generate_key(key2);
if(ret!=1)
{
printf("EC_KEY_generate_key err.\n");
return -1;
}
/* 检查密钥 */
ret=EC_KEY_check_key(key1);
if(ret!=1)
{
printf("check key err.\n");
return -1;
}
/* 获取密钥大小 */
size=ECDSA_size(key2);
printf("size: %d \n",size);
/* 获取对方公钥,不能直接引用 */
key3=EC_KEY_new();
out=(unsigned char *)malloc(size);
ret=i2o_ECPublicKey(key2,&out);
printf("%d",ret);
for(int i=0;i<ret;i++)
printf("%02x",*(out+i));
o2i_ECPublicKey(&key3,(const unsigned char **)&out,ret);
pubkey2=EC_KEY_get0_public_key(key3);
/* 生成一方的共享密钥 */
len1=ECDH_compute_key(shareKey1, 128, pubkey2, key1, NULL);
pubkey1=EC_KEY_get0_public_key(key1);
/* 生成另一方共享密钥 这里没有转化格式,直接用了*/
len2=ECDH_compute_key(shareKey2, 128, pubkey1, key2, NULL);
printf("\n");
for(i=0;i<128;i++)
printf("%c",shareKey1[i]);
printf("\n");
for(i=0;i<128;i++)
printf("%c",shareKey1[i]);
if(len1!=len2)
{
printf("shareKey err\n");
}
else
{
ret=memcmp(shareKey1,shareKey2,len1);
if(ret==0)
printf("生成共享密钥成功\ntest ok!\n");
else
printf("生成共享密钥失败\n");
}
EC_KEY_free(key1);
EC_KEY_free(key2);
free(curves);
return 0;
}
望各位大侠不吝赐教,谢谢.