使用windows crypto API加密解密

文章一:使用windows crypto API加密解密

本文转自: http://ticktick.blog.51cto.com/823160/168538

      最近在学习使用windows crypto API 对数据进行加密和解密,有些收获和经验,在此分享,希望对学习加密解密的朋友们有所帮助。
      经过这次windows crypto API的学习过程,让我明白一个道理。其实,使用windows API编程并不难,首先要有信心。MSDN提供了详细的帮助和指南,许多问题,只要详细查阅MSND,完全可以不用在网上查找任何资料完成自己所需要的编程任务。
       网上的东西,许多都是来自别人的经验介绍,很多,但也很杂,为了搜索到真正有用的资料,往往需要花费很多的时间和精力。

       首先,大家不要觉得加密和解密是一件很深奥的事情,其实说白了,数据加密就是对原始数据进行一种变换而已,比如:你的密码是123456,我对每一位都加1,即234567,写到文件中,这就是加密,只要别人不知道你是对每一位都加1得到的234567,别人即使拿到你的密码文件,他也不知道怎样把你的密码从234567解密出来。(当然,这种简单的加密是可以很容易被破解的)

       数据加密主要分为两种,一种为对称加密,另一种为非对称加密。
       对称加密主要用于大量数据的加密,加密和解密都使用同一份密钥,密钥其实就是一串数据,使用这一串数据对你要加密的数据进行与啊、或啊或者异或什么的,于是就得到了一串人家看不懂的“密文”。

       非对称加密最经典的应用场合是客户端/服务器模式的系统,主要用于需要在网络中传送的少量数据进行加密(比如客户端的用户名、密码向服务器传送)。它使用两份密钥,公钥和私钥。
       公钥用于发给客户端,私钥留在服务器端。数据经过公钥加密后只能使用对应的私钥来解密。
       因此,客户端先对用户名密码信息使用公钥加密,然后向服务器端发送,即使中途被黑客截获,由于他没有私钥,故无法进行解密,当服务器端收到数据后,就使用自己的私钥进行解密。这样就可以实现所有的客户端都使用公钥进行加密,然后放心地发送数据到服务器端,因为只有服务器端才能够解密。(思考一下:这种场合如果使用对称密钥安全吗?)

       windows crypto API提供了对称加密和非对称加密,并且提供了各种加密、解密的算法,要使用相应的算法进行加密解密,只需要对生成密钥的函数的相关参数改变一下即可。
       为了学习使用windows crypto API,我沿袭以前的习惯,花费了大量的时间在网上搜索资料(许多资料用处不大),最终还是在MSND的指导下完全掌握了crypto API的用法,不过,MSND还是有其不足之处,它详细描述了crypto API相关的知识和信息,但没有从宏观上对实现用crypto API加密解密到底需要做哪些事情进行做出明确地指导,故在此,我用下面这幅流程图来告诉大家。
 

         我只从宏观上描述了整个加密解密需要进行的几个流程,具体每一步的代码怎么写,可以参考MSDN,或者本文后面链接的一份文档(这份文档讲得非常详细,也非常好,是我搜集的资料中最好的一份,希望对需要它的人有所帮助)
       当然,在学习和使用windows crypto API的过程中可能会遇到很多的问题,如果有什么疑问,可以E—Mail给我。


附件下载:
  --CryptoAPI对数据进行加解密



文章二:使用Microsoft CryptoAPI进行加密、解密、签名及验证

本文转自:http://blog.csdn.net/mmpire/article/details/1640670


使用CryptoAPI编写一个文件保护程序,具有如下功能:
(1)给定明文文件,生成加密文件,同时产生文件的数字签名文件;
(2)给定密文文件,解密出明文文件,并验证签名的正确性。
 
代码:见所附main.cpp
 
一、    程序概况
a)    开发平台:Visual Studio 2005
b)    开发语言:C/C++
c)    使用密码库:CryptoAPI
二、    主要函数
a)    主函数
void main(void)
b)    加密文件
BOOL EncryptFile(PCHAR szSource, PCHAR szDestination, PCHAR szPassword);
c)    解密文件
BOOL DecryptFile(PCHAR szSource, PCHAR szDestination, PCHAR szPassword);
d)    签名文件
BOOL SignFile (PCHAR szSource, PCHAR szDestination);
e)    验证签名
BOOL VerifyFile (PCHAR szSource, PCHAR szDestination);
f)     错误处理
void HandleError(char *s);
 
 
 
