C语言利用openssl实现的ECDH问题

yuxiaofeng654321 2011-01-10 11:58:48
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;
}
望各位大侠不吝赐教,谢谢.
...全文
1923 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
ytfrdfiw 2012-02-29
  • 打赏
  • 举报
回复
如何使用ECC来加解密呢?楼主这段代码在武大密码学上也有。
vega921 2011-05-25
  • 打赏
  • 举报
回复
i2o_ECPublicKey后,out值已改变。

out=(unsigned char *)malloc(size);
unsigned char *pszTmp = out;
ret=i2o_ECPublicKey(key2,&pszTmp);
用户 昵称 2011-04-27
  • 打赏
  • 举报
回复
厄正在发愁这个,厄抄了半天,最后才知道是sm2的,跟ecc还不全一样。
课程简介    随着”新基建“的推行,其中涉及到的工业互联网、物联网、人工智能、云计算、区块链,无一不是与安全相关,所有数据的存储、传输、签名认证都涉及到密码学技术,所以在这样的大环境下再结合我多年安全开发经验,设计出这门课程。    因为密码学技术在新基建中的重要性,所以使其成为底层开发人员所必备的技能。特别是现在的区块链技术是全面应用密码学,大数据技术和人工智能技术也要解决隐私安全问题。所以现在学习相关技术是非常必要的技术储备,并且可以改造现有的系统,提升其安全性。课程学习目标了解DES算法原理VS2019创建C++项目,并导入openssl库学会OpenSSL DES算法加解密接口加密文件并做PKCS7 Padding 数据填充解密数据并做数据填充解析课程特点    面向工程应用    市面上的一些密码学课程和密码学的书籍,很多都是从考证出发,讲解算法原理并不面向工程应用,而我们现在缺少的是工程应用相关的知识,本课程从工程应用出发,每种技术都主要讲解其在工程中的使用,并演示工程应用的代码。    从零实现部分算法    课程中实现了base16编解码 ,XOR对称加解密算法,PKCS7 pading数据填充算法,通过对一些简单算法的实现,从而加深对密码学的理解。    理论与实践结合    课程如果只是讲代码,同学并不能理解接口背后的原理,在项目设计中就会留下隐患,出现错误也不容易排查出问题。    如果只讲理论,比如对密码学的一些研究,对于大部分从事工程应用的同学并没有必要,而是理论与实践结合,一切为了工程实践。    代码现场打出    代码不放在ppt而是现场打出,更好的让学员理解代码编写的逻辑,老师现场敲出代码正是展示出了工程项目的思考,每个步骤为什么要这么做,考虑了哪些异常,    易学不枯燥    课程为了确保大部分人开发者都学得会,理解算法原理(才能真正理解算法特性),学会工程应用(接口调用,但不局限接口调用,理解接口背后的机制,并能解决工程中会出现的问题),阅读算法源码但不实现密码算法,,并能将密码学投入到实际工程中,如果是想学习具体的加密算法实现,请关注我后面的课程。课程用到的技术    课程主要演示基于 VS2019 C++,部分演示基于ubuntu 18.04 GCC makefile    如果没有装linux系统,对本课程的学习也没有影响    课程中的OpenSSL基于最新的3.0版本,如果是openss 1.1.1版本也支持,再低的版本不支持国密算法。 课程常见问题课程讲解用的什么平台和工具?    课程演示主要在windows,基于VS2019 ,一些项目会移植到Linux在ubuntu18.04上我不会Linux能否学习本门课程?    可以的,课程主要在Windows上,Linux部分只是移植,可以暂时跳过,熟悉了Linux再过来看我不会C/C++ 语言是否能学习本门课程?    至少要会C语言,C++特性用得不多,但做了一个封装,可以预习一些C++基础。会不会讲算法实现,会不会太难学不会?    课程偏工程应用,具体的AES,椭圆曲线、RSA等算法只通过图示讲原理,一些简单hash算法会读一些源码,并不去实现,课程中会单独实现简洁的XOR对称加密和base16算法(代码量不大易懂)。其他的应用我们都基于OpenSSL3.0的SDK调用算法。课程提供源码和PPT吗?    课程中所有讲解的源码都提供,课程的上课的ppt也提供,PPT提供pdf版,只可以用于学习,不得商用,代码可以用于商用软件项目,涉及到开源系统部分,需要遵守开源的协议,但不得用于网络教学。要观看全部内容请点击c++实战区块链核心密码学-基于opensslhttps://edu.csdn.net/course/play/29593

3,881

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 其它技术问题
社区管理员
  • 其它技术问题社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