Microsoft CryptoAPI加密技术(二)
作者:Cuick
下载本文示例源代码
上次我们讲了Microsoft CryptoAPI的构成以及会话密钥的使用。接下来我们将看一下公私密钥对的使用、HASH算法、数字签名等技术。
一、 公用密钥加密技术
公用密钥加密技术使用两个不同的密钥:公钥和私钥。私钥必须安全的保管好不能被外人知道,而公钥可以告诉任何人,只要他需要。通常公钥是以数字证书的形式发布的。
用公私密钥对中的一个密钥加密的数据只能用密钥对中的另一个密钥才能解密。也就是说用用户A的公钥加密的数据只能用A的私钥才能解密,同样,用A的私钥加密的数据只能用A的公钥才能解密。
如果用私钥签名一个消息,那么必须用与之对应的公钥去验证签名的有效性。
不幸的是公用密钥加密技术的效率非常低甚至只有对称加密的千分之一,所以不适合对大量的数据进行加密。实际上,公用密钥加密技术一般用来加密会话密钥,而数据加密可以用对称加密的方法。
好了,让我们回到Microsoft CryptoAPI。我们知道一个CSP有一个密钥库,这个密钥库有一个或多个密钥容器。而密钥容器中有什么呢?一般来说,一个密钥容器中有两对公私密钥对,一对用来加密会话密钥,而另一对用来进行数字签名,也就是大家知道的key exchange key pair和signature key pair。
那么,怎么得到这些密钥对呢?
if(CryptGetUserKey( hCryptProv, // 我们已经得到的CSP句柄 AT_SIGNATURE, // 这里想得到signature key pair &hKey)) // 返回密钥句柄{ printf("A signature key is available.n");}else//取signature key pair错误{ printf("No signature key is available.n"); if(GetLastError() == NTE_NO_KEY) //密钥容器里不存在signature key pair { // 创建 signature key pair. printf("The signature key does not exist.n"); printf("Create a signature key pair.n"); if(CryptGenKey( hCryptProv,//CSP句柄 AT_SIGNATURE,//创建的密钥对类型为signature key pair 0,//key类型,这里用默认值 &hKey)) //创建成功返回新创建的密钥对的句柄 { printf("Created a signature key pair.n"); } else { printf ("Error occurred creating a signature key.n"); } } else { printf ("An error other than NTE_NO_KEY getting signaturekey.n"); }} // end if将参数AT_SIGNATURE换成AT_KEYEXCHANGE就可以得到key exchange key pair。
现在我们得到的仅仅是一个句柄,我们需要把这个key值存储的磁盘或文件中,这样才能传给对方来进行解密。下面让我们来看一个用于导出密钥的API。
BOOL WINAPI CryptExportKey( HCRYPTKEY hKey, HCRYPTKEY hExpKey, DWORD dwBlobType, DWORD dwFlags, BYTE* pbData, DWORD* pdwDataLen);hKey:需要被导出的密钥句柄
hExpKey:前面咱们提到公用密钥加密技术的效率非常低所以公用密钥加密技术
一般用来加密会话密钥。这里传入的密钥就是用来加密被导出的密钥
的。也就是说,被导出的密钥hKey的数据是经过这个密钥hExpKey
加密的。如果为NULL表示不经过加密直接导出。
dwBlobType:被导出的密钥类型,比如公钥还是私钥等
dwFlags:标志位
pbData:保存导出的数据,如果为NULL, pdwDataLen将返回导出数据的长度
pdwDataLen:输入pbData缓冲区的大小,输出导出数据的长度
下面的例子演示如何导出密钥。
if(CryptExportKey( hKey, NULL, PUBLICKEYBLOB,//导出公钥 0, NULL, &dwBlobLen)) //返回密钥数据长度{ printf("Size of the BLOB for the public key determined. n");}else{ printf("Error computing BLOB length.n"); exit(1);}//--------------------------------------------------------------------// Allocate memory for the pbKeyBlob.if(pbKeyBlob = (BYTE*)malloc(dwBlobLen)) { printf("Memory has been allocated for the BLOB. n");}else{ printf("Out of memory. n"); exit(1);}//--------------------------------------------------------------------// Do the actual exporting into the key BLOB.if