簡體   English   中英

CNG AES-> C#AES

[英]CNG AES -> C# AES

我想用C# 編寫一個可以打開KeePass 1.x kdb文件的程序。 我下載了源代碼,並嘗試移植密碼數據庫讀取功能。 數據庫內容已加密。 通過以下方式獲得加密密鑰:

  1. 用戶輸入密碼;
  2. 計算SHA256密碼的哈希值並將其分成兩個128個一半。
  3. 使用數據庫頭中的密鑰,將幾輪AES應用於哈希的每半部分;
  4. 將一半串聯起來;
  5. 結果用數據庫標頭中的鹽腌;
  6. 計算第4步結果的SHA256哈希。 那就是加密密鑰。

我被困在第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個參數傳遞,這意味着它將不使用初始化向量。

現在,我該如何在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個字節,它將產生我所需要的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM