《openssl 编程》之 DH
第十九章DH
19.1? DH算法介紹
DH算法是W.Diffie和M.Hellman提出的。此算法是最早的公鑰算法。它實質是一個通信雙方進行密鑰協商的協議:兩個實體中的任何一個使用自己的私鑰和另一實體的公鑰,得到一個對稱密鑰,這一對稱密鑰其它實體都計算不出來。DH算法的安全性基于有限域上計算離散對數的困難性。離散對數的研究現狀表明:所使用的DH密鑰至少需要1024位,才能保證有足夠的中、長期安全。
首先,發送方和接收方設置相同的大數數n和g,這兩個數不是保密的,他們可以通過非安全通道來協商這兩個素數;
?????? 接著,他們用下面的方法協商密鑰:
發送方選擇一個大隨機整數x,計算X= g^x mod n ,發送X給接收者;
接收方選擇一個大隨機整數y,計算Y = g^y mod n ,發送Y給發送方;
雙方計算密鑰:發送方密鑰為k1=Y^x mod n,接收方密鑰為k2=X^y mod n。
其中k1=k2=g^(xy) mod n。
其他人可以知道n、g、X和Y,但是他們不能計算出密鑰,除非他們能恢復x和y。DH算法不能抵御中間人攻擊,中間人可以偽造假的X和Y分別發送給雙方來獲取他們的秘密密鑰,所以需要保證X和Y的來源合法性。
19.2? openssl的DH實現
?????? Openssl的DH實現在crypto/dh目錄中。各個源碼如下:
?????? 1)? dh.h
????????????? 定義了DH密鑰數據結構以及各種函數。
?????? 2)??? dh_asn1.c
????????????? DH密鑰參數的DER編解碼實現。
?????? 3)? dh_lib.c
????????????? 實現了通用的DH函數。
?????? 4)? dh_gen.c
????????????? 實現了生成DH密鑰參數。
?????? 5)? dh_key.c
實現openssl提供的默認的DH_METHOD,實現了根據密鑰參數生成DH公私鑰,以及根據DH公鑰(一方)以及DH私鑰(另一方)來生成一個共享密鑰,用于密鑰交換。
?????? 6)dh_err.c
????????????? 實現了DH錯誤處理。
?????? 7)? dh_check.c
????????????? 實現了DH密鑰檢查。
19.3數據結構
DH數據結構定義在crypto/dh/dh.h中,主要包含兩項,如下:
1)??? DH_METHOD
?????? struct dh_method
?????? {
?????? ?????? const char *name;
int (*generate_key)(DH *dh);
?????? ?????? int (*compute_key)(unsigned char *key,const BIGNUM *pub_key,DH *dh);
?????? ?????? int (*bn_mod_exp)(const DH *dh, BIGNUM *r, const BIGNUM *a,
??????????????????????????? const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
??????????????????????????? BN_MONT_CTX *m_ctx);
?????? ?????? int (*init)(DH *dh);
?????? ?????? int (*finish)(DH *dh);
?????? ?????? int flags;
?????? ?????? char *app_data;
?????? ?????? int (*generate_params)(DH *dh, int prime_len, int generator, BN_GENCB *cb);
?????? };
?????? DH_METHOD指明了一個DH密鑰所有的計算方法函數。用戶可以實現自己的DH_METHOD來替換openssl提供默認方法。各項意義如下:
name:DH_METHOD方法名稱。
generate_key:生成DH公私鑰的函數。
compute_key:根據對方公鑰和己方DH密鑰來生成共享密鑰的函數。
?????? bn_mod_exp:大數模運算函數,如果用戶實現了它,生成DH密鑰時,將采用用戶實現的該回調函數。用于干預DH密鑰生成。
?????? init:初始化函數。
?????? finish:結束函數。
?????? flags:用于記錄標記。
?????? app_data:用于存放應用數據。
?????? generate_params:生成DH密鑰參數的回調函數,生成的密鑰參數是可以公開的。
2)??? DH
struct dh_st
?????? {
?????? ?????? /* 其他 */
?????? ?????? BIGNUM *p;
?????? ?????? BIGNUM *g;
?????? ?????? long length; /* optional */
?????? ?????? BIGNUM *pub_key;
?????? ?????? BIGNUM *priv_key;
?????? ?????? int references;
?????? ?????? CRYPTO_EX_DATA ex_data;
?????? ?????? const DH_METHOD *meth;
?????? ?????? ENGINE *engine;
????????????? /* 其他 */
?????? };
?????? p、g、length:DH密鑰參數;
?????? pub_key:DH公鑰;
?????? priv_key:DH私鑰;
?????? references:引用;
?????? ex_data:擴展數據;
?????? meth:DH_METHOD,本DH密鑰的各種計算方法,明確指明了DH的各種運算方式;
?????? engine:硬件引擎。
19.4??主要函數
1)? DH_new
?????? 生成DH數據結構,其DH_METHOD采用openssl默認提供的。
?????? 2)? DH_free
????????????? 釋放DH數據結構。
?????? 3)? DH_generate_parameters
????????????? 生成DH密鑰參數。
?????? 4)? DH_generate_key
????????????? 生成DH公私鑰。
?????? 5)? DH_compute_key
????????????? 計算共享密鑰,用于數據交換。
?????? 6)? DH_check
????????????? 檢查DH密鑰。
?????? 7)? DH_get_default_method
????????????? 獲取默認的DH_METHOD,該方法是可以由用戶設置的。
?????? 8)? DH_get_ex_data
????????????? 獲取DH結構中的擴展數據。
9)??? DH_new_method
生成DH數據結構。
?????? 10)DH_OpenSSL
????????????? 獲取openssl提供的DH_METHOD。
?????? 11)DH_set_default_method
設置默認的DH_METHOD方法,當用戶實現了自己的DH_METHOD時,可調用本函數來設置,控制DH各種計算。
?????? 12)DH_set_ex_data
????????????? 獲取擴展數據。
13)DH_set_method
?????? 替換已有的DH_METHOD。
14)DH_size
?????? 獲取DH密鑰長度的字節數。
15)? DH_up_ref
增加DH結構的一個引用。
?????? 16)DHparams_print
????????????? 將DH密鑰參數輸出到bio中。
17)? DHparams_print_fp
?????? 將DH密鑰參數輸出到FILE中。
19.5??編程示例
?????? #include <openssl/dh.h>
#include <memory.h>
int??? main()
{
?????? DH???????? *d1,*d2;
?????? BIO??????? *b;
?????? int?????????? ret,size,i,len1,len2;
?????? char sharekey1[128],sharekey2[128];
?
?????? /* 構造DH數據結構 */
?????? d1=DH_new();
?????? d2=DH_new();
?????? /* 生成d1的密鑰參數,該密鑰參數是可以公開的 */
?????? 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");
?????? /* 密鑰大小 */
?????? size=DH_size(d1);
?????? printf("DH key1 size : %d\n",size);
?????? /* 生成公私鑰 */
?????? 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");
?????? }
?????? /* 計算共享密鑰 */
?????? len1=DH_compute_key(sharekey1,d2->pub_key,d1);
?????? len2=DH_compute_key(sharekey2,d1->pub_key,d2);
?????? if(len1!=len2)
?????? {
????????????? printf("生成共享密鑰失敗1\n");
????????????? return -1;
?????? }
?????? if(memcmp(sharekey1,sharekey2,len1)!=0)
?????? {
????????????? printf("生成共享密鑰失敗2\n");
????????????? return -1;
?????? }
?????? printf("生成共享密鑰成功\n");
?????? b=BIO_new(BIO_s_file());
?????? BIO_set_fp(b,stdout,BIO_NOCLOSE);
?????? /* 打印密鑰 */
?????? DHparams_print(b,d1);
?????? BIO_free(b);
?????? DH_free(d1);
?????? DH_free(d2);
?????? return 0;
}
本例主要演示了生成DH密鑰以及密鑰交換函數。
總結
以上是生活随笔為你收集整理的《openssl 编程》之 DH的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《openssl 编程》之错误处理
- 下一篇: 《openssl 编程》之 RSA(转)