由于项目需要,使用openssl编写一段ECDH代码实现网络两端实体的密钥交换。

虽然对openssl不熟悉,但也开始做。

最先参照的是openssl官方wiki上的Elliptic Curve Diffie Hellman:http://wiki.openssl.org/index.php/Elliptic_Curve_Diffie_Hellman

直接使用文中的代码。不过其中有段代码需要替换:

/* Get the peer's public key, and provide the peer with our public key -* how this is done will be specific to your circumstances */peerkey = get_peerkey(pkey);

我以为只要将这pkey和peerkey指向的密钥块通过网络交换一下就行了。

先不经过网络交换这两个密钥数据,在本地测试,完全通过。但是,一涉及网络交换,程序就崩溃,并爆出内存错误。

总以为是外围程序的问题,调试了好久好久……

直到后来,最后打印出pkey和peerkey指向的类型为EVP_PKEY的数据来看,才发现EVP_PKEY占存储量很小(32字节),这才发现奇怪。因为密钥块一般挺大的。

在openssl库安装路径include目录中找到evp.h,打开查看,发现:

struct evp_pkey_st{int type;int save_type;int references;const EVP_PKEY_ASN1_METHOD *ameth;ENGINE *engine;union  {char *ptr;
#ifndef OPENSSL_NO_RSAstruct rsa_st *rsa;   /* RSA */
#endif
#ifndef OPENSSL_NO_DSAstruct dsa_st *dsa;   /* DSA */
#endif
#ifndef OPENSSL_NO_DHstruct dh_st *dh;  /* DH */
#endif
#ifndef OPENSSL_NO_ECstruct ec_key_st *ec;  /* ECC */
#endif} pkey;int save_parameters;STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */} /* EVP_PKEY */;

这下明白了,原来在网络上传输的我以为的“密钥块”原来是一堆指针!(而且是公私密钥对的指针。。。。)

于是得想办法解决。找到这个帖子:

How does one access the raw ECDH public key, private key and params inside OpenSSL's EVP_PKEY structure?

http://stackoverflow.com/questions/18155559/how-does-one-access-the-raw-ecdh-public-key-private-key-and-params-inside-opens

文中指出要进行公钥的序列化。

然后挨个搜索API的说明,花了不少时间。又是一阵子调试……

最后还是卡在反序列化过程中EC_KEY_set_public_key() to get an EC_KEY和EC_KEY to EVP_PKEY_set1_EC_KEY上了。

心想只好换一种方法了。调试途中在google搜索EC_POINT_point2oct关键字时发现了一个页面:

OpenSSL - User - ECDH http://openssl.6102.n7.nabble.com/ECDH-td22150.html

3楼Rick的回复给的代码比较好。采用并改进,调试之。

最终得到完整的ECDH代码:

#include <openssl/ssl.h>
#define ECDH_SIZE 33void handleErrors()
{printf("Error occurred.\n");
}
static void disp(const char *str, const void *pbuf, const int size)
{int i=0;if(str != NULL){printf("%s:\n", str);}if(pbuf != NULL && size > 0){for(i=0;i<size;i++)printf("%02x ", *((unsigned char *)pbuf+i));putchar('\n');}putchar('\n');
}
int main() {/* alice */EC_KEY *ecdh = EC_KEY_new();EC_POINT *point = NULL;EC_POINT *point2c;EC_GROUP *group;unsigned char pubkey[ECDH_SIZE];unsigned char shared[ECDH_SIZE];int len;//Generate Publicecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);//NID_secp521r1EC_KEY_generate_key(ecdh);point = EC_KEY_get0_public_key(ecdh);group = EC_KEY_get0_group(ecdh);if(0 == (len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, pubkey, ECDH_SIZE, NULL))) handleErrors();printf("len=%d\n",len);/* bob */EC_KEY *ecdh2 = EC_KEY_new();EC_POINT *point2 = NULL;EC_POINT *pointc;EC_GROUP *group2;unsigned char pubkey2[ECDH_SIZE];unsigned char shared2[ECDH_SIZE];int len2;//Generate Publicecdh2 = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);//NID_secp521r1EC_KEY_generate_key(ecdh2);point2 = EC_KEY_get0_public_key(ecdh2);group2 = EC_KEY_get0_group(ecdh2);if(0 == (len2 = EC_POINT_point2oct(group2, point2, POINT_CONVERSION_COMPRESSED, pubkey2, ECDH_SIZE, NULL))) handleErrors();printf("len2=%d\n",len);/* alice *///ComputeKeypoint2c = EC_POINT_new(group);EC_POINT_oct2point(group, point2c, pubkey2, ECDH_SIZE, NULL);if (0 != EC_POINT_cmp(group, point2, point2c, NULL)) handleErrors();if(0 == (len = ECDH_compute_key(shared, ECDH_SIZE, point2c, ecdh, NULL))) handleErrors();printf("len=%d\n",len);disp("shared", shared, len);/* bob *///ComputeKeypointc = EC_POINT_new(group2);EC_POINT_oct2point(group2, pointc, pubkey, ECDH_SIZE, NULL);if (0 != EC_POINT_cmp(group2, point, pointc, NULL)) handleErrors();if(0 == (len2 = ECDH_compute_key(shared2, ECDH_SIZE, pointc, ecdh2, NULL))) handleErrors();printf("len2=%d\n",len2);disp("shared2", shared2, len2);/* alice */EC_POINT_free(pointc);EC_KEY_free(ecdh);/* bob */EC_POINT_free(point2c);EC_KEY_free(ecdh2);printf("To the end\n");return 0;
}

之后抽象、整理封装后的ECDH代码:

#include <openssl/ssl.h>
#define ECDH_SIZE 33void handleErrors()
{printf("Error occurred.\n");
}
static void disp(const char *str, const void *pbuf, const int size)
{int i=0;if(str != NULL){printf("%s:\n", str);}if(pbuf != NULL && size > 0){for(i=0;i<size;i++)printf("%02x ", *((unsigned char *)pbuf+i));putchar('\n');}putchar('\n');
}static EC_KEY *genECDHtemppubkey(unsigned char *pubkey)
{int len;EC_KEY *ecdh = EC_KEY_new();//Generate Publicecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);//NID_secp521r1EC_KEY_generate_key(ecdh);const EC_POINT *point = EC_KEY_get0_public_key(ecdh);const EC_GROUP *group = EC_KEY_get0_group(ecdh);//unsigned char *pubkey = malloc(ECDH_SIZE);if(0 == (len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, pubkey, ECDH_SIZE, NULL))) handleErrors();printf("len=%d\n",len);//return pubkey;return ecdh;
}static unsigned char *genECDHsharedsecret(EC_KEY *ecdh, unsigned char *peerkey, size_t secret_len)
{int len;unsigned char *shared = malloc(ECDH_SIZE);const EC_GROUP *group = EC_KEY_get0_group(ecdh);//ComputeKeyEC_POINT *point_peer = EC_POINT_new(group);EC_POINT_oct2point(group, point_peer, peerkey, ECDH_SIZE, NULL);//if (0 != EC_POINT_cmp(group, point2, point2c, NULL)) handleErrors();if(0 == (len = ECDH_compute_key(shared, secret_len, point_peer, ecdh, NULL))) handleErrors();printf("len=%d\n",len);disp("shared", shared, secret_len);return shared;
}int main() {unsigned char *keydata = malloc(ECDH_SIZE);unsigned char *keydata2 = malloc(ECDH_SIZE);EC_KEY *ecdh = genECDHtemppubkey(keydata);EC_KEY *ecdh2 = genECDHtemppubkey(keydata2);unsigned char *ECDH_keydata = genECDHsharedsecret(ecdh2, keydata, ECDH_SIZE-1);unsigned char *ECDH_keydata2 = genECDHsharedsecret(ecdh, keydata2, ECDH_SIZE-1);printf("To the end\n");free(keydata);free(keydata2);EC_KEY_free(ecdh);EC_KEY_free(ecdh2);free(ECDH_keydata);free(ECDH_keydata2);return 0;
}

调试时在“ECDH_SIZE-1”的问题上纠结了好一阵子,不小心把EC_POINT_oct2point中参数ECDH_SIZE换成值为ECDH_SIZE-1的secret_len了;导致ECDH_compute_key一直返回-1,怎么搜索都得不到解决。

最后还是耐心的一步步调试、对比前面参考的源码、调整变量数值,终于解决。编译通过,执行的非常好。

耐心真的是非常重要,失之毫厘差之千里。

参考资料:

ECC加密算法原理入门介绍

http://blog.csdn.net/sahusoft/article/details/6868016

ECDH密钥交换的C程序相关推荐

