(1)DH_new 生成DH数据结构,其DH_METHOD采用openssl默认提供的。
(2) DH_generate_parameters
生成DH密钥参数。
临时代码如下:
#include <openssl/bn.h>
#include <openssl/dh.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <iostream>
#include <cassert>
using namespace std;
class Request
{
public:
Request()
{
//补全函数,要求生成 DH 数据结构
m_dh=DH_new();
//生成 DH 密钥参数
//DH_check 检查 DH 密钥
//根据 DH_check 返回结果判断密钥是否符合要求
int ret;
ret = DH_generate_parameters_ex(d1, 64, DH_GENERATOR_2, NULL);
if (ret != 1)
{
printf(“DH_generate_parameters_ex err!\n”);
return -1;
}
/* 检查密钥参数 */
ret = DH_check(d1, &i);
if (ret != 1)
{
printf(“DH_check err!\n”);
if (i&DH_CHECK_P_NOT_PRIME)
printf(“p value is not prime\n”);
if (i&DH_CHECK_P_NOT_SAFE_PRIME)
printf(“p value is not a safe prime\n”);
if (i&DH_UNABLE_TO_CHECK_GENERATOR)
printf(“unable to check the generator value\n”);
if (i&DH_NOT_SUITABLE_GENERATOR)
printf(“the g value is not a generator\n”);
}
printf(“DH parameters appear to be ok.\n”);
// 生成 DH 密钥
/* 生成公私钥 */
ret = DH_generate_key(d1);
if (ret != 1)
{
printf(“DH_generate_key err!\n”);
return -1;
}
/* p和g为公开的密钥参数,因此可以拷贝 */
d2->p = BN_dup(d1->p);
d2->g = BN_dup(d1->g);
/* 生成公私钥,用于测试生成共享密钥 */
ret = DH_generate_key(d2);
if (ret != 1)
{
printf(“DH_generate_key err!\n”);
return -1;
}
/* 检查公钥 */
ret = DH_check_pub_key(d1, d1->pub_key, &i);
if (ret != 1)
{
if (i&DH_CHECK_PUBKEY_TOO_SMALL)
printf(“pub key too small \n”);
if (i&DH_CHECK_PUBKEY_TOO_LARGE)
printf(“pub key too large \n”);
}
}
~Request()
{
if (m_dh)
//释放 DH 数据结构
DH_free(m_dh);
}
void GetSharedNums(BIGNUM *&p, BIGNUM *&g)
{
assert(m_dh);
//自行编写代码,要求如下:
//新建一个 BIGNUM 结构,将 DH_get0_p(m_dh)复制给新建结构返回给 p,错误返回 NULL
p = DH_get0_p(m_dh);
//新建一个 BIGNUM 结构,将 DH_get0_g(m_dh)复制给新建结构返回给 g,错误返回 NULL
g = DH_get0_g(m_dh);
}
void GetPubKey(BIGNUM *&pubkey)
{
assert(m_dh);
//自行编写代码,要求如下:
//新建一个 BIGNUM 结构,将 DH_get0_pub_key(m_dh)复制给新建结构返回,错误返回 NULL
pubkey = DH_get0_pub_key(m_dh);
}
std::string GetPriKey(const BIGNUM *pubkey)
{
//编写一段代码,计算共享密钥
len1=DH_compute_key(sharekey1,d2->pub_key,d1);
len2=DH_compute_key(sharekey2,d1->pub_key,d2);
}
private:
DH *m_dh;
};
class Response
{
public:
//构造函数
Response() : m_dh(NULL) {}
//析构函数
~Response()
{
if (m_dh)
//释放 DH 数据结构
DH_free(m_dh);
}
bool Init(BIGNUM *p, BIGNUM *g)
{
if (!m_dh)
{
m_dh = DH_new();
}
/*编写一段代码,设置 response 的参数 p 和 g*/
}
void GetPubKey(BIGNUM *&pubkey)
{
assert(m_dh);
//DH_get0_priv_key(m_dh)判断结构
assert(DH_get0_priv_key(m_dh));
//新建一个 BIGNUM 结构,将 DH_get0_priv_key(m_dh)复制给新建结构返回,错误返回 NULL
//...这个是啥?
//编写代码,通过 DH_get0_pub_key 获取公钥
pubkey = DH_get0_pub_key(m_dh);
}
std::string GetPriKey(const BIGNUM *pubkey)
{
assert(m_dh);
//声明变量* key 并分配内存空间
unsigned char *key = (unsigned char *)malloc(DH_size(m_dh));
//计算共享密钥,用于数据交换
int rst = DH_compute_key(key, pubkey, m_dh);
if (rst < 0)
{
cout << "error" << endl;
printf("%s", ERR_reason_error_string(ERR_get_error()));
}
char hex[1024];
const char mapping_hex_string[] = "0123456789ABCDEF";
for (int i = 0; i < DH_size(m_dh); i++)
{
hex[i * 2] = mapping_hex_string[key[i] >> 4];
// printf("pDst[i * 2]=%c\n", pDst[i * 2]);
hex[i * 2 + 1] = mapping_hex_string[key[i] & 15];
// printf("pDst[i * 2 + 1]=%c\n", pDst[i * 2 + 1]);
}
printf("ResponseKey=");
for (int i = 0; i < 2 * DH_size(m_dh); i++)
{
printf("%c", hex[i]);
}
printf("\n");
std::string ret(reinterpret_cast<char *>(key));
free(key);
return ret;
}
private:
DH *m_dh;
};
8
int main(void)
{
char hex[1024];
//新建对象
DH *m_dh = DH_new();
//成可在一组用户之间共享的 Diffie-Hellman 参数,并将它们存储在提供的 DH 结构中
//也可以理解为生成合适的质数
int rst = DH_generate_parameters_ex(m_dh, 512, 2, NULL);
//检查 DH 密钥
rst = DH_check(m_dh, &rst);
assert(rst == 1);
const BIGNUM *ppp = DH_get0_p(m_dh);
BIGNUM *x = BN_dup(ppp);
//新建 Request 对象,对应流程图中的步骤①
Request request;
//初始化指针均为 NULL
BIGNUM *p = NULL, *g = NULL;
//新建 BIGNUM 结构
request.GetSharedNums(p, g);
//新建 Response 对象,对应流程图中的步骤③
Response response;
//初始化
bool init = response.Init(p, g);
assert(init);
//初始化 request 和 response 指针均为 NULL
BIGNUM *pubkey_of_request = NULL, *pubkey_of_response = NULL;
//获取 request 公钥
request.GetPubKey(pubkey_of_request);
//获取 response 公钥
response.GetPubKey(pubkey_of_response);
//获取 request 私钥,对应流程图中的步骤②
std::string key1 = request.GetPriKey(pubkey_of_response);
cout << endl;
//获取 response 私钥,对应流程图中的步骤④
std::string key2 = response.GetPriKey(pubkey_of_request);
//判断是私钥是否相同
int cmp = key1.compare(key2);
if (cmp == 0)
{
cout << "协商后的密钥一致" << endl;
}
else
{
cout << "协商后的密钥不一致" << endl;
}
return 0;
}