【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
加密和解密是我们在软件开发中经常遇到的一种情形。最早的时候,加密是用在军事上面。现在由于各个行业、各个公司之间的竞争也非常激烈,因此有必要利用加密方法来保证自己软件的数据不被破解。此外,加解密还有一个重要的应用场合,那就是软件的有效期,这部分很多时候也是加密特定的文件,最后被软件加载和解密使用的。
不过可惜的是,目前为止在qt上面没有看到比较好的加解密库。还在window平台提供类类似的加解密api,也可以用来进行数据处理。
1、创建基本的qt widget环境
首先我们可以创建一个基本的widget环境,主要是用来生成编译环境比较方便。
2、代码说明
本次文中引用的代码主要来自这篇文章,大家可以参考一下原来作者的思路和想法。
https://blog.csdn.net/weixin_41077112/article/details/132753791
3、算法流程
如果用windows api进行数据数据的加解密,其实流程不算复杂。一般来说,先利用CryptAcquireContext创建一个HCRYPTPROV,再创建一个HCRYPTKEY。后期利用HCRYPTKEY进行数据的加密和解密动作。所有操作都做完,如果没有其他的工作,还需要把
前面资源释放一下。
int main()
{
HCRYPTPROV hCryptProv = NULL;
HCRYPTKEY hKey = NULL;
BYTE* pDataToEncrypt = (BYTE*)"Hello, World!";
BYTE* pEncryptedData = NULL;
DWORD encryptedDataLen = 0;
BYTE* pDecryptedData = NULL;
DWORD decryptedDataLen = 0;
//Get the handler of Crypt Service Provider(CSP)
if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_AES, 0)) {
printf("CryptAcquireContext failed: %d\n", GetLastError());
return 1;
}
//Generate AES key
if (!CryptGenKey(hCryptProv, CALG_AES_256, 0, &hKey)) {
printf("CryptGenKey failed: %d\n", GetLastError());
CryptReleaseContext(hCryptProv, 0);
return 1;
}
//Encrypt data
if (EncryptData(hKey, pDataToEncrypt, strlen((char*)pDataToEncrypt) + 1, &pEncryptedData, &encryptedDataLen)) {
printf("Data encrypted successfully.\n");
printf("Encrypted data: ");
for (DWORD i = 0; i < encryptedDataLen; i++)
{
printf("%02X", pEncryptedData[i]);
}
printf("\n");
//Decrypt data
if (DecryptData(hKey, pEncryptedData, encryptedDataLen, &pDecryptedData, &decryptedDataLen)) {
printf("Decrypted data: %s\n", pDecryptedData);
free(pDecryptedData);
}
free(pEncryptedData);
}
//Clean resources
CryptDestroyKey(hKey);
CryptReleaseContext(hCryptProv, 0);
return 0;
}
4、数据加密
数据加密的过程主要采用了CryptEncrypt函数,大家可以参考下,
#include <windows.h>
#include <wincrypt.h>
#include <iostream>
// encrypt data here
BOOL EncryptData(HCRYPTKEY hKey, BYTE* pData, DWORD dataLen, BYTE** ppEncryptedData, DWORD* pEncryptedDataLen)
{
*pEncryptedDataLen = dataLen + 16;
*ppEncryptedData = (BYTE*)malloc(*pEncryptedDataLen);
ZeroMemory(*ppEncryptedData, *pEncryptedDataLen);
if (*ppEncryptedData == NULL)
{
printf("Memory allocation failed.\n");
return FALSE;
}
memcpy(*ppEncryptedData, pData, dataLen);
if (!CryptEncrypt(hKey, NULL, TRUE, 0, *ppEncryptedData, &dataLen, *pEncryptedDataLen))
{
printf("CryptEncrypt failed: %d\n", GetLastError());
free(*ppEncryptedData);
if (GetLastError() == ERROR_MORE_DATA)
{
*pEncryptedDataLen = dataLen + 1;
*ppEncryptedData = (BYTE*)malloc(*pEncryptedDataLen);
ZeroMemory(*ppEncryptedData, *pEncryptedDataLen);
if (*ppEncryptedData == NULL)
{
printf("Memory allocation failed again.\n");
return FALSE;
}
memcpy(*ppEncryptedData, pData, dataLen);
if (!CryptEncrypt(hKey, NULL, TRUE, 0, *ppEncryptedData, &dataLen, *pEncryptedDataLen))
{
printf("CryptEncrypt failed again: %d\n", GetLastError());
free(*ppEncryptedData);
return FALSE;
}
}
else
{
return FALSE;
}
}
*pEncryptedDataLen = dataLen;
return TRUE;
}
5、数据解密
数据解密,则引用了另外一个api,即CryptDecrypt。
BOOL DecryptData(HCRYPTKEY hKey, BYTE* pEncryptedData, DWORD encryptedDataLen, BYTE** ppDecryptedData, DWORD* pDecryptedDataLen)
{
*ppDecryptedData = (BYTE*)malloc(encryptedDataLen);
ZeroMemory(*ppDecryptedData, encryptedDataLen);
if (*ppDecryptedData == NULL)
{
printf("Memory allocation failed.\n");
return FALSE;
}
memcpy(*ppDecryptedData, pEncryptedData, encryptedDataLen);
*pDecryptedDataLen = encryptedDataLen;
if (!CryptDecrypt(hKey, NULL, TRUE, 0, *ppDecryptedData, pDecryptedDataLen))
{
printf("CryptDecrypt failed: %d\n", GetLastError());
free(*ppDecryptedData);
return FALSE;
}
return TRUE;
}
6、测试和验证
上面三部分代码,大家如果放到一个文件里面,其实就可以开始编译验证了。单步调试即可。主要的验证方法,就是确认加密前和加密后的数据是否一致即可。当然,这个demo还有一个很大的不足,就是目前为止,生成的key没有导出来,每次都是重新创建。
实际应用中,对于生成的key,一般需要用CryptExportKey和CryptImportKey进行导出和导入处理一下。有兴趣的同学可以继续把这部分代码补充上,让整体的功能更加完善一点。