天天看點

使用 openssl 實作 DH 算法及其中間人攻擊

  1. 生成 DH 密鑰對
//! \param prime. DH 的 prime.
//! \param gen. DH 的 gen.
//! \param dh. 傳回資料.
//! \return. 成功與否.
int generate_dh_key(const char *prime, const char *gen, DH *dh) 
{
	BIGNUM *p = BN_new();
	BIGNUM *g = BN_new();

	BN_hex2bn(&p, prime);
	BN_hex2bn(&g, gen);
	DH_set0_pqg(dh, p, NULL, g);

	/* generate key */
	if (1 != DH_generate_key(dh)) {
		perror("DH_generate_key failed!");
		return -1;
	}

	return 0;
}

           
  1. 生成 DH 共享密鑰,此處有坑:使用 openssl DH_compute_key() 函數計算 DH 密鑰長度不對的問題
//! \param dh. DH,其中有本端的公鑰和私鑰.
//! \param peer_pub_key. 對端 DH 公鑰.
//! \param peer_pub_key_len. 對端 DH 公鑰長度.
//! \param shared_key. 輸出 DH 共享密鑰.
//! \return. DH 共享密鑰長度.
int gene_shared_key(DH *dh, uint8_t *peer_pub_key, 
		uint16_t peer_pub_key_len, unsigned char *shared_key) {
	BIGNUM *p_pub_key = BN_bin2bn(peer_pub_key, peer_pub_key_len, NULL);

	/* computer shared_dh_secret */
	int shared_key_len = DH_compute_key_padded(shared_key, p_pub_key, dh);
	if(-1 == shared_key_len) {
		perror("DH_compute_key_padded failed!");
		return -1;
	}

	return shared_key_len;
}
           
  1. 中間人攻擊
  • 截獲雙方發送的 DH 公共值
  • 修改為自己的公共值發送給雙方
  • 使用兩端的公共值同自身的 dh 分别生成中間人到用戶端以及中間人到伺服器的共享密鑰
  • 實作中間人