三、    加密文件
a)    打开源文件
hSource = fopen(szSource,"rb")
b)    取得密钥容器(CSP)句柄
CryptAcquireContext(&hCryptProv,NULL,NULL,PROV_RSA_FULL,0)
c)    根据用户输入的密码创建一个会话密钥(即对称密钥,用于对原文件加密)
//创建一个Hash对象
CryptCreateHash(hCryptProv,CALG_MD5, 0, 0, &hHash)
//用用户输入的密码产生一个散列
CryptHashData(hHash, (BYTE *)szPassword, strlen(szPassword), 0)
//通过散列生成一个会话密钥
CryptDeriveKey(hCryptProv, ENCRYPT_ALGORITHM,hHash, KEYLENGTH, &hKey))
//销毁Hash对象
CryptDestroyHash(hHash);
注:会话密钥即对称密钥,用于对原文件进行加密;非对称密钥由于效率非常低,所以一般不用于对数据直接加密,而是对会话密钥进行加密,然后把它传送给对方。对方通过非对称密钥解密获得这个会话密钥,然后再对数据文件进行解密。可以看出,一个会话密钥的生存期可以限制在这次通信中,即每次通信都用不同的会话密钥加密,而非对称密钥则必须是长期使用的。在此例中,加解密过程中没有使用到非对称RSA密钥对,而只在数字签名及验证使用它。
d)    加密数据文件
CryptEncrypt(
hKey,               //密钥
0,                    //如果数据同时进行散列和加密,这里传入一个散列对象
feof(hSource), //如果是最后一个被加密的块,输入TRUE.如果不是输
//FALSE这里通过判断是否到文件尾来决定是否为最后一块
0,                    //保留
pbBuffer,          //输入被加密数据,输出加密后的数据
&dwCount,       //输入被加密数据实际长度,输出加密后数据长度
dwBufferLen)    //pbBuffer的大小
注:查看完整代码时可以发现这是一个循环加密的过程,pbBuffer循环读入待加密文件的固定长度的内存块;当然你也可以将pbBuffer设得很大,一次读入整个文件,但那样浪费内存空间,而且影响扩展性(存在缓冲区溢出的可能)。
e)    清理工作,如释放Buffer空间、密钥句柄、CSP句柄等。
if(pbBuffer)
free(pbBuffer);
if(hKey)
CryptDestroyKey(hKey);
if(hHash)
CryptDestroyHash(hHash);
if(hCryptProv)
CryptReleaseContext(hCryptProv, 0);
            …
 
