在 windows 中将 AES CBC 与 NCrypt 结合使用
Use AES CBC with NCrypt in windows
我正在尝试使用 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没有成功(所以我认为这是不可能的)。
您可以使用 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;
}
我正在尝试使用 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没有成功(所以我认为这是不可能的)。
您可以使用 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;
}