gpt4 book ai didi

c# - CNG AES -> C# AES

转载 作者:太空宇宙 更新时间:2023-11-04 14:02:24 29 4
gpt4 key购买 nike

我想用 C# 编写一个可以打开 KeePass 的程序1.x kdb 文件。我下载了源代码并尝试移植密码数据库读取功能。数据库内容已加密。加密 key 通过以下方式获得:

  1. 用户输入密码;
  2. 计算密码的 SHA256 哈希值并将其拆分为两个 128 位的一半;
  3. 使用数据库 header 中的 key 将几轮 AES 应用于哈希的每一半;
  4. 将两半连接起来;
  5. 结果用数据库头中的盐加盐;
  6. 计算第 4 步结果的 SHA256 哈希值。那就是加密 key 。

我卡在了第 3 步。KeePass 使用 CNG对于 AES。简化的来源(对于一半的哈希,另一半也适用于它):

BCRYPT_ALG_HANDLE hAes = NULL;
BCRYPT_KEY_HANDLE hKey = NULL;
BYTE pbKey32[32] = <encryption key>;
BYTE pbData16[16] = <half of hash from step 2>;

BCryptOpenAlgorithmProvider(&hAes, BCRYPT_AES_ALGORITHM, NULL, 0);

DWORD dwKeyObjLen = 0;
ULONG uResult = 0;
BCryptGetProperty(hAes, BCRYPT_OBJECT_LENGTH, (PUCHAR)&dwKeyObjLen, sizeof(DWORD), &uResult, 0);

BCryptSetProperty(hAes, BCRYPT_CHAINING_MODE, (PUCHAR)BCRYPT_CHAIN_MODE_ECB, static_cast<ULONG>((wcslen(BCRYPT_CHAIN_MODE_ECB) + 1) * sizeof(wchar_t)), 0);

BCRYPT_KEY_DATA_BLOB_32 keyBlob;
ZeroMemory(&keyBlob, sizeof(BCRYPT_KEY_DATA_BLOB_32));
keyBlob.dwMagic = BCRYPT_KEY_DATA_BLOB_MAGIC;
keyBlob.dwVersion = BCRYPT_KEY_DATA_BLOB_VERSION1;
keyBlob.cbKeyData = 32;
memcpy(keyBlob.pbData, pbKey32, 32);
pKeyObj = new UCHAR[dwKeyObjLen];

BCryptImportKey(hAes, NULL, BCRYPT_KEY_DATA_BLOB, &hKey, pKeyObj.get(), dwKeyObjLen, (PUCHAR)&keyBlob, sizeof(BCRYPT_KEY_DATA_BLOB_32), 0);

for (int i = 0; i < rounds; ++i)
{
BCryptEncrypt(hKey, pbData16, 16, NULL, NULL, 0, pbData16, 16, &uResult, 0);
}

因此,据我所知,它使用具有 ECB 链接模式的 AES 算法,并将 NULL0 作为 BCryptEncrypt 的第 5 个和第 6 个参数传递。函数意味着它不会使用初始化 vector 。

现在,我如何在 C# 中执行相同的操作?我编写了以下函数来进行一轮转换(基于 MSDN 示例):

    public static byte[] KeyTransform(byte[] buffer, byte[] key)
{
Aes aes = Aes.Create();
aes.Key = key;
aes.BlockSize = 128;
aes.KeySize = key.Length * 8;
aes.Mode = CipherMode.ECB;
//aes.IV = new byte[16] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

ICryptoTransform ct = aes.CreateEncryptor();
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, ct, CryptoStreamMode.Write))
{
using (BinaryWriter bw = new BinaryWriter(cs))
{
bw.Write(buffer);
}

cs.Flush();
}

return ms.ToArray();
}
}

然后我在原始代码和我的代码中应用一轮 AES 后比较缓冲区。我的代码产生与原始代码不同的结果。我该如何解决?

顺便说一句,无论我是否指定 IV,我的代码每次都会产生不同的结果(所以我相信 IV 总是会生成和使用)。如果我尝试将 aes.IV 设置为 null,它会抛出异常,提示我无法将其设置为 null

最佳答案

似乎像这样初始化 ICryptoTransform:

ICryptoTransform ct = aes.CreateEncryptor(key, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 });

成功了。唯一让我担心的是生成的内存流有 32 个字节而不是 16 个字节。但是如果我删除最后 16 个字节,它会产生我需要的东西。

关于c# - CNG AES -> C# AES,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18679696/

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