Я пытаюсь использовать алгоритм Windows CNG BCRYPT_XTS_AES_ALGORITHM
для шифрования и расшифровки файлов. В рамках этого я написал следующий код для шифрования и дешифрования.
Когда я использую этот код с алгоритмом BCRYPT_AES_ALGORITHM
, шифрование и дешифрование работают нормально. Но когда то же самое используется с BCRYPT_XTS_AES_ALGORITHM
, он выдает ошибку STATUS_INVALID_PARAMETER
в BCryptGenerateSymmetricKey
API.
Любая помощь в этом очень ценится.
auto AesCrypt::CreateAESProviderAlgo()->void
{
auto status = BCryptOpenAlgorithmProvider(&m_aesHandle, BCRYPT_AES_ALGORITHM, nullptr, 0);
//auto status = BCryptOpenAlgorithmProvider(&m_aesHandle, BCRYPT_XTS_AES_ALGORITHM, nullptr, 0);
if (0 != status) {
N2S_THROW("BCryptException::Failed to get provider for BCRYPT_XTS_AES_ALGORITHM. Reason: " + GetErrorCodeAsString(status));
}
DWORD cbData = 0;
DWORD cbKeyObject = 0;
status = BCryptGetProperty(m_aesHandle, BCRYPT_OBJECT_LENGTH, (PBYTE)&cbKeyObject, sizeof(DWORD), &cbData, 0);
if (0 != status) {
N2S_THROW("CreateSymmetricKeySHA1Hash::BCryptGetProperty return with error " + GetErrorCodeAsString(status));
}
m_pbKeyObject = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbKeyObject);
if (nullptr == m_pbKeyObject) {
N2S_THROW("CreateSymmetricKeySHA1Hash::Memory allocation failed.");
}
status = BCryptGenerateSymmetricKey(m_aesHandle, &m_keyHandle, m_pbKeyObject, cbKeyObject, (PUCHAR)m_encrptKey.c_str(), SYMM_KEY_SIZE_SECRET, 0);
if (0 != status) {
N2S_THROW("CreateSymmetricKeySHA1Hash::BCryptGenerateSymmetricKey return with error " + GetErrorCodeAsString(status));
}
}
auto AesCrypt::ProcessEncryptFile() ->void
{
DWORD bytesToSave = 0;
UCHAR bufFileToOpen[BLOCK_SIZE] = { 0 };
UCHAR bufFileToSave[BLOCK_SIZE * 2] = { 0 }; // TODO: Need to alloc on heap and reuse it.
auto toReadBytes = GetFileSize(m_workOnFile);
for (;;) // TODO: Need to take out the duplicate code from both locations.
{
m_readStream.read((CHAR *)bufFileToOpen, BLOCK_SIZE);
auto bytesRead = m_readStream.gcount();
if (0 == bytesRead) {
N2S_THROW("Error reading the file " + GetStringFromWstring(m_workOnFile));
}
toReadBytes -= bytesRead;
if (0 != toReadBytes && bytesRead == BLOCK_SIZE) {
GetCryptStatus(BCryptEncrypt(m_keyHandle, bufFileToOpen, (ULONG)bytesRead, nullptr, nullptr, 0, bufFileToSave, (ULONG)bytesRead, &bytesToSave, 0));
m_writeStream.write((CHAR *)bufFileToSave, bytesToSave);
continue;
}
// Reading the last byte
if (0 != BCryptEncrypt(m_keyHandle, bufFileToOpen, (ULONG)bytesRead, nullptr, nullptr, 0, nullptr, 0, &bytesToSave, BCRYPT_BLOCK_PADDING)) {
N2S_THROW("BCryptEncrypt::Error receiving the size required for the ciphertext.");
}
GetCryptStatus(BCryptEncrypt(m_keyHandle, bufFileToOpen, (ULONG)bytesRead, nullptr, nullptr, 0, bufFileToSave, bytesToSave, &bytesToSave, BCRYPT_BLOCK_PADDING));
m_writeStream.write((CHAR *)bufFileToSave, bytesToSave);
return; // Last block done.
}
}
auto AesCrypt::ProcessDecryptFile()->void
{
DWORD bytesToSave = 0;
UCHAR bufFileToOpen[BLOCK_SIZE] = { 0 };
UCHAR bufFileToSave[BLOCK_SIZE * 2] = { 0 }; // TODO: Need to alloc on heap and reuse it.
auto toReadBytes = GetFileSize(m_workOnFile);
for (;;)
{
m_readStream.read((CHAR *)bufFileToOpen, BLOCK_SIZE);
auto bytesRead = m_readStream.gcount();
if (0 == bytesRead) {
N2S_THROW("Error reading the file " + GetStringFromWstring(m_workOnFile));
}
toReadBytes -= bytesRead;
if (0 != toReadBytes && bytesRead == BLOCK_SIZE) {
GetCryptStatus(BCryptDecrypt(m_keyHandle, bufFileToOpen, (ULONG)bytesRead, nullptr, nullptr, 0, bufFileToSave, (ULONG)bytesRead, &bytesToSave, 0));
m_writeStream.write((CHAR *)bufFileToSave, bytesToSave);
continue;
}
// Reading last block data
if (0 != BCryptDecrypt(m_keyHandle, bufFileToOpen, (ULONG)bytesRead, nullptr, nullptr, 0, nullptr, 0, &bytesToSave, BCRYPT_BLOCK_PADDING)) {
N2S_THROW("BCryptEncrypt::Error receiving the size required for the ciphertext.");
}
GetCryptStatus(BCryptDecrypt(m_keyHandle, bufFileToOpen, (ULONG)bytesRead, nullptr, nullptr, 0, bufFileToSave, bytesToSave, &bytesToSave, BCRYPT_BLOCK_PADDING));
m_writeStream.write((CHAR *)bufFileToSave, bytesToSave);
return; // Last block done.
}
}
BCRYPT_SUCCESS
оцениваетtrue
как неотрицательное. Таким образом, вы можете попробовать заменить0 != status
макросом!BCRYPT_SUCCESS(status)
, а затем посмотреть, что произойдет. Кроме того, вы также можете взглянуть на этот ответ =› Есть ли примеры выполнения шифрования AES-XTS? с использованием СПГ? - person sandthorn   schedule 23.07.2018STATUS_INVALID_PARAMETER
означает, что вы можете ввести неверные типы переменных. Убедитесь, что вашm_keyHandle
имеет типBCRYPT_KEY_HANDLE
, аSYMM_KEY_SIZE_SECRET
имеет типULONG
и меньше или равенm_encrptKey.size()
. Я попытался скомпилировать Win10SDK v10.0.16299.0, и функцияBCryptGenerateSymmetricKey
возвращаетBCRYPT_SUCCESS
status =› godbolt. document =›BCryptGenerateSymmetricKey
- person sandthorn   schedule 31.07.2018BCRYPT_AES_GMAC_ALGORITHM
, но я так и не понял почему. Также см. Как использовать AES-GMAC с секретом в BCrypt? и Как определить, какой из 23 параметров является STATUS_INVALID_PARAMETER? - person jww   schedule 19.08.2019