Diffie-Hellman 算法描述: 目前被许多商业产品交易采用。
DH 算法为公开的密钥算法,发明于1976年。该算法不能用于加密或解密,而是用于密钥的传输和分配。
DH 算法的安全性体现在:在有限域上计算离散对数非常困难,或者说:已知gx 和gy,若不知道x和y,则计算gxy是困难的。
离散对数 :定义素数p的原始根(primitive root)为这样一个数,它能生成1~p-1所有数的一个数。现设a为p的原始根,则
a mod p, a2 mod p,…,ap-1 mod p
两两互不相同,构成一个1~p-1的全体数的一个排列。对于任意数b及素数p的原始根a,可以找到一个唯一的指数i,满足
b=ai mod p, 0<=i<=p-1
则称指数i为以a为底、模P的b的离散对数。
算法描述:
假如Alice 和 Bob在不安全的网络上进行协商共同的密码:
1.Alice和Bob先说好一个大素数p和它的原始根a
2.Alice随机产生一个数x, 计算X=ax mod p, 然后把X发给Bob;
3. Bob秘密产生一个随机数y,计算Y=ay mod p, 然后把Y发给Alice;
4.Alice计算k=Yx mod p;
5.Bob计算k*=Xy mod p;
因为
k=Yx mod p= (ay) x mod p=(a x)y mod p=X y mod p= k*
所以 k= k*。
不安全线路上的窃听者只能得到a、p、X、Y,除非能计算离散对数x和y,否则将无法得到密钥k。因此,k为Alice和Bob独立计算出的密钥。
缺点:DH密钥交换算法易受到中间人攻击。
中间人攻击 描述:
(1) Alice 公开发送值a和p给Bob,攻击者Carol截获这些值,随即把自己产生的公开值发给Bob。
(2) Bob 公开发送值a和p给Alice,又被 Carol截获,随即把自己产生的公开值发给Alice。
(3) Alice 和Carol计算出两人之间的共享密钥k1。
(4) Bob 和Carol计算出两人之间另一个的共享密钥k2。
受到中间人Carol攻击后,Alice用密钥k1给Bob发送消息,Carol截获后用k1解密就可读取消息,然后将获得的明文消息用k2加密(加密前对消息可能做某些修改,即主动攻击),然后发给Bob。对Bob发给Alice的消息,Carol用同样的手法读取和修改。
造成中间人攻击得逞的原因是:DH密钥交换算法不进行认证对方。利用数字签名可以解决中间人攻击的缺陷。
1 //演示程序(VC6.0) 2 3 //----------Diffie-Hellman.h--------- 4 5 #define LFSR(n) {if (n&1) n=((n^0x80000055)>>1)|0x80000000; else n>>=1;} 6 #define ROT(x, y) (x=(x<<y)|(x>>(32-y))) 7 #define MAX_RANDOM_INTEGER 2147483648 //Should make these numbers massive to be more secure 8 #define MAX_PRIME_NUMBER 2147483648 //Bigger the number the slower the algorithm 9 10 class Diffie_Hellman{ 11 public: 12 Diffie_Hellman(); 13 int CreatePrimeAndGenerator(); 14 unsigned __int64 GetPrime(); 15 unsigned __int64 GetGenerator(); 16 unsigned __int64 GetPublicKey(); 17 void ShowValue(unsigned __int64 key); 18 unsigned __int64 GetKey(unsigned __int64 HisPublieKey); 19 int SetPrimeAndGenerator(unsigned __int64 Prime,unsigned __int64 Generator); 20 private: 21 __int64 GetRTSC( void ); 22 unsigned __int64 GenerateRandomNumber(void); 23 __int64 XpowYmodN(__int64 x, __int64 y, __int64 N); 24 bool IsItPrime (__int64 n, __int64 a) ; 25 bool MillerRabin (__int64 n, __int64 trials); 26 unsigned __int64 GeneratePrime(); 27 int CreatePrivateKey(); 28 int CreatePublicKey(); 29 int GenerateKey(unsigned __int64 HisPublicKey); 30 unsigned __int64 p; //素数 31 unsigned __int64 g; //对应的本原根 32 unsigned __int64 X; //私钥 33 unsigned __int64 Y; //公钥 34 unsigned __int64 Key;//通讯密钥 35 }; 36 37 --------------Diffie-Hellman.cpp-------------- 38 39 #include "Diffie-Hellman.h" 40 #include<iostream> 41 Diffie_Hellman::Diffie_Hellman(){ 42 p=0; 43 g=0; 44 X=0; 45 Y=0; 46 Key=0; 47 } 48 49 __int64 Diffie_Hellman::GetRTSC( void ) 50 { 51 int tmp1 = 0; 52 int tmp2 = 0; 53 54 __asm 55 { 56 RDTSC; // Clock cycles since CPU started 57 mov tmp1, eax; 58 mov tmp2, edx; 59 } 60 61 return ((__int64)tmp1 * (__int64)tmp2); 62 } 63 unsigned __int64 Diffie_Hellman::GenerateRandomNumber(void) 64 { 65 static unsigned long rnd = 0x41594c49; 66 static unsigned long x = 0x94c49514; 67 68 LFSR(x); 69 rnd^=GetRTSC()^x; 70 ROT(rnd,7); 71 72 return (unsigned __int64)GetRTSC() + rnd; 73 } 74 75 __int64 Diffie_Hellman::XpowYmodN(__int64 x, __int64 y, __int64 N) 76 { 77 __int64 tmp = 0; 78 if (y==1) return (x % N); 79 80 if ((y&1)==0) 81 { 82 tmp = XpowYmodN(x,y/2,N); 83 return ((tmp * tmp) % N); 84 } 85 else 86 { 87 tmp = XpowYmodN(x,(y-1)/2,N); 88 tmp = ((tmp * tmp) % N); 89 tmp = ((tmp * x) % N); 90 return (tmp); 91 } 92 } 93 94 bool Diffie_Hellman::IsItPrime (__int64 n, __int64 a) 95 { 96 __int64 d = XpowYmodN(a, n-1, n); 97 if (d==1) 98 return true; 99 else 100 return false; 101 102 } 103 104 bool Diffie_Hellman::MillerRabin (__int64 n, __int64 trials) 105 { 106 __int64 a = 0; 107 108 for (__int64 i=0; i<trials; i++) 109 { 110 a = (rand() % (n-3))+2;// gets random value in [2..n-1] 111 112 if (IsItPrime (n,a)==false) 113 { 114 return false; 115 //n composite, return false 116 } 117 } return true; // n probably prime 118 } 119 120 unsigned __int64 Diffie_Hellman::GeneratePrime() 121 { 122 unsigned __int64 tmp = 0; 123 124 tmp = GenerateRandomNumber() % MAX_PRIME_NUMBER; 125 126 //ensure it is an odd number 127 if ((tmp & 1)==0) 128 tmp += 1; 129 130 if (MillerRabin(tmp,5)==true) return tmp; 131 132 do 133 { 134 tmp+=2; 135 } while (MillerRabin(tmp,5)==false); 136 137 return tmp; 138 } 139 int Diffie_Hellman::CreatePrimeAndGenerator()// 产生素数p,和它的本原根g 140 { 141 unsigned __int64 q; 142 bool f=true; 143 while(f){ 144 p=GeneratePrime(); 145 q=p*2+1; 146 if(MillerRabin(q,5)==true) 147 f=false; 148 } 149 f=true; 150 while(f){ 151 g=GenerateRandomNumber() % (p-2); 152 if(XpowYmodN(g, 2, p)!=1 && XpowYmodN(g, q, p)!=1) 153 f=false; 154 } 155 return 0; 156 } 157 158 unsigned __int64 Diffie_Hellman::GetPrime(){ 159 return p; 160 } 161 unsigned __int64 Diffie_Hellman::GetGenerator(){ 162 return g; 163 } 164 165 int Diffie_Hellman::CreatePrivateKey(){ 166 X=GenerateRandomNumber() %(p-1); 167 return 0; 168 } 169 170 int Diffie_Hellman::CreatePublicKey(){ 171 //先设置私钥 172 if(X==0) 173 CreatePrivateKey(); 174 Y=XpowYmodN(g, X, p); 175 return 0; 176 } 177 unsigned __int64 Diffie_Hellman::GetPublicKey(){ 178 if(Y==0) CreatePublicKey(); 179 return Y; 180 } 181 void Diffie_Hellman::ShowValue(unsigned __int64 key){ 182 char s[20]; 183 _i64toa(key,s,10); 184 std::cout<<s<<std::endl; 185 } 186 187 int Diffie_Hellman::GenerateKey(unsigned __int64 HisPublicKey){ 188 Key=XpowYmodN(HisPublicKey, X, p); 189 return 0; 190 } 191 192 unsigned __int64 Diffie_Hellman::GetKey(unsigned __int64 HisPublicKey){ 193 if(Key==0) 194 GenerateKey(HisPublicKey); 195 return Key; 196 } 197 198 int Diffie_Hellman::SetPrimeAndGenerator(unsigned __int64 Prime,unsigned __int64 Generator){ 199 p=Prime; 200 g=Generator; 201 return 0; 202 } 203 204 ----------------Main.cpp------------ 205 206 #include<iostream> 207 #include "Diffie-Hellman.h" 208 using namespace std; 209 210 int main(){ 211 unsigned __int64 p=0,g=0,Alice_Y,Bob_Y,Alice_key,Bob_key; 212 char prime[20],generator[20],sAlice_key[20],sBob_key[20]; 213 Diffie_Hellman Alice,Bob; 214 Alice.CreatePrimeAndGenerator(); 215 p=Alice.GetPrime(); 216 g=Alice.GetGenerator(); 217 _i64toa(p,prime,10); 218 _i64toa(g,generator,10); 219 cout<<"prime:"<<prime<<endl<<"generator:"<<generator<<endl; 220 Bob.SetPrimeAndGenerator(p,g); 221 //p=Bob.GetPrime(); 222 //g=Bob.GetGenerator(); 223 //_i64toa(p,prime,10); 224 //_i64toa(g,generator,10); 225 //cout<<"prime:"<<prime<<endl<<"generator:"<<generator<<endl; 226 Alice_Y=Alice.GetPublicKey(); 227 //_i64toa(Alice_Y,prime,10);cout<<prime<<endl; 228 Bob_Y=Bob.GetPublicKey(); 229 //_i64toa(Bob_Y,prime,10);cout<<prime<<endl; 230 Alice_key=Alice.GetKey(Bob_Y); 231 //_i64toa(Alice_key,prime,10);cout<<prime<<endl; 232 Bob_key=Bob.GetKey(Alice_Y); 233 //_i64toa(Bob_key,prime,10);cout<<prime<<endl; 234 _i64toa(Alice_key,sAlice_key,10); 235 _i64toa(Bob_key,sBob_key,10); 236 cout<<sAlice_key<<endl<<sBob_key<<endl; 237 return 0; 238 }