C++ 使用WinCrypt的AES-128加密

C++ 使用WinCrypt的AES-128加密,c++,c,aes,cryptoapi,wincrypt,C++,C,Aes,Cryptoapi,Wincrypt,我需要使用WinCrypt为我的C/C++应用程序加密AES-128下的字符串 为了理解整个过程是如何工作的,我编写了一个程序,用16字节AES密钥(128位)加密16字节字符串,但它没有按预期工作(MSDN示例也没有帮助) 我的主要问题是调用CryptEncrypt,我可能不清楚如何使用参数: *pbData *pdwDataLen 德布弗伦 这是我的密码: #include <windows.h> #include <stdio.h> #include <

我需要使用WinCrypt为我的C/C++应用程序加密AES-128下的字符串

为了理解整个过程是如何工作的,我编写了一个程序,用16字节AES密钥(128位)加密16字节字符串,但它没有按预期工作(MSDN示例也没有帮助)

我的主要问题是调用CryptEncrypt,我可能不清楚如何使用参数:

  • *pbData
  • *pdwDataLen
  • 德布弗伦
这是我的密码:

#include <windows.h> 
#include <stdio.h>
#include <wincrypt.h>
#define ENCRYPT_ALGORITHM CALG_AES_128

int main()
{

  HCRYPTPROV hCryptProv;
  HCRYPTKEY hKey;

//---------------------------------------------------------------
// Get the handle to the provider.
if(CryptAcquireContext(
    &hCryptProv, 
    NULL, 
    NULL, //MS_ENH_RSA_AES_PROV
    PROV_RSA_AES, 
    0))
{
    printf("A cryptographic provider has been acquired. \n");
}
else
{
    printf("Error during CryptAcquireContext!\n");
    exit(1);
}


//---------------------------------------------------------------
//  Create a random session key. 

 if(CryptGenKey(
          hCryptProv, 
          ENCRYPT_ALGORITHM, 
          CRYPT_EXPORTABLE, //KEYLENGTH | CRYPT_EXPORTABLE, 
          &hKey))
 {
         printf("A session key has been created.\n");
 } 
 else
 {
          printf("Error during CryptGenKey.\n"); 
          exit(1);
 }
}

char text_test [] = "abcdabcdabcdabcd";
   DWORD text_len = strlen(text_test);

   printf("PlainText: %s\n",text_test);
   printf("Buf Len: %d\n",text_len);

   if (!CryptEncrypt(hKey,
                    NULL,  // hHash = no hash
                    1,  // Final
                    0,     // dwFlags
                    &text_test, //*pbData
                    &text_len,  //*pdwDataLen
                    32)) {      //dwBufLen
     printf("Encryption failed\n");
   }

   printf("CipherText: %s\n",text_test);
   printf("Len: %d\n",text_len);

   if (!CryptDecrypt(hKey,
                    NULL,  // hHash = no hash
                    1,  // Final
                    0,     // dwFlags
                    &text_test,
                    &text_len)) {
     printf("Decryption failed\n");
   }

   printf("PlainText: %s\n",text_test);
   printf("Len: %d\n",text_len);
.
.
.
CryptDestroyKey(hKey)
.
.
CryptReleaseContext(hCryptProv, 0)
.
#包括
#包括
#包括
#定义加密算法计算AES 128
int main()
{
HCRYPTPROV HCRYPTPROV;
HCRYPTKEY hKey;
//---------------------------------------------------------------
//获取提供程序的句柄。
如果(加密)上下文(
&hCryptProv,
无效的
NULL,//MS\u ENH\u RSA\u AES\u PROV
证明,
0))
{
printf(“已获取加密提供程序。\n”);
}
其他的
{
printf(“加密过程中出错!\n”);
出口(1);
}
//---------------------------------------------------------------
//创建一个随机会话密钥。
if(cryptgenekey)(
hCryptProv,
加密算法,
CRYPT_EXPORTABLE,//KEYLENGTH | CRYPT_EXPORTABLE,
&(港币)
{
printf(“已创建会话密钥。\n”);
} 
其他的
{
printf(“CryptGenKey期间出错。\n”);
出口(1);
}
}
char text_test[]=“abcdabcdcdcdabcdcdabcd”;
DWORD text\u len=strlen(text\u测试);
printf(“纯文本:%s\n”,文本测试);
printf(“基本长度:%d\n”,文本长度);
如果(!CryptEncrypt(hKey,
NULL,//hHash=无哈希
1,//最终版本
0,//dwFlags
&文本测试,//*pbData
&text_len,//*pdwDataLen
32)){//dwBufLen
printf(“加密失败\n”);
}
printf(“密文:%s\n”,文本测试);
printf(“Len:%d\n”,text\u Len);
如果(!CryptDecrypt(hKey,
NULL,//hHash=无哈希
1,//最终版本
0,//dwFlags
&文本测试,
&文本(小标题){
printf(“解密失败\n”);
}
printf(“纯文本:%s\n”,文本测试);
printf(“Len:%d\n”,text\u Len);
.
.
.
加密密钥(hKey)
.
.
CryptReleaseContext(hCryptProv,0)
.
cmd中的输出为:


有人能解释一下为什么解密的字符串更长,哪一个是CryptEncrypt的三个参数的正确用法吗?我将最后一个值设置为32,因为经过一些尝试和错误之后,这是唯一一个使这个东西工作的值。请帮忙,提前谢谢你

我也不熟悉crytography,但此代码可能有您的解决方案:

  // This acts as both the length of bytes to be encoded (on input) and the
  // number of bytes used in the resulting encrypted data (on output).
  DWORD length = kAesBytes128;
  if (!CryptEncrypt(hKey,
                    NULL,  // hHash = no hash
                    true,  // Final
                    0,     // dwFlags
                    reinterpret_cast<BYTE*>(encrypted->data()),
                    &length,
                    encrypted->length())) {
    throw std::runtime_error("Encryption failed");
  }

  // See comment above.
  encrypted->chop(length - kAesBytes128);
//它同时充当要编码的字节长度(输入时)和
//结果加密数据中使用的字节数(输出时)。
DWORD长度=kAesBytes128;
如果(!CryptEncrypt(hKey,
NULL,//hHash=无哈希
对,//最终
0,//dwFlags
重新解释强制转换(加密->数据()),
&长度,
加密->长度()){
抛出std::runtime_错误(“加密失败”);
}
//见上面的评论。
加密->印章(长度-kAesBytes128);

或者我可能有一些类似的项目代码,使用Crypto++

它的填充。默认情况下,插入的填充量与加密的字节相同。忽略最后16个字节。前16个字节是您想要的。

我想解密字符串的其余部分是padding@zapredelom是的,我认为它可能是填充,但我不知道如何正确使用CryptEncrypt的参数。谢谢,但我在发布问题之前看到了这篇文章。在本例中,我不理解参数*pbData或dwBufLen。我不知道如何在我的代码中使用它们。是API文档
pbData-指向包含要加密的明文的缓冲区的指针。此缓冲区中的明文将被此函数创建的密文覆盖。
dwBufLen-指定输入pbData缓冲区的总大小(以字节为单位)。
对我来说似乎很简单。此外,AES是块密码,因此此限制适用:
使用块密码时,此数据长度必须是块大小的倍数,除非这是要加密的数据的最终部分,且最终参数为真。