ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

了解一下密钥交换算法ECDH

2019-08-16 19:37:18  阅读:566  来源: 互联网

标签:ecdh ECDH EC char 算法 密钥 KEY


原文链接:https://www.jianshu.com/p/b26cd2bfdc28

搬一下别人的解释:

下面我们以Alice和Bob为例叙述Diffie-Hellman密钥交换的原理。

1,Diffie-Hellman交换过程中涉及到的所有参与者定义一个组,在这个组中定义一个大质数p,底数g。

2,Diffie-Hellman密钥交换是一个两部分的过程,Alice和Bob都需要一个私有的数字a,b。

下面是DH交换的过程图:

本图片来自wiki

下面我们进行一个实例

1.爱丽丝与鲍伯协定使用p=23以及g=5.

2.爱丽丝选择一个秘密整数a=6, 计算A = g^a mod p并发送给鲍伯。  

A = 5^6 mod 23 = 8. 

3.鲍伯选择一个秘密整数b=15, 计算B = g^b mod p并发送给爱丽丝。  

B = 5^15 mod 23 = 19. 

4.爱丽丝计算s = B a mod p  

19^6 mod 23 = 2. 

5.鲍伯计算s = A b mod p  

8^15 mod 23 = 2. 

 

ECDH密钥交换:

ECDH:

       ECC算法和DH结合使用,用于密钥磋商,这个密钥交换算法称为ECDH。交换双方可以在不共享任何秘密的情况下协商出一个密钥。ECC是建立在基于椭圆曲线的离散对数问题上的密码体制,给定椭圆曲线上的一个点P,一个整数k,求解Q=kP很容易;给定一个点P、Q,知道Q=kP,求整数k确是一个难题。ECDH即建立在此数学难题之上。密钥磋商过程:

假设密钥交换双方为Alice、Bob,其有共享曲线参数(椭圆曲线E、阶N、基点G)。

1) Alice生成随机整数a,计算A=a*G。 #生成Alice公钥

2) Bob生成随机整数b,计算B=b*G。 #生产Bob公钥

3) Alice将A传递给Bob。A的传递可以公开,即攻击者可以获取A。

    由于椭圆曲线的离散对数问题是难题,所以攻击者不可以通过A、G计算出a。

4) Bob将B传递给Alice。同理,B的传递可以公开。

5) Bob收到Alice传递的A,计算Q =b*A#Bob通过自己的私钥和Alice的公钥得到对称密钥Q

6) Alice收到Bob传递的B,计算Q`=a*B#Alice通过自己的私钥和Bob的公钥得到对称密钥Q'

Alice、Bob双方即得Q=b*A=b*(a*G)=(b*a)*G=(a*b)*G=a*(b*G)=a*B=Q' (交换律和结合律),即双方得到一致的密钥Q。

        目前Openssl里面的ECC算法的套件支持是ECDSA/ECDH。在国密的SSL套件中,可以使用ECDSA/ECC(密钥加密传输),ECDSA/ECDH(密钥磋商)两种套件


作者:介和
链接:https://www.jianshu.com/p/b26cd2bfdc28
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

 

测试代码:

#include "stdafx.h"

#include <string.h>
#include <stdio.h>
#include <openssl/ec.h>
#include <openssl/ecdh.h>
#include <openssl/ecdsa.h>
#include <openssl/objects.h>
#include <openssl/err.h>

#define ECDH_SIZE 256

void handleErrors()
{
	printf("Error occurred.\n");
}

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');
}


EC_KEY *genECDHpubkey(unsigned char *pubkey, size_t& lenn)
{
	size_t len;
	int ret;	
	
	//Generate Public
	EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); // NID_secp521r1	
	//或者
	//EC_KEY *ecdh = EC_KEY_new();
	//EC_GROUP *group_ = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); // NID_secp256k1
	//EC_KEY_set_group(ecdh, group_);
	//
	ret = EC_KEY_generate_key(ecdh);
	//
	const EC_POINT *point = EC_KEY_get0_public_key(ecdh);//传输给对方的公钥
	const EC_GROUP *group = EC_KEY_get0_group(ecdh);
	//
	BIGNUM *x = BN_new();
	BIGNUM *y = BN_new();
	if (EC_POINT_get_affine_coordinates_GFp(group, point, x, y, NULL))
	{
		BN_print_fp(stdout, x);
		putc('\n', stdout);
		BN_print_fp(stdout, y);
		putc('\n', stdout);
	}
	BN_free(x);
	BN_free(y);
	//将公钥由POINT格式转成OCT字符串
	if (0 == (len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, pubkey, ECDH_SIZE, NULL)))
	{
		handleErrors();
	}
	printf("len=%d\n",len);
	disp("pubkey", pubkey, len);
	lenn = len;

	return ecdh;
}

unsigned char *genECDHsharedsecret(EC_KEY *ecdh, unsigned char *peerkey, size_t secret_len)
{
	int len, ret;
	unsigned char *shared = (unsigned char *)malloc(ECDH_SIZE);
	const EC_GROUP *group = EC_KEY_get0_group(ecdh);
	
	//ComputeKey
	EC_POINT *point_peer = EC_POINT_new(group);
	if (0 == (ret = EC_POINT_oct2point(group, point_peer, peerkey, secret_len, NULL))) // ECDH_SIZE
	{
		handleErrors();
	}
	//
	if (0 == (len = ECDH_compute_key(shared, ECDH_SIZE-1, point_peer, ecdh, NULL)))
	{
		handleErrors();
	}
	
	printf("len=%d\n",len);
	disp("shared", shared, len);

	return shared;
}


int testECDH()
{
	unsigned char *keydata = (unsigned char *)malloc(ECDH_SIZE);
	unsigned char *keydata2 = (unsigned char *)malloc(ECDH_SIZE);
	size_t len1 = 0, len2 = 0;
	
	EC_KEY *ecdh = genECDHpubkey(keydata, len1);
	EC_KEY *ecdh2 = genECDHpubkey(keydata2, len2);
	
	unsigned char *ECDH_keydata  = genECDHsharedsecret(ecdh2, keydata, len1);//ECDH_SIZE-1
	unsigned char *ECDH_keydata2 = genECDHsharedsecret(ecdh, keydata2, len2);//ECDH_SIZE-1
	if (0== memcmp(ECDH_keydata, ECDH_keydata2, ECDH_SIZE - 1)) //算出来的共享密钥必须相同
	{
		printf("------sharedsecret ok------\n");
	}
	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;
}


int main8(int argc, char *argv[])
{
	return testECDH();
}

运行结果:

shared密钥就是我们后续采用AES等对称算法的Key。

 

参考:

https://www.cnblogs.com/Kalafinaian/p/7392505.html

https://bbs.csdn.net/topics/360001596

https://www.freebuf.com/articles/database/155912.html

https://my.oschina.net/safedead/blog/515386

https://www.cnblogs.com/10zhang/p/9381897.html

https://blog.csdn.net/bravegogo/article/details/63684286

 

标签:ecdh,ECDH,EC,char,算法,密钥,KEY
来源: https://blog.csdn.net/houwenbin1986/article/details/99683910

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有