四、    解密文件
a)    打开加密文件(同上)
b)    取得密钥容器(CSP)句柄(同上)
c)    根据用户输入的密码创建一个会话密钥(即对称密钥,用于对原文件解密)(同上)
注:这里要求用户输入的密码与加密时输入的密码相同。在实际应用中,这个所谓用户输入的“密码”其实只是一个产生密钥的种子,一旦产生完会话密钥,则用户完全可以忘记当初输入的“密码”,接收方可以使用传过来的密钥直接对加密文件进行解密,而不用再重复一次“生成密钥”的过程。
d)    解密数据文件
CryptDecrypt(
hKey,               //密钥
0,                    //如果数据同时进行散列和加密,这里传入一个散列对象
feof(hSource), //如果是最后一个被加密的块,输入TRUE.如果不是输.
//FALSE这里通过判断是否到文件尾来决定是否为最后一块。
0,                    //保留
pbBuffer,          //输入被加密数据,输出加密后的数据
&dwCount))           //输入被加密数据实际长度,输出加密后数据长度
e)    清理工作,如释放Buffer空间、密钥句柄、CSP句柄等。(同上)
五、    签名文件
a)    打开源文件(同上)
b)    取得密钥容器(CSP)句柄(同上)
c)    取得签名用的密钥句柄(非对称RSA密钥)
CryptGetUserKey(
hCryptProv,               // 我们已经得到的CSP句柄
AT_SIGNATURE,            // 这里想得到signature key pair
&hKey))                       // 返回密钥句柄
d)    导出签名用密钥对的公钥,保存在pbKeyBlob中
CryptExportKey(hKey, NULL,PUBLICKEYBLOB, 0, pbKeyBlob,&dwBlobLen)
e)    计算数据文件的Hash值,保存在Hash对象hHash中
//生成一个空的Hash对象
CryptCreateHash(hCryptProv,CALG_MD5,0,0,&hHash)
//计算数据文件的Hash值,保存在Hash对象中
CryptHashData(hHash,pbBuffer,dwCount,0)
f)     对数据文件的Hash值进行签名,数字签名保存在pbSignature中
CryptSignHash(hHash, AT_SIGNATURE, NULL, 0, pbSignature, &dwSigLen)
g)    清理工作,如释放Buffer空间、密钥句柄、CSP句柄等。(同上)
六、    验证签名
a)    打开文件(同上)
b)    取得密钥容器(CSP)句柄(同上)
c)    导入 pbKeyBlob 公钥
CryptImportKey(hCryptProv, pbKeyBlob, dwBlobLen, 0, 0, &hPubKey)
注:必须是与签名时所用的私钥配对的公钥,在此例中,这个公钥在生成数字签名时已经导出到pbKeyBlob中。
d)    计算数据文件的Hash值,保存在Hash对象hHash中。(同上)
e)    验证数字签名
CryptVerifySignature(hHash, pbSignature, dwSigLen,hPubKey,NULL, 0)
f)     清理工作,如释放Buffer空间、密钥句柄、CSP句柄等。(同上)
七、    实验结果
// 加密文件
Encrypt a file.
 
 
Enter the name of the file to be encrypted: 1.txt
 
Enter the name of the output file: 2.txt
 
Enter the password:123456
 
The source plaintext file, 1.txt, is open.
 
Destination file 2.txt is open.
A cryptographic provider has been acquired.
A hash object has been created.
The password has been added to the hash.
An encryption key is derived from the password hash.
Memory has been allocated for the buffer.
 
Encryption of the file 1.txt was a success.
 
The encrypted data is in file 2.txt.
 
//解密文件
Decrypt a file.
 
 
Enter the name of the file to be decrypted: 2.txt
 
Enter the name of the output file: 3.txt
 
Enter the password:123456
 
The source plaintext file, 2.txt, is open.
 
Destination file 3.txt is open.
A cryptographic provider has been acquired.
A hash object has been created.
The password has been added to the hash.
An encryption key is derived from the password hash.
Memory has been allocated for the buffer.
 
Decryption of the file 2.txt was a success.
 
The decrypted data is in file 3.txt.
 
//数字签名
Sign a file.
 
 
Enter the name of the file to be signed: 1.txt
 
Enter the name of the signature file: 11
 
The source plaintext file, 1.txt, is open.
Memory has been allocated for the buffer.
 
Destination file 11 is open.
A cryptographic provider has been acquired.
A signature key is available.
Size of the BLOB for the public key determined.
Memory has been allocated for the BLOB.
Contents have been written to the BLOB.
Hash object created.
The data buffer has been hashed.
Signature length 128 found.
Memory allocated for the signature.
pbSignature is the hash signature.
The hash object has been destroyed.
The signing phase of this program is completed.
 
 
Signature of the file 1.txt was a success.
 
The signature data is in file 11.
 
//验证签名
Verify a file and its signature.
 
 
Enter the name of the file to be verified: 1.txt
 
Enter the name of the signature file: 11
 
The source plaintext file, 1.txt, is open.
Memory has been allocated for the buffer.
A cryptographic provider has been acquired.
The key has been imported.
The hash object has been recreated.
The new has been created.
The signature has been verified.
 
Verification of the file 1.txt was a success.
八、    参考资料
1)      Microsoft CryptoAPI加密技术
2)      MSDN


九、  代码:

          http://blog.csdn.net/mmpire/article/details/1640670


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章