|
|
所谓“密钥协商”,就是指使用加密协议通信的双方,在通讯之前如何约定一个共同的密码的问题。
例如网络游戏中的消息一般都是使用对称加密算法加密的,比如DES或者BlowFish等,这些对称算法的加密密码和解密密码是一样的,也就是说,如果黑客知道密码的话,就能通过拦截消息包解密出玩家的账号密码等信息。所以使用对称加密算法的通讯双方在通讯前需要约定一个动态的密钥,而且这个密钥不能被监听者得到,这就是“密钥协商”协议。
密钥协商协议的关键就是利用“不可逆”算法,举个简单例子:
A和B分别住在两个帐篷里,他们之间的通讯大家都能看得到,现在他们想共同约定出一种颜色,而且不被别人知道,应该怎么办呢?
方法如下:
.A和B首先约定好公开的一种颜色,比如红色
.A挑选出一种私密的颜色,比如蓝色,然后和红色混合起来
.B挑选出一种私密的颜色,比如黄色,然后也和红色混合起来
.A和B互相交换混合后的颜色
.A把得到的颜色中加入自己选中的蓝色
.B把得到的颜色中加入自己选中的黄色
.现在A和B手里的颜色都是"红+蓝+黄",也就是说,A和B已经约定好了共同的颜色,而帐篷外的人却无法得知
秘密就在于,把两种颜色混合在一起是一种“不可逆”的过程,起码很难。目前常用的加密协议中的不可逆算法都是这样,并不是理论上不可逆,而是很困难,困难到以目前的计算条件,算上几万年才能算出来,我们也就认为这种算法是安全的。比如两个大素数的相乘是很容易计算的,但把相乘的结果分解则是非常困难的,很多不对称加密算法都是利用大素数的相乘来进行的。
在加密通讯前进行密钥协商的原理和上面的例子流程差不多,当然,已经有很多很好的算法和开源库可以利用,相对来说,cryptopp比起openssl更轻便一些,windows下使用也比较方便。
Cryptopp的官方网站是http://www.cryptppp.com,不知道为什么,国内近期已经无法访问了,还好在SourceForge上也有cryptopp的影像,大家可以从这里下载(http://sourceforge.net/projects/cryptopp/)。
目前的Cryptopp5.5.2提供了VS2005的sln文件,在Windows下可以直接编译使用,下面是利用其中的Diffie-Hellmar协议进行密钥协商的示例代码:
- [color=#000080]using[/color] [color=#000080]namespace[/color] CryptoPP;
-
- [color=#008800]//////////////////////////////////////////////////////////////////////////[/color]
- [color=#008800]// Alice[/color]
-
- [color=#008800]// Initialize the Diffie-Hellman class with a random prime and base[/color]
- AutoSeededRandomPool arngA;
- RandomNumberGenerator& rngA = *[color=#000080]dynamic_cast[/color]<RandomNumberGenerator *>(&arngA);
- DH dhA(rngA, [color=#0000ff]128[/color]);
-
- [color=#008800]// Extract the prime and base. These values could also have been hardcoded [/color]
- [color=#008800]// in the application[/color]
- Integer iPrime = dhA.GetGroupParameters().GetModulus();
- Integer iGenerator = dhA.GetGroupParameters().GetSubgroupGenerator();
-
- SecByteBlock privA(dhA.PrivateKeyLength());
- SecByteBlock pubA(dhA.PublicKeyLength());
- SecByteBlock secretKeyA(dhA.AgreedValueLength());
-
- [color=#008800]// Generate a pair of integers for Alice. The public integer is forwarded to Bob.[/color]
- dhA.GenerateKeyPair(rngA, privA, pubA);
-
-
- [color=#008800]//////////////////////////////////////////////////////////////////////////[/color]
- [color=#008800]// Bob[/color]
-
- AutoSeededRandomPool arngB;
- RandomNumberGenerator& rngB = *[color=#000080]dynamic_cast[/color]<RandomNumberGenerator *>(&arngB);
- [color=#008800]// Initialize the Diffie-Hellman class with the prime and base that Alice generated.[/color]
- DH dhB(iPrime, iGenerator);
-
- SecByteBlock privB(dhB.PrivateKeyLength());
- SecByteBlock pubB(dhB.PublicKeyLength());
- SecByteBlock secretKeyB(dhB.AgreedValueLength());
-
- [color=#008800]// Generate a pair of integers for Bob. The public integer is forwarded to Alice.[/color]
- dhB.GenerateKeyPair(rngB, privB, pubB);
-
-
-
- [color=#008800]//////////////////////////////////////////////////////////////////////////[/color]
- [color=#008800]// Agreement[/color]
-
- [color=#008800]// Alice calculates the secret key based on her private integer as well as the[/color]
- [color=#008800]// public integer she received from Bob.[/color]
- [color=#000080]if[/color] (!dhA.Agree(secretKeyA, privA, pubB))
- [color=#000080]return[/color] [color=#000080]false[/color];
-
- [color=#008800]// Bob calculates the secret key based on his private integer as well as the[/color]
- [color=#008800]// public integer he received from Alice.[/color]
- [color=#000080]if[/color] (!dhB.Agree(secretKeyB, privB, pubA))
- [color=#000080]return[/color] [color=#000080]false[/color];
-
- [color=#008800]// Just a validation check. Did Alice and Bob agree on the same secret key?[/color]
- [color=#000080]if[/color] (memcmp(secretKeyA.begin(), secretKeyB.begin(), dhA.AgreedValueLength()))
- [color=#000080]return[/color] [color=#000080]false[/color];
-
- [color=#008800]//////////////////////////////////////////////////////////////////////////[/color]
- [color=#008800]// Building on the previous example. Note that the example uses in-place encryption and [/color]
- [color=#008800]// decryption where the input and output buffers are identical[/color]
- [color=#000080]int[/color] aesKeyLength = SHA256::DIGESTSIZE; [color=#008800]// 32 bytes = 256 bit key[/color]
- [color=#000080]int[/color] defBlockSize = AES::BLOCKSIZE;
-
- [color=#008800]// Calculate a SHA-256 hash over the Diffie-Hellman session key[/color]
- SecByteBlock key(SHA256::DIGESTSIZE);
- SHA256().CalculateDigest(key, secretKeyA, secretKeyA.size());
-
- [color=#008800]// Generate a random IV[/color]
- byte iv[AES::BLOCKSIZE];
- arngA.GenerateBlock(iv, AES::BLOCKSIZE);
-
- [color=#000080]char[/color] message[] = [color=#0000ff]"Hello! How are you."[/color];
- [color=#000080]int[/color] messageLen = ([color=#000080]int[/color])strlen(message) + [color=#0000ff]1[/color];
-
-
- [color=#008800]//////////////////////////////////////////////////////////////////////////[/color]
- [color=#008800]// Encrypt[/color]
-
- CFB_Mode<AES>::Encryption cfbEncryption(key, aesKeyLength, iv);
- cfbEncryption.ProcessData((byte*)message, (byte*)message, messageLen);
-
- [color=#008800]//////////////////////////////////////////////////////////////////////////[/color]
- [color=#008800]// Decrypt[/color]
-
- CFB_Mode<AES>::Decryption cfbDecryption(key, aesKeyLength, iv);
- cfbDecryption.ProcessData((byte*)message, (byte*)message, messageLen);
复制代码
|
|