mbedtls學習(7)DH密鑰協商

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.cdh_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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章