以前我曾经在 Visual Studio 中使用select sv.*, v.visitorid, v.visittypeid
from (select s.sitesId, s.name, s.modality,
count(v.visitId) as numvisits,
max(v.startdate) as maxdate
from sites as s left join
visits as v
on s.sitesid = v.sitesId
group by s.sitesId, s.name, s.modality
) as sv left join
visits as v
on v.sitesId = sv.sitesId and v.startdate = sv.maxdate
where sv.modality = "A";
,但是现在我想使用crypto++
API函数使用 AES 256 < / strong>和 IV (cbc模式)。
我做了下面的步骤,但是我对wincrypt.h
和CryptEncrypt()
函数感到困惑,因为它们似乎无法正常工作:
CryptDecrypt()
定义为创建CryptAcquireContextA
:
CSP
对于设置键,我正在使用这种方式(导入键):
// create a cryptographic service provider (CSP)
CryptAcquireContextA(&hProv, NULL, MS_ENH_RSA_AES_PROV_A, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)
IV,密钥,纯文本大小为:
CryptImportKey(hProv, (BYTE*)&AESBlob, sizeof(AES256KEYBLOB), NULL, CRYPT_EXPORTABLE, &hKey)
这是我的整个#define DEFAULT_AES_KEY_SIZE 32
#define DEFAULT_IV_SIZE 16
#define BUFFER_FOR_PLAINTEXT 32
:
code
它只是加密了一半的纯文本,并且解密没有完成!即使仅更改// handles for csp and key
HCRYPTPROV hProv = NULL;
HCRYPTPROV hKey = NULL;
BYTE szKey[DEFAULT_AES_KEY_SIZE + 1] = {0};
BYTE szIV[DEFAULT_IV_SIZE + 1] = {0};
// plain bytes
BYTE szPlainText[BUFFER_FOR_PLAINTEXT + 1] = {0};
DWORD dwPlainSize = 0;
// initalize key and plaintext
StrCpyA((LPSTR)szKey, "00112233445566778899001122334455");
StrCpyA((LPSTR)szIV, "4455667788990011");
StrCpyA((LPSTR)szPlainText, "abcdefghijklmnopqrstuvwxyzabcdef");
// blob data for CryptImportKey() function (include key and version and so on...)
struct AES256KEYBLOB
{
AES256KEYBLOB() { StrCpyA((LPSTR)szBytes, 0); }
BLOBHEADER bhHdr;
DWORD dwKeySize;
BYTE szBytes[DEFAULT_AES_KEY_SIZE + 1];
} AESBlob;
AESBlob.bhHdr.bType = PLAINTEXTKEYBLOB;
AESBlob.bhHdr.bVersion = CUR_BLOB_VERSION;
AESBlob.bhHdr.reserved = 0;
AESBlob.bhHdr.aiKeyAlg = CALG_AES_256;
AESBlob.dwKeySize = DEFAULT_AES_KEY_SIZE;
StrCpyA((LPSTR)AESBlob.szBytes, (LPCSTR)szKey);
// create a cryptographic service provider (CSP)
if(CryptAcquireContextA(&hProv, NULL, MS_ENH_RSA_AES_PROV_A, PROV_RSA_AES, CRYPT_VERIFYCONTEXT))
{
if(CryptImportKey(hProv, (BYTE*)&AESBlob, sizeof(AES256KEYBLOB), NULL, CRYPT_EXPORTABLE, &hKey))
{
if(CryptSetKeyParam(hKey, KP_IV, szIV, 0))
{
if(CryptEncrypt(hKey, NULL, TRUE, 0, szPlainText, &dwPlainSize, lstrlenA((LPCSTR)szPlainText) + 1))
{
printf("\nEncrypted data : %s\nSize : %d\n", (LPCSTR)szPlainText, dwPlainSize);
if(CryptDecrypt(hKey, NULL, TRUE, 0, szPlainText, &dwPlainSize)) {
printf("\nDecrypted data : %s\nSize : %d\n", (LPCSTR)szPlainText, dwPlainSize);
}
else
printf("failed to decrypt!");
}
else
printf("failed to encrypt");
}
}
}
的值,它也总是给我以下的输出(这意味着szPlainText
和CryptEncrypt()
不能按预期工作!):</ p>
CryptDecrypt()
答案 0 :(得分:2)
这是我从 VStudio2015 运行的一种变体。
code.c :
#include <windows.h>
#include <wincrypt.h>
#include <stdio.h>
#include <Shlwapi.h>
#define DEFAULT_AES_KEY_SIZE 32
#define DEFAULT_IV_SIZE 16
#define BUFFER_FOR_PLAINTEXT 32
#define CLEANUP_CRYPT_STUFF(PROV, KEY) \
CryptDestroyKey(KEY); \
CryptReleaseContext(PROV, 0)
#define PRINT_FUNC_ERR_AND_RETURN(FUNC) \
printf("%s (line %d) failed: %d\n", ##FUNC, __LINE__, GetLastError()); \
return -1
typedef struct AES256KEYBLOB_ {
BLOBHEADER bhHdr;
DWORD dwKeySize;
BYTE szBytes[DEFAULT_AES_KEY_SIZE + 1];
} AES256KEYBLOB;
int main() {
// handles for csp and key
HCRYPTPROV hProv = NULL;
HCRYPTKEY hKey = NULL;
BYTE szKey[DEFAULT_AES_KEY_SIZE + 1] = { 0 };
BYTE szIV[DEFAULT_IV_SIZE + 1] = { 0 };
// plain bytes
BYTE szPlainText[BUFFER_FOR_PLAINTEXT + 1] = { 0 }, *pBuf = NULL;
AES256KEYBLOB AESBlob;
memset(&AESBlob, 0, sizeof(AESBlob));
// initalize key and plaintext
StrCpyA((LPSTR)szKey, "00112233445566778899001122334455");
StrCpyA((LPSTR)szIV, "4455667788990011");
StrCpyA((LPSTR)szPlainText, "abcdefghijklmnopqrstuvwxyzabcdef");
DWORD dwPlainSize = lstrlenA((LPCSTR)szPlainText), dwBufSize = dwPlainSize, dwBufSize2 = dwPlainSize;
// blob data for CryptImportKey() function (include key and version and so on...)
AESBlob.bhHdr.bType = PLAINTEXTKEYBLOB;
AESBlob.bhHdr.bVersion = CUR_BLOB_VERSION;
AESBlob.bhHdr.reserved = 0;
AESBlob.bhHdr.aiKeyAlg = CALG_AES_256;
AESBlob.dwKeySize = DEFAULT_AES_KEY_SIZE;
StrCpyA((LPSTR)AESBlob.szBytes, (LPCSTR)szKey);
// create a cryptographic service provider (CSP)
if (!CryptAcquireContextA(&hProv, NULL, MS_ENH_RSA_AES_PROV_A, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
PRINT_FUNC_ERR_AND_RETURN(CryptAcquireContextA);
}
if (!CryptImportKey(hProv, (BYTE*)&AESBlob, sizeof(AES256KEYBLOB), NULL, CRYPT_EXPORTABLE, &hKey)) {
CryptReleaseContext(hProv, 0);
PRINT_FUNC_ERR_AND_RETURN(CryptImportKey);
}
if (!CryptSetKeyParam(hKey, KP_IV, szIV, 0)) {
CLEANUP_CRYPT_STUFF(hProv, hKey);
PRINT_FUNC_ERR_AND_RETURN(CryptSetKeyParam);
}
if (CryptEncrypt(hKey, NULL, TRUE, 0, NULL, &dwBufSize, 0)) {
printf("%d bytes required to hold the encrypted buf\n", dwBufSize);
if ((pBuf = calloc(dwBufSize, sizeof(BYTE))) == NULL)
{
CLEANUP_CRYPT_STUFF(hProv, hKey);
PRINT_FUNC_ERR_AND_RETURN(calloc);
}
StrCpyA(pBuf, szPlainText);
} else {
CLEANUP_CRYPT_STUFF(hProv, hKey);
PRINT_FUNC_ERR_AND_RETURN(CryptEncrypt);
}
if (CryptEncrypt(hKey, NULL, TRUE, 0, pBuf, &dwBufSize2, dwBufSize)) {
printf("\nEncrypted data: [%s]\nSize: %d\n", (LPCSTR)pBuf, dwBufSize2);
if (CryptDecrypt(hKey, NULL, TRUE, 0, pBuf, &dwBufSize)) {
printf("\nDecrypted data: [%s]\nSize: %d\n", (LPCSTR)pBuf, dwBufSize);
} else {
free(pBuf);
CLEANUP_CRYPT_STUFF(hProv, hKey);
PRINT_FUNC_ERR_AND_RETURN(CryptDecrypt);
}
} else {
free(pBuf);
CLEANUP_CRYPT_STUFF(hProv, hKey);
PRINT_FUNC_ERR_AND_RETURN(CryptEncrypt);
}
free(pBuf);
CLEANUP_CRYPT_STUFF(hProv, hKey);
return 0;
}
注释:
AES256KEYBLOB
构造函数(这在使用内存“不是你的”时很正常)。将结构初始化替换为memset
调用(逻辑)主要错误是缓冲区不够大,无法存储加密的文本(结合了错误的值( 0 )用于dwPlainSize
-使函数误导成功)。根据{{3}}:
如果此参数包含 NULL ,则此函数将计算密文所需的大小,并将其放在 pdwDataLen 参数所指向的值中。
要找出所需的大小,请另外调用该函数,将pbData
设置为NULL
(在其他 WinAPI 中也会遇到这种情况)。然后分配一个缓冲区,用所需的数据填充它,并使“ main”在该缓冲区上调用函数...
添加了丢失的#include
和main
if
条件,因为我不喜欢这么多的嵌套级别CLEANUP_CRYPT_STUFF
,PRINT_FUNC_ERR_AND_RETURN
),以避免代码重复%s
说明符仅在遇到\0
时停止,只有{哑}的运气阻止了printf
缓冲时,控制台充满了垃圾(甚至导致程序崩溃)输出:
48 bytes required to hold the encrypted buf Encrypted data: [<É╙åh∩φ:bOPs r2w~w╪c╟D╡ï╥V╟neΓßv∩·J8cÅ╥²²²²s] Size: 48 Decrypted data: [abcdefghijklmnopqrstuvwxyzabcdefΓßv∩·J8cÅ╥²²²²s] Size: 32
答案 1 :(得分:2)
CristiFati
的答案很好,这使我可以使用波纹管语句来计算密码长度:
CryptEncrypt(hKey, NULL, TRUE, 0, NULL, &dwBufSize, 0);
根据Microsoft文档:
如果 pbData 为 NULL ,则不会返回任何错误,并且该函数将加密数据的大小(以字节为单位)存储在pdwDataLen指向的DWORD值中) :
BOOL CryptEncrypt(
HCRYPTKEY hKey,
HCRYPTHASH hHash,
BOOL Final,
DWORD dwFlags,
BYTE *pbData,
DWORD *pdwDataLen,
DWORD dwBufLen
);
我的解决方案:
但是在我的代码中,当我将szPlainText
赋给CryptEncrypt()
时,我只是忘记了计算大小:
DWORD dwPlainSize = 0; // initialized with 0
因此,“零长度”对于波纹管功能没有任何意义(CryptEncrypt()
函数始终获得长度为0
的纯文本):
CryptEncrypt(hKey, NULL, TRUE, 0, szPlainText, &dwPlainSize, lstrlenA((LPCSTR)szPlainText) + 1)
我应该用下面的语句设置它的大小(只需添加以下内容,我的code
就可以工作):
dwPlainSize = lstrlenA((LPCSTR)szPlainText);
然后在正确的情况下传递它:
CryptEncrypt(hKey, NULL, TRUE, 0, szPlainText, &dwPlainSize, BUFFER_FOR_PLAINTEXT)
所以,输出就像下面这样:
Encrypted data : <É╙åh∩φ:bOPs r2w~w╪c╟D╡ï╥V╟neΓßv∩·J8cÅ╥
Size : 48
Decrypted data : abcdefghijklmnopqrstuvwxyzabcdefΓßv∩·J8cÅ╥
Size : 32