【问题标题】:AES/Rijndael in C++ Microsoft CryptoAPIC++ Microsoft CryptoAPI 中的 AES/Rijndael
【发布时间】:2014-10-25 20:57:14
【问题描述】:

如何使用 Microsoft CryptoAPI(CryptDeriveKey、BCrypt[...] 函数、CryptAcquireContext 等)将以下加密代码 (VB.NET 4.0) 转换为 C++ 等效代码? (我在 Internet 上没有找到一篇描述使用 Microsoft CryptoAPI 进行 AES 的文章……)

Dim Key(31) As Byte
Dim IV(15) As Byte

Array.Copy(SomeByteArray, IV, 16)
Array.Copy((New SHA512Managed).ComputeHash(SomeByteArray), Key, 32)

Using AESEncr As New RijndaelManaged() With {.Padding = PaddingMode.ISO10126}

    FinalEncrypted = AESEncr.CreateEncryptor(Key, IV).TransformFinalBlock(AnotherByteArray, 0, AnotherByteArray.GetLength(0))

End Using

还有解密的:

Dim Key(31) As Byte
Dim IV(15) As Byte

Array.Copy(SomeByteArray, IV, 16)
Array.Copy((New SHA512Managed).ComputeHash(SomeByteArray), Key, 32)

Using AESEncr As New RijndaelManaged() With {.Padding = PaddingMode.ISO10126}

    FinalDecrypted = AESEncr.CreateDecryptor(Key, IV).TransformFinalBlock(FinalEncrypted, 0, FinalEncrypted.GetLength(0))

End Using

(注意:我已经有关于 SHA-512 方法的 C++ 代码,所以不要为此烦恼。)

【问题讨论】:

  • 如果您不介意我们希望您自己尝试一下,如果您卡在某个地方,请返回。
  • 开始阅读here,然后写一些代码看看会发生什么。
  • @owlstead 我找到了如何使用 CNG BCrypt.dll,但是:1)它不支持 Windows XP,上面的 .NET 代码支持,2)它不支持自定义密钥/ iv 长度(属性 BCRYPT_OBJECT_LENGTH 和 BCRYPT_BLOCK_LENGTH 是只读的)和 3)它不支持从字节数组设置自定义键(我假设是这样,因为我读过 this code)。那么,我能做些什么来解决上述所有问题呢? (放弃 XP 平台对我来说不是一个选择……)
  • @owlstead 我找不到密钥长度为 32 字节的 AES 的任何 ALG_ID,只有 128 字节+(就 advapi32 的功能(CryptAcquireContext 等)而言,并且使用 the above comment 我证明了这一点bcrypt函数没用,所以我认为没有选择)...
  • 也许你真的不是 VB/C++ 的初学者,但你要求我们给你一个例子使用MS CryptoAPI,为此您坚持认为它不支持 AES-256(仅在 cmets 中)。我不知道你的 C++ 技能,但上面很清楚你是在这里提问的初学者。

标签: c++ vb.net encryption cryptoapi mscapi


【解决方案1】:

所以,我为 AES-256 加密/解密编写的代码如下:(它以 BYTE* DataBYTE* IV 作为参数)

    BYTE *hash, *res;
    HCRYPTPROV hCrypt = NULL;
    HCRYPTKEY hKey = NULL;

    struct {
        BLOBHEADER hdr;
        DWORD len;
        BYTE key[32];
    } key_blob;

    key_blob.hdr.bType = PLAINTEXTKEYBLOB;
    key_blob.hdr.bVersion = CUR_BLOB_VERSION;
    key_blob.hdr.reserved = 0;
    key_blob.hdr.aiKeyAlg = CALG_AES_256;
    key_blob.len = 32;

    hash = ComputeSHA512Hash(IV);
    copy(hash, hash + 32, key_blob.key);

    res = new BYTE[16];
    copy(Data, Data + 15, res);
    res[15] = 0;

    // Get the Microsoft Enhanced RSA and AES Cryptographic Service Provider

    if (!CryptAcquireContext(&hCrypt, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, 0))
        throw E_FAIL;

    // Import our key blob

    if (!CryptImportKey(hCrypt, (BYTE *)&key_blob, sizeof(key_blob), NULL, 0, &hKey))
        throw E_FAIL;

    // Set the mode to Cipher Block Chaining

    DWORD dwMode = CRYPT_MODE_CBC;

    if (!CryptSetKeyParam(hKey, KP_MODE, (BYTE *)&dwMode, 0))
        throw E_FAIL;

    // Set the Initialization Vector to ours

    if (!CryptSetKeyParam(hKey, KP_IV, IV, 0))
        throw E_FAIL;

    // Do the main encryption

    DWORD pdwDataLen = 15;

    if (!CryptEncrypt(hKey, NULL, TRUE, 0, res, &pdwDataLen, 16))
        throw E_FAIL;

    // Do the main decryption

    pdwDataLen = 16;

    if (!CryptDecrypt(hKey, NULL, TRUE, 0, res, &pdwDataLen))
        throw E_FAIL;

     // Destroy whatever was created before (free memory)

     delete hash;

     delete res;

     if (hKey)
            CryptDestroyKey(hKey);

     if (hCrypt)
            CryptReleaseContext(hCrypt, 0);

正如我之前所说,我已经有了 ComputeSHA512Hash() 函数的代码,所以我的代码对于我的目的来说是完整的。我希望这段代码对所有想编写 AES-256 代码的人有用。

【讨论】:

    猜你喜欢
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 2012-05-02
    • 1970-01-01
    • 1970-01-01
    • 2023-03-13
    • 1970-01-01
    • 2010-10-19
    相关资源
    最近更新 更多