  1. secp256k1的结构——ECDH密钥交换

    2021SC@SDUSC secp256k1的结构--ECDH密钥交换 ECDH地址 共享密钥ECDH 在加密通信过程中可以使用Diffie Hellman密钥交换来进行密钥分发,经过密钥交换之后相当 ...

  2. primekey证书服务器,使用 OpenSSL 制作 ECDH 密钥交换证书

    前言 对于 ECDH,Wikipedia 如下描述: Elliptic curve Diffie–Hellman (ECDH) is an anonymous key agreement protoc ...

  3. java ecdh秘钥交换_ECDH密钥交换的C程序

    由于项目需要,使用openssl编写一段ECDH代码实现网络两端实体的密钥交换. 虽然对openssl不熟悉,但也开始做. 最先参照的是openssl官方wiki上的Elliptic Curve Di ...

  4. ECDH 密钥交换举例(ECDH Key Exchange - Examples)

    现在,让我们用Python实现ECDH算法(Elliptic Curve Diffie–Hellman Key Exchange). 我们将使用Python中用于ECC的tinyec库: pip in ...

  5. QQ安卓协议8.2 ecdh 密钥交换

    ps:使用openssl库c++ ,java有自带 或者安卓手机系统自带openssl库 QQ ecdh 协议算法生成规则: 初始会有一个默认的49字节长度tk:(一个默认的密钥) 使用曲线为:711 ...

