gpt4 book ai didi

c++ - Wincrypt : Unable to decrypt file which was encrypted in C#. NTE_BAD_DATA 在 CryptDecrypt

转载 作者:行者123 更新时间:2023-11-30 02:12:39 27 4
gpt4 key购买 nike

我正在尝试使用 wincrypt 解密一段文件,但我似乎无法正确解密此函数。这些字节使用 C# 中的 RC2 实现加密,我为加密和解密过程提供相同的密码和 IV(在 C# 中加密,在 C++ 中解密)。

在最后的“CryptDecrypt”函数之前,我的所有函数都返回 true。不用我再打字了,这里是函数:

static char* DecryptMyFile(char *input, char *password, int size)
{
HCRYPTPROV provider = NULL;

if(CryptAcquireContext(&provider, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0))
{printf("Context acquired.");}
else
{
if (GetLastError() == NTE_BAD_KEYSET)
{
if(CryptAcquireContext(&provider, 0, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET))
{printf("new key made.");}
else
{
printf("Could not acquire context.");
}
}
else
{printf("Could not acquire context.");}
}

HCRYPTKEY key = NULL;
HCRYPTHASH hash = NULL;

if(CryptCreateHash(provider, CALG_MD5, 0, 0, &hash))
{printf("empty hash created.");}
else
{printf("could not create hash.");}

if(CryptHashData(hash, (BYTE *)password, strlen(password), 0))
{printf("data buffer is added to hash.");}
else
{printf("error. could not add data buffer to hash.");}

if(CryptDeriveKey(provider, CALG_RC2, hash, 0, &key))
{printf("key derived.");}
else
{printf("Could not derive key.");}

DWORD dwKeyLength = 128;

if(CryptSetKeyParam(key, KP_EFFECTIVE_KEYLEN, reinterpret_cast<BYTE*>(&dwKeyLength), 0))
{printf("success");}
else
{printf("failed.");}

BYTE IV[8] = {0,0,0,0,0,0,0,0};

if(CryptSetKeyParam(key, KP_IV, IV, 0))
{printf("worked");}
else
{printf("faileD");}

DWORD dwCount = size;
BYTE *decrypted = new BYTE[dwCount + 1];

memcpy(decrypted, input, dwCount);
decrypted[dwCount] = 0;


if(CryptDecrypt(key,0, true, 0, decrypted, &dwCount))
{printf("succeeded");}
else
{printf("failed");}

return (char *)decrypted;
}

输入是传递给函数的加密数据。 password 与用于在 C# 中加密数据的密码相同。 size 是加密时数据的大小。
在 CryptDecrypt 之前,上述所有函数都返回 true,我似乎无法弄清楚原因。同时,我不确定 CryptDecrypt 函数如何编辑我的“解密”变量,因为我没有传递它的引用。

对于为什么这不起作用的任何帮助或建议,我们将不胜感激。这是我第一次尝试使用 wincrypt,也是多年来第一次使用 C++。

如果还有帮助,这是我的加密(在 C# 中):

 public static byte[] EncryptString(byte[] input, string password)
{
PasswordDeriveBytes pderiver = new PasswordDeriveBytes(password, null);
byte[] ivZeros = new byte[8];
byte[] pbeKey = pderiver.CryptDeriveKey("RC2", "MD5", 128, ivZeros);

RC2CryptoServiceProvider RC2 = new RC2CryptoServiceProvider();

//using an empty initialization vector for convenience.
byte[] IV = new byte[8];
ICryptoTransform encryptor = RC2.CreateEncryptor(pbeKey, IV);

MemoryStream msEncrypt = new MemoryStream();
CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);
csEncrypt.Write(input, 0, input.Length);
csEncrypt.FlushFinalBlock();

return msEncrypt.ToArray();
}

我已确认我在 C++ 中的哈希值与我在 C# 中的 key 相同,由 PasswordDeriveBytes.CryptDeriveKey 创建

最佳答案

首先,如我的评论所述,使用 GetLastError() 以便您知道什么它失败了。我假设您得到 NTE_BAD_DATA,所有其他错误都更容易处理,因为它们基本上意味着您错过了 API 调用序列中的某个步骤。

CryptDecrypt 因 NTE_BAD_DATA 而失败的典型原因是您正在解密 block 密码的最后一个 block (如您所愿)并且解密的填充字节不正确。如果输入被截断(并非所有加密字节都保存到文件中)或 key 不正确,就会发生这种情况。

我建议您有条不紊地进行此操作,因为有很多地方可能会失败,并且只会在 CryptDecrypt 时间出现:

  1. 确保您用 C# 加密的文件可以用 C# 解密。这将消除任何文件保存截断问题。
  2. 首先尝试使用固定的硬编码 key (不派生密码)进行加密和解密,这将确保您的 key 集代码 IV 初始化正确(以及填充模式和密码链模式)。
  3. 确保密码派生过程使用相同的哈希值。诸如 ANSI 与 Unicode 或终端 0 之类的东西可能会对 MD5 散列造成严重破坏,并导致表面上相同的密码散列产生截然不同的 key 。

关于c++ - Wincrypt : Unable to decrypt file which was encrypted in C#. NTE_BAD_DATA 在 CryptDecrypt,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1546447/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com