DH密钥协商算法
RSA算法再一定程度熵解决了密钥配送问题,但也可以用DH密钥协商算法来解决密钥配送问题。DH密钥协商算法时基于离散对数问题。DH(Diffie-Hellman)密钥协商是由Whitfield Diffie和Martin Hellman提出,该算法允许通讯双方再不安全的信道交换数据,从而协商出一个会话密钥。
DH密钥协商原理
- DH共享参数
Alice和Bob进行DH密钥协商之前双方要有共同的DH共享参数即大素数p和生成源a,为了保证DH协商的安全性,大素数p的长度不应小于2048bit(256字节),RFC7919 Negotiated Finite Field Diffie-Hellman Ephemeral Parameters for Transport Layer Security (TLS)
中规定了5组DH共享参数可以直接用里面的。
- DH密钥协商
1.Alice选择一个随机数x(1<=x<=p-1),算法得到公开参数A≡a^x mod p
发送给Bob
2.Bob选择一个随机数y(1<=y<=p-1),算法得到公开参数B≡a^y mod p
发送给Alice
3.Bob收到A并计算得到共享密钥参数k≡A^y mode p → (a^x)^y mod p → a^xy mod p
4.Alice收到B并计算得到共享密钥参数k≡B^y mode p → (a^y)^x mod p → a^xy mod p
5.最终的k就是用于对称加密的会话密钥,如下图
- DH密钥协商的安全性
DH密钥协商不会对公开参数的发送者进行身份认证,因此无法阻止主动攻击者,如果攻击Mallory入侵了Alice和Bob的非安全通道,当Alice和Bob进行DH密钥协商时,攻击者Mallory对于Alice来说冒充Bob,对于Bob来说冒充Alice,这样就能对Alice和Bob之间发送的信息进行解密,身份认证的问题需要加入ECDSA或者RSA。
下面是在mbedtls\programs\pkey
目录下
dh_client.c
,DH客户端
dh_server.c
,DH服务器
dh_genprime.c
,产生DH共享参数,保存在dh_prime.txt
rsa_genkey.c
,产生RSA密钥对,保存在rsa_priv.txt、rsa_pub.txt
这几个文件表达的意思,这里DH协商用RSA来做身份认证。
DH协商例子
其实上面的dh_client.c
、dh_server.c
就是DH协商的例子,这里通过内存共享的方式模拟网络通讯获得DH公钥,注意这里没有进行身份认证。要打开以下宏
#define MBEDTLS_AES_C
#define MBEDTLS_SHA256_C
#define MBEDTLS_ENTROPY_C
#define MBEDTLS_CTR_DRBG_C
#define MBEDTLS_MD_C
#define MBEDTLS_BIGNUM_C 开启大数计算
#define MBEDTLS_DHM_C 开启DH密钥协商模块
#define MBEDTLS_GENPRIME 开启大素数生成
#define MBEDTLS_AES_ROM_TABLES
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include "mbedtls/dhm.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/platform.h"
#define assert_exit(cond, ret) \
do { if (!(cond)) { \
printf(" !. assert: failed [line: %d, error: -0x%04X]\n", __LINE__, -ret); \
goto cleanup; \
} } while (0)
#define GENERATOR "2" //生成元
//大素数
#define T_P "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1D8B9C583CE2D3695" \
"A9E13641146433FBCC939DCE249B3EF97D2FE363630C75D8F681B202AEC4617A"\
"D3DF1ED5D5FD65612433F51F5F066ED0856365553DED1AF3B557135E7F57C935"\
"984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE73530ACCA4F483A797A"\
"BC0AB182B324FB61D108A94BB2C8E3FBB96ADAB760D7F4681D4F42A3DE394DF4"\
"AE56EDE76372BB190B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F61"\
"9172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD733BB5FCBC2EC22005"\
"C58EF1837D1683B2C6F34A26C1B2EFFA886B423861285C97FFFFFFFFFFFFFFFF"
/*
static int entropy_source(void *data, uint8_t *output, size_t len, size_t *olen)
{
uint32_t seed;
seed = sys_rand32_get();
if (len > sizeof(seed)) {
len = sizeof(seed);
}
memcpy(output, &seed, len);
*olen = len;
return 0;
}*/
static void dump_buf(char *info, uint8_t *buf, uint32_t len)
{
mbedtls_printf("%s", info);
for (int i = 0; i < len; i++) {
mbedtls_printf("%s%02X%s", i % 16 == 0 ? "\n ":" ",
buf[i], i == len - 1 ? "\n":"");
}
}
int main(void)
{
int ret = 0;
size_t n = 0;
const char *pers = "simple_dh";
uint8_t cli_pub[256], cli_secret[256];
uint8_t srv_pub[256], srv_secret[256];
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_dhm_context dhm_cli, dhm_srv;
mbedtls_dhm_init(&dhm_cli); //初始化dhm_cli结构体
mbedtls_dhm_init(&dhm_srv); //初始化dhm_srv结构体
mbedtls_entropy_init(&entropy); //初始化熵结构体
mbedtls_ctr_drbg_init(&ctr_drbg);//初始化随机数结构体
/*
mbedtls_entropy_add_source(&entropy, entropy_source, NULL,
MBEDTLS_ENTROPY_MAX_GATHER, MBEDTLS_ENTROPY_SOURCE_STRONG);*/
//根据个性化字符串更新种子
ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
(const unsigned char *) pers, strlen(pers));
assert_exit(ret == 0, ret);
mbedtls_printf("\n . setup rng ... ok\n\n");
mbedtls_mpi_read_string(&dhm_srv.P, 16, T_P);//设置dh_srv共享参数之大素数
mbedtls_mpi_read_string(&dhm_srv.G, 10, GENERATOR);//设置dh_srv共享参数之生成元
dhm_srv.len = mbedtls_mpi_size(&dhm_srv.P);//大素数长度
mbedtls_mpi_read_string(&dhm_cli.P, 16, T_P);//设置dh_cli共享参数之大素数
mbedtls_mpi_read_string(&dhm_cli.G, 10, GENERATOR);//设置dh_cli共享参数之生成元
dhm_cli.len = mbedtls_mpi_size(&dhm_cli.P);//大素数长度
mbedtls_printf(" 1. dh generate 2048 bit prime(G, P) ... ok\n");
//生成dh_srv公开参数
ret = mbedtls_dhm_make_public(&dhm_srv, 256, srv_pub, sizeof(srv_pub),
mbedtls_ctr_drbg_random, &ctr_drbg);
assert_exit(ret == 0, ret);
dump_buf(" 2. dh server generate public parameter:", srv_pub, sizeof(srv_pub));
//生成dh_cli公开参数
ret = mbedtls_dhm_make_public(&dhm_cli, 256, cli_pub, sizeof(cli_pub),
mbedtls_ctr_drbg_random, &ctr_drbg);
assert_exit(ret == 0, ret);
dump_buf(" 3. dh client generate public parameter:", cli_pub, sizeof(cli_pub));
//这里模拟dh_srv获得dh_cli发来的公开参数
ret = mbedtls_dhm_read_public(&dhm_srv, cli_pub, sizeof(cli_pub));
assert_exit(ret == 0, ret);
mbedtls_printf(" 4. dh server read public ... ok\n");
//这里模拟dh_cli获得dh_srv发来的公开参数
ret = mbedtls_dhm_read_public(&dhm_cli, srv_pub, sizeof(srv_pub));
assert_exit(ret == 0, ret);
mbedtls_printf(" 5. dh client read public ... ok\n");
//dh_srv计算出共享密钥
ret = mbedtls_dhm_calc_secret(&dhm_srv, srv_secret, sizeof(srv_secret),
&n, mbedtls_ctr_drbg_random, &ctr_drbg);
assert_exit(ret == 0, ret);
dump_buf(" 6. dh server generate secret:", srv_secret, sizeof(srv_secret));
//dh_cli计算出共享密钥
ret = mbedtls_dhm_calc_secret(&dhm_cli, cli_secret, sizeof(cli_secret),
&n, mbedtls_ctr_drbg_random, &ctr_drbg);
assert_exit(ret == 0, ret);
dump_buf(" 7. dh client generate secret:", cli_secret, sizeof(cli_secret));
//这里判断dh_srv 、dh_cli各自计算得到这共享密钥知否一致
ret = memcmp(cli_secret, srv_secret, sizeof(srv_secret));
assert_exit(ret == 0, ret);
mbedtls_printf(" 8. dh checking secrets ... ok\n\n");
cleanup:
mbedtls_dhm_free(&dhm_cli); //释放dh结构体
mbedtls_dhm_free(&dhm_srv);
mbedtls_entropy_free(&entropy); //释放熵结构体
mbedtls_ctr_drbg_free(&ctr_drbg);//释放随机数结构体
return ret;
}
运行如下
. setup rng ... ok
1. dh generate 2048 bit prime(G, P) ... ok
2. dh server generate public parameter:
3A 32 A4 91 83 9D 1C 1C BD 8B 58 42 5C 9C F1 16
AC E5 98 93 77 01 99 FA 07 5C 13 7F C7 FB AF 5D
42 51 62 F0 93 C9 B5 73 D1 DC EC C2 2B 3C D2 6B
B5 4E E1 CA B7 08 34 F7 43 B6 19 16 C3 94 12 72
D4 55 C1 9D 08 BA 1A 75 EE 8C A5 09 E3 D4 35 1C
52 04 7B 14 54 47 3A C6 C4 E6 11 9C BA 83 B3 95
63 12 17 08 98 20 D5 FF 77 70 1C 31 62 0A 37 37
04 EF 94 B8 3E FF 6B 21 D2 01 8D 71 EA 1E 98 A1
40 F8 A9 23 72 49 39 AB CF D4 F8 68 EA 9D F8 77
CE 81 AC E5 4B 65 E3 45 6F AD 26 B9 6D BA 09 B1
0D BD 6E F9 C7 92 2A 6E EA 6B 02 58 2A 83 C2 11
1E AD 73 87 12 3F 42 41 55 10 6E 57 A9 37 20 02
3D 0B 7F DA B0 AB 2B 14 98 66 FF 48 D5 CE 96 31
9D BB C0 4A 46 4C 6F 45 2A 93 68 94 40 8B F5 5B
E5 F9 95 C0 24 00 CD E5 6C 90 ED 84 75 05 5C 26
B8 7B 82 BB FD DC D2 41 AD 5E 7E C6 B4 A7 4D 0C
3. dh client generate public parameter:
C5 6E C2 B0 60 88 E2 28 69 AD C0 5B 9E 00 41 4E
EA A4 D0 4F E2 CA EC 03 37 45 12 6B 1C 9C 86 31
34 1C C3 83 4F 4B E4 C9 FC FE C6 C3 8B 8F ED B6
EF A0 FD A0 28 3E F1 54 73 B0 9D 58 77 F4 33 FF
55 A0 4D 32 98 47 06 F7 4E B1 C9 45 92 7B FC 25
E7 CF B8 83 16 9A F0 E0 9B 77 20 6C 58 C3 8D 9B
E9 4F AA D0 26 F6 B3 B6 CB B3 1F 46 50 F7 06 91
7A 9E BC DD E7 5E 74 3B 09 A6 DD EA 0F BD 97 18
1B EF 6B 82 7E 54 DC F5 C9 76 75 BA B4 51 E7 58
96 94 03 A2 78 9D A0 E5 48 22 5E 79 A7 1D AC 48
41 F8 EA 02 91 F1 3F 6A 85 A8 01 47 40 6F 6A C2
80 42 CE E6 F3 B5 A5 84 00 8D AA 75 0B 85 92 9D
0E C5 CA A0 AF 0E 9A 44 A1 E4 85 79 54 7D 1D FF
53 64 AA 02 26 44 BF D3 44 9B 13 9F 7C 60 33 15
6F 36 54 A2 25 EE D1 83 1E 18 0D 85 C0 77 6E FA
73 C6 ED 1D 23 28 AD 48 C1 23 8E F6 BB C6 81 48
4. dh server read public ... ok
5. dh client read public ... ok
6. dh server generate secret:
3B F9 8F 25 5C 32 38 43 6A 3E 93 96 98 A5 55 5D
9E 99 A4 DC B2 34 B8 81 D4 17 26 B4 AC 2A 5B F8
7D AE A2 72 D4 7C CF F7 89 34 45 2C 9F DA 01 77
54 AE B4 66 F3 5E 2B 2F 4C B1 93 69 3A 32 59 57
A8 0F 84 8D FC 1C A2 1C D0 2B 40 36 2F 47 54 8A
24 F2 23 D1 EC 7E 48 1E DB 83 6A A4 5B A8 05 05
45 A6 2E 2A 6A 91 45 4C 2F 22 FD 87 E5 3C 55 A8
A6 66 E6 1B FD 9A 56 15 25 39 6E 2A F1 FB E5 CB
2E B0 83 57 7B C6 00 AC A5 4A 4D 5B C7 EC D6 DE
1F C4 3B 6F C7 7A 4A B6 52 D1 52 2D FF 6E 77 8B
DC 29 7B B5 E0 F3 46 23 83 58 8D 02 6D 7E 73 6D
B8 FC E7 93 F8 83 21 29 3D E8 04 4E 07 60 EF B7
A6 F0 BB 8A 41 1A 4E 9F A0 B5 A4 93 64 16 8F A5
D3 7C B4 D5 4D 20 EC C4 91 2A 57 1D 3F 11 FC 5F
61 5A AF CA 78 96 58 1E CE 00 0C 2A 05 56 14 F7
4E 91 79 5B 62 5C 40 C4 A2 D0 9B 9C 84 F1 5F 96
7. dh client generate secret:
3B F9 8F 25 5C 32 38 43 6A 3E 93 96 98 A5 55 5D
9E 99 A4 DC B2 34 B8 81 D4 17 26 B4 AC 2A 5B F8
7D AE A2 72 D4 7C CF F7 89 34 45 2C 9F DA 01 77
54 AE B4 66 F3 5E 2B 2F 4C B1 93 69 3A 32 59 57
A8 0F 84 8D FC 1C A2 1C D0 2B 40 36 2F 47 54 8A
24 F2 23 D1 EC 7E 48 1E DB 83 6A A4 5B A8 05 05
45 A6 2E 2A 6A 91 45 4C 2F 22 FD 87 E5 3C 55 A8
A6 66 E6 1B FD 9A 56 15 25 39 6E 2A F1 FB E5 CB
2E B0 83 57 7B C6 00 AC A5 4A 4D 5B C7 EC D6 DE
1F C4 3B 6F C7 7A 4A B6 52 D1 52 2D FF 6E 77 8B
DC 29 7B B5 E0 F3 46 23 83 58 8D 02 6D 7E 73 6D
B8 FC E7 93 F8 83 21 29 3D E8 04 4E 07 60 EF B7
A6 F0 BB 8A 41 1A 4E 9F A0 B5 A4 93 64 16 8F A5
D3 7C B4 D5 4D 20 EC C4 91 2A 57 1D 3F 11 FC 5F
61 5A AF CA 78 96 58 1E CE 00 0C 2A 05 56 14 F7
4E 91 79 5B 62 5C 40 C4 A2 D0 9B 9C 84 F1 5F 96
8. dh checking secrets ... ok