  6. java ecdh秘钥交换_DH密钥交换和ECDH原理(转)

    下面我们以Alice和Bob为例叙述Diffie-Hellman密钥交换的原理. 1,Diffie-Hellman交换过程中涉及到的所有参与者定义一个组,在这个组中定义一个大质数p,底数g. 2,Di ...

  7. 了解一下密钥交换算法ECDH

    搬一下别人的解释: 下面我们以Alice和Bob为例叙述Diffie-Hellman密钥交换的原理. 1,Diffie-Hellman交换过程中涉及到的所有参与者定义一个组,在这个组中定义一个大质数p ...

  8. DH密钥交换和ECDH原理

    DH密钥交换和ECDH原理 上述的就是DH密钥交互的图表: 可以这么理解,A与B想要生成只有彼此知道的密钥,而使得自己本地产生的私钥,不被对方知道,包括第三方的Eve. 此时的Alice 和Bob 彼 ...

  9. java ecdh秘钥交换_了解一下密钥交换算法ECDH

    https://www.jianshu.com/p/b26cd2bfdc28 搬一下别人的解释: 下面我们以Alice和Bob为例叙述Diffie-Hellman密钥交换的原理. 1,Diffie-H ...

最新文章

  1. xshell使用命令总结
  2. LNMP - Nginx配置防盗链
  3. 《敏捷敬业度》作者访谈
  4. 从服务器上的数据库备份到本地
  5. 计算机网络——链路层之流量控制和可靠传输机制
  6. docker mysql日志_面试官问:了解Mysql主从复制原理么?我呵呵一笑
  7. 电子计算机厂 四月份生产计,一题多解 分数和百分数应用题(1)
  8. Hive数仓之拉链表(原理、设计以及在Hive中的实现)
  9. 网络传输---HttpURLConnection
  10. Windows Forms Programming In C# 读书笔记 - 第三章 Dialogs (2)
  11. Linux 下的这些高效指令,是你快速入门运维的神器
  12. 三菱PlC程序大型项目QCPU+QD77MS16 包含一套完整的电气开发系统资料(包含plc程序,触摸屏程序,伺服模块设置程序,程序开发地址规划表)
  13. VMware虚拟机安装win10 32位
  14. 计算机行业未来的规划模板,计算机专业个人职业规划优秀模板
  15. 代码不规范,亲人两行泪——DTO
  16. python登陆pc微信_GitHub - ccboby/WechatPCAPI: 微信PC版的API接口,可通过Python调用微信获取好友、群、公众号列表,并收发消息等功能。...
  17. Windows与ipad共享文件
  18. vim中复制整个别的文件内容
  19. 机器学习--梯度-牛顿-拟牛顿优化算法和实现
  20. javascript设计模式-单体singleton模式(2)

热门文章

  1. 计算机缺失d3dcompiler43.dll,电脑d3dcompiler43.dll文件丢失怎么解决?
  2. matlab 果壳,万能的果壳网啊请问如何制作DNA图?万能的 – 手机爱问
  3. 硬盘对拷/硬盘克隆/硬盘数据迁移工具
  4. 算法比赛经历--蓝桥杯,天梯赛,力扣,牛客,cf,acwing,acm
  5. 【PTA乙级练习题】topic:1001
  6. HTML5+CSS3的学习(一)
  7. 最新某宝x-sign参数生成原理
  8. 前端面试题(附答案)完善中……
  9. maven私服、将项目发布到maven私服、从私服下载jar到本地仓库、将第三方jar安装到本地仓库和maven私服
  10. Ubunbu18.4运行代码bug提示:Successful NUMA node read from SysFS had negative value (-1)