简介
文中用到了一些Cryptography API Next Generation(CNG)函数,开发环境为Windows Vista下的Visual C++ 2005 SP1标准版,加上Windows SDK及CNG SDK。
程序可适用于以下情况:
? 在安全环境下保存文档,但需要在不安全的媒质(如互联网)中传送。
? 加密文件,如图像、MP3、各类文档。
? 创建软件的产品密钥。
需要注意的是,CNG目前只支持Windows Vista,且不能使用在Visual Basic及C#中。要在Visual Studio中生成相应的Windows程序,可能还需要Windows Vista SDK及CNG SDK,两者都可以从微软官方网站下载获得。
背景
我们最初是想在一个简单的GUI程序中使用CNG来加密文件,需要以下三步:
1、 选择加密操作。
2、 选择需要加密的文件。
3、 选择加密密钥。
相关程序
此处创建了一个MFC应用程序,程序使用单文档界面,在其中可选择待加解密的文件、加密还是解密、密码;此外,还有一个列表框,用于显示其他信息。
另外,要在Visual C++ 2005中使用CNG SDK,还需要进行如下的项目设置:
1、 在“C/C++——General”项右方的“Additional Include Directories”中,添加以下目录:C:\Program Files\Microsoft CNG Development Kit\Include
2、 在“Link——General”项右方的“Additional Library Directories”中,添加以下目录:C:\Program Files\Microsoft CNG Development Kit\Lib\X86
3、 在“Linker——Input”项右方的“Additional Dependencies”中,添加“bcrypt.lib”。
相关代码
在此使用CNG创建了类CMyCNGCryptFile,它有三个公有方法:
? EnumProviders:枚举出注册的提供者。
? CryptFile:加密或解密一个文件。
? GetLastError:返回发生在CryptFile或EnumProviders中的最后一个错误。
相关步骤如下:1、打开算法提供者;2、创建或导入一个密钥;3、获取或设置算法属性;4、执行操作;5、关闭算法提供者。
以下是CNG API:
打开算法提供者:
BCryptOpenAlgorithmProvider
导入密钥:
BCryptGenerateSymmetricKey
创建密钥:
BCryptCreateHash
BCryptHashData
BCryptFinishHash
BCryptGenerateSymmetricKey
获取或设置算法属性:
BCryptGetProperty
BCryptSetProperty
执行加解密操作:
BCryptEncrypt
BCryptDecrypt
枚举提供者:
BCryptEnumRegisteredProviders
关闭算法提供者:
BCryptCloseAlgorithmProvider
销毁密钥:
BCryptDestroyKey
销毁哈希:
BCryptDestroyHash
bool CryptFile(bool bEncrypt, CString sFileToOpen,CString sFileToCrypt,CString sKey)
这是从对话框中调用的主要方法,它接受要执行的操作、输入的文件、输出的文件、密钥作为参数,步骤如下:
1、 用OpenMSPrimitiveProviderAES打开算法提供者。
2、 用CreateSymmetricKey_AES_CBC创建一个密钥,或用CreateSymmetricKey_SHA1_Hash导入一个密钥。
3、 获取相关文件的缓冲区。
4、 通过Crypt执行加解密操作,输出中间文件,并通过CryptLastByte获得最终的文件。
5、 保存加密数据到输出文件。
OpenMSPrimitiveProviderAES方法打开一个到AES提供者的句柄。
bool CMyCNGCryptFile::OpenMSPrimitiveProviderAES()
{
NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
ntStatus = BCryptOpenAlgorithmProvider( &m_hAesAlg,
BCRYPT_AES_ALGORITHM, NULL, 0);
switch (ntStatus)
{
case STATUS_SUCCESS:
return true;
case STATUS_INVALID_PARAMETER:
case STATUS_NO_MEMORY:
default:
//... ...
}
return false;
}
CreateSymmetricKey_AES_CBC方法获取一个密钥,并把它作为一个静态常数BYTE变量rgbAES128Key存储在程序中。第一步,通过BCryptGetProperty取得算法属性,接着用算法提供者句柄得到算法的实现细节,如密钥大小及IV大小;第二步,把它分配在堆中,并通过BCryptSetProperty修改算法的属性。此处假定要使用BCRYPT_CHAIN_MODE_CBC,我们将AES算法的BCRYPT_CHAINING_MODE属性设为BCRYPT_CHAIN_MODE_CBC。现在,