Diffile-Hellman密钥交换协议

作者: hxd

日期: 2025年3月28日


Diffie-Hellman(迪菲-赫尔曼)是一种密钥交换协议,由 Whitfield Diffie 和 Martin Hellman 在 1976 年提出。它是现代密码学中最重要的协议之一,用于在不安全的通信渠道上安全地交换密钥。Diffie-Hellman 协议的核心思想是允许双方通过公开的通信渠道生成一个共享的密钥,而无需事先共享任何秘密信息。

Diffie-Hellman 的核心概念

  1. 密钥交换的目标
    • 通信双方(例如 Alice 和 Bob)希望生成一个共享的密钥,用于后续的加密通信(如对称加密)。
    • 这个密钥需要在公开的通信渠道上生成,即使攻击者监听了通信内容,也无法推导出共享密钥。
  2. 数学基础
    • Diffie-Hellman 基于离散对数问题的数学难题。
    • 它使用模幂运算大素数的性质来确保安全性。
  3. 协议流程
    • 双方协商两个公开的参数:一个大素数$p$和一个生成元$g$($g$是模$p$的一个原根)。
    • 双方各自选择一个私密的随机数($a$和$b$),并计算自己的公钥:
      • Alice 的公钥:$A = g^a \mod p$
      • Bob 的公钥:$B = g^b \mod p$
    • 双方交换公钥。
    • 双方使用对方的公钥和自己的私钥计算共享密钥:
      • Alice 计算:$S = B^a \mod p$
      • Bob 计算:$S = A^b \mod p$
    • 由于$S = g^{ab} \mod p$,双方最终得到相同的共享密钥。

Diffie-Hellman 的示例

  1. 参数选择
    • 选择一个大素数$p = 23$和一个生成元$g = 5$。
  2. 私钥选择
    • Alice 选择一个私钥$a = 6$,计算公钥$A = 5^6 \mod 23 = 8$。
    • Bob 选择一个私钥$b = 15$,计算公钥$B = 5^{15} \mod 23 = 19$。
  3. 交换公钥
    • Alice 发送$A = 8$给 Bob。
    • Bob 发送$B = 19$给 Alice。
  4. 计算共享密钥
    • Alice 计算$S = B^a \mod p = 19^6 \mod 23 = 2$。
    • Bob 计算$S = A^b \mod p = 8^{15} \mod 23 = 2$。
    • 双方得到相同的共享密钥$S = 2$。

Diffie-Hellman 的安全性

  1. 离散对数问题
    • 攻击者即使知道$p, g, A, B$,也无法轻易计算出$a$或$b$,因为计算离散对数(即从$A = g^a \mod p$中求出$a$)在计算上是不可行的。
  2. 中间人攻击
    • Diffie-Hellman 本身不提供身份验证,因此容易受到中间人攻击(Man-in-the-Middle Attack)。
    • 为了解决这个问题,通常需要结合数字签名或其他身份验证机制。

Diffie-Hellman 的应用

  1. TLS/SSL
    • Diffie-Hellman 是 TLS/SSL 协议中密钥交换的一种常用方法(如 DHE 和 ECDHE)。
  2. VPN
    • 许多 VPN 协议(如 IPsec)使用 Diffie-Hellman 来建立安全的通信通道。
  3. SSH
    • SSH 协议也使用 Diffie-Hellman 来协商会话密钥。

Diffie-Hellman 的变种

  1. 椭圆曲线 Diffie-Hellman(ECDH)
    • 基于椭圆曲线密码学,提供更高的安全性和更小的密钥长度。
  2. 静态 Diffie-Hellman
    • 使用固定的公钥和私钥,适用于长期通信。

代码实现

C++实现

#include<iostream>
#include<cmath>
using namespace std;

//计算a^b mod P
long long power(long long a, long long b, long long P)
{
if (b == 1)return a;
else return (long long)pow(a, b) % P;//显式类型转化
}
//试除法判断是不是素数
bool isPrime(long long n)
{
for (long long i = 1; i <= sqrt(n); i++)
{
if (n % i == 0)
{
return false;
}
}
return true;
}

//判断是否是原根
bool isOriginRoot(long long g,long long P)
{
for (; g <= P; g++)
{
if ((int)pow(g, P - 1) % P == 1)
{
cout << g << "is Origin Root" << endl;
return true;
}
else
{
return false;
}
}
}
int main()
{
long long P, G=2, x, a, y, b, ka, kb;
int seed;
cout << "Please enter a seed: ";
cin >> seed;
srand(seed);
//P是一个大素数
while (1)
{
P = rand();
cout << P << endl;
if (isPrime(P))
{
cout << P << " is a prime ." << endl;
break;
}
}
while (1)
{
if (isOriginRoot(G, P))
{
break;
}
}
cout << "The value of P : " << P << endl;

cout << "The value of G :" << G << endl;

//Alice will choose the private key a
a =rand()%P;
cout << "The private key a for Alice : "<<a<< endl;
x = power(G, a, P);//get the Alice public key

//Bob will choose the private key b
b = rand() % P;
cout << "The private key b for Bob : " << b << endl;
y = power(G, b, P);//get the Bob public key

//Generating the secret key after exchange
ka = power(y, a, P);
kb = power(x, b, P);
cout << "Secret key for the Alice is :" << ka << endl;

cout << "Secret key for the Bob is : " << kb << endl;

return 0;
}