本节显示发送用户端实现三相密钥交换协议所需的代码。发送用户和目的用户之间的通信的细节没有显示,因为这些对于每个实现将是不同的。
为了可读性,这个例子和以下一个公然地避免了两个主要方面的良好的编程实践:
*不显示错误检查。工作程序应始终检查返回的错误代码,并在遇到错误时执行一些适当的操作。
*固定长度的缓冲区用于存储密钥和散列值。实际上,这些缓冲区应该动态分配,因为这个数据会根据所使用的CSP而有所不同。
#include < wincrypt.h >
HCRYPTPROV hProv = 0;
#define BLOB_SIZE 256
BYTE pbDestName[NAME_SIZE];
DWORD dwDestNameLen;
BYTE pbSendName[NAME_SIZE];
DWORD dwSendNameLen;
HCRYPTKEY hDestPubKey = 0;
HCRYPTKEY hKeyA = 0;
HCRYPTKEY hKeyB = 0;
#define HASH_SIZE 256
BYTE pbKeyBlob[BLOB_SIZE];
DWORD dwBlobLen;
// Obtain the sending user's exchange public key.
BYTE pbHash[HASH_SIZE];
DWORD dwHashLen;
BYTE pbDestHash[HASH_SIZE];
DWORD dwDestHashLen;
HCRYPTHASH hHash = 0;
//获取默认提供程序的句柄。
CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0);
//获取目标用户的交换机公钥。将其导入
// CSP并在'hDestPubKey'中放置一个句柄。
...
CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hDestPubKey);
//获取目标用户的名字。这通常是在
//同时获得公钥。放在这里
//'pbDestName'并将'dwDestNameLen'设置为字节数
// 名字。
...
//将发送用户的名称放在'pbSendName'并设置
//'dwSendNameLen'到其中的字节数。
...
//创建一个随机会话密钥(会话密钥A)。因为这个钥匙会
//仅用于密钥交换而不是加密
//这里没有指定哪种算法。
CryptGenKey(hProv, CALG_RC2, CRYPT_EXPORTABLE, &hKeyA);
//将会话密钥A导出为一个简单的密钥blob。
dwBlobLen = BLOB_SIZE;
CryptExportKey(hKeyA,hDestPubKey,SIMPLEBLOB,0,pbKeyBlob,& dwBlobLen);
//发送包含会话密钥A的密钥blob到目标用户。
...
//等待目标用户响应。
...
//从目的地接收包含会话密钥B的密钥blob
//用户并将其放在'pbKeyBlob'中。将'dwBlobLen'设置为数字
//关键blob中的字节。
...
//从目标用户接收哈希值并将其放入
//“Pbsvlua。将'dwHashLen'设置为散列中的字节数
//值。
...
//将关键点blob导入CSP。
CryptImportKey(hProv, pbKeyBlob, dwBlobLen, 0, 0, &hKeyB);
//
//验证从目标用户接收的哈希值。
//
//创建哈希对象。
CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
//将会话密钥A添加到哈希。
CryptHashSessionKey(hHash, hKeyA, 0);
//将目标用户名添加到哈希。
CryptHashData(hHash, pbDestName, dwDestNameLen, 0);
//将会话密钥B添加到哈希。
CryptHashSessionKey(hHash, hKeyB, 0);
//将发送用户名添加到哈希。
CryptHashData(hHash, pbSendName, dwSendNameLen, 0);
//将“阶段2”文本添加到哈希。
CryptHashData(hHash, "phase 3", 7, 0);
//完成哈希计算并检索哈希值。
dwHashLen = HASH_SIZE;
CryptGetHashParam(hHash,HP_HASHVALUE,pbHash,& dwHashLen,0);
//销毁哈希对象。
CryptDestroyHash(hHash);
//
//比较从目标用户接收的哈希值
//我们刚刚计算出的哈希值。如果不匹配的话
//终止协议。
//
if(dwHashLen!=dwDestHashLen || memcmp(pbHash, pbDestHash, dwHashLen)) {
printf("Key exchange protocol failed in phase 2!\n");
printf("Aborting protocol!\n");
return;
}
//
//计算要发送给目标用户的哈希值。
//
//创建哈希对象。
CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
//将会话密钥B添加到哈希。
CryptHashSessionKey(hHash, hKeyB, 0);
//将发送用户名添加到哈希。
CryptHashData(hHash, pbSendName, dwSendNameLen, 0);
//将目标用户名添加到哈希。
CryptHashData(hHash, pbDestName, dwDestNameLen, 0);
//添加“阶段3”文本到哈希。
CryptHashData(hHash, "phase 3", 7, 0);
//完成哈希计算并检索哈希值。
dwHashLen = HASH_SIZE;
CryptGetHashParam(hHash,HP_HASHVALUE,pbHash,& dwHashLen,0);
//销毁哈希对象。
CryptDestroyHash(hHash);
//将哈希值发送到目标用户。
...
//
//使用会话密钥A加密发送到接收者的邮件。
//使用会话密钥B来解密从接收者接收的消息。
//
...
//销毁会话密钥。
CryptDestroyKey(hKeyA);
CryptDestroyKey(hKeyB);
//发布提供者句柄。
CryptReleaseContext(hProv, 0);