【问题标题】:Use AES CBC with NCrypt in windows在 Windows 中使用 AES CBC 和 NCrypt
【发布时间】:2017-01-06 18:03:01
【问题描述】:

我正在尝试使用 NCrypt.dll 在 C++ 中加密一些数据,但在处理密钥和算法时遇到了问题。

我想将 AES 与 CBC 链接方法一起使用,但无法让 NCryptEncrypt 函数工作(我不断收到无效的缓冲区大小)。

我已经使用 NCRYPT_AES_ALGORITHM 标志创建并存储了一个密钥(在密钥存储提供程序中),但不知道如何设置算法以使用 CBC 方法。

    secSt = NCryptCreatePersistedKey(phProvider, &keyHndl, NCRYPT_AES_ALGORITHM, keyname, 0, 0);

我尝试了一些属性设置但没有成功,所以我想知道这是否可以通过 NCrypt 实现?

我知道 Bcrypt 加密功能允许这样做,并尝试将我的 NCRYPT_KEY_HANDLE 转换为 BCRYPT_KEY_HANDLE 没有成功(所以我认为这是不可能的)。

【问题讨论】:

  • 我删除了 bcrypt 标签,因为它指向密码哈希算法,而不是 CNG 中的 BCrypt。哎呀,我不知道谁编写了 Mickeysoft API 文档,但这些人密集。 AES-GCM 是 AES_GMAC 对称加密算法。对,如何表明你不知道你到底在做什么。恐怕没有帮助。

标签: c++ cryptography cryptoapi cng


【解决方案1】:

您可以使用NCryptSetProperty 和BCrypt 常量BCRYPT_CHAIN_MODE_CBC 应用链接模式CBC。

请注意NCryptEncrypt 似乎不支持对称密钥的填充(参见NCryptEncrypt 中参数dwFlags 的描述)。所以我不得不应用一些穷人的明文填充来获得 16 个字节的倍数。如果没有填充,我也会得到状态码 0xc0000206 (STATUS_INVALID_BUFFER_SIZE)。

// Clear text for testing
static const char* clearText = "The quick brown fox jumps over the lazy dog. 1234567890.        ";
static const int clearTextLen = 64;

int main()
{
    LPCWSTR keyName = L"NCryptTest";
    SECURITY_STATUS status;
    NCRYPT_PROV_HANDLE hProvider;
    NCRYPT_KEY_HANDLE hKey;

    // Open storage provider
    status = NCryptOpenStorageProvider(&hProvider, NULL, 0);

    // Get stored key
    status = NCryptOpenKey(hProvider, &hKey, keyName, 0, 0);
    if (status == NTE_BAD_KEYSET)
    {
        // Create key if it doesn't exist
        status = NCryptCreatePersistedKey(hProvider, &hKey, BCRYPT_AES_ALGORITHM, keyName, 0, 0);
        status = NCryptFinalizeKey(hKey, 0);
    }

    // Set the chaining mode CBC
    LPCWSTR chainMode = BCRYPT_CHAIN_MODE_CBC;
    status = NCryptSetProperty(hKey, NCRYPT_CHAINING_MODE_PROPERTY, (PBYTE)chainMode, wcslen(chainMode) * 2 + 2, 0);

    // Encrypt the text
    DWORD outlen = -1;
    unsigned char* cipherData = new unsigned char[clearTextLen];
    status = NCryptEncrypt(hKey, (PBYTE)clearText, clearTextLen, NULL, cipherData, clearTextLen, &outlen, 0);

    // Cleanup
    delete[] cipherData;
    NCryptFreeObject(hKey);
    NCryptFreeObject(hProvider);

    return 0;
}

【讨论】:

  • 谢谢,这就是我想要的。为了清楚起见,只是一个快速的问题。 “穷人的填充”是明文末尾的 1234567890?
  • 穷人的填充是字符串末尾的空格。在 NCrypt 之上实现适当的填充(例如 PKCS#7)应该不会太难。
猜你喜欢
  • 2013-08-11
  • 1970-01-01
  • 2017-09-28
  • 2016-01-12
  • 2011-07-03
  • 2017-12-10
  • 2019-04-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多