CryptoAPI RSA: CryptDecrypt只在第一次解密,其他调用返回NTE_BAD_DATA
CryptoAPI RSA: CryptDecrypt decrypts only at the first time, other calls return NTE_BAD_DATA
我已经编写了加密/解密自定义长度的内存缓冲区的程序。加密结束得很好;但是我的解密代码只在任何缓冲区位置解密一次数据,这对应于块条目。其他块的解密以NTE_BAD_DATA结束。
你有什么建议为什么会发生这种情况?
这是我的加密代码:
void CWinRSA::FinishEncrypt(const char* pcbRawData, const size_t nDataSize, char** ppcbEcrData, size_t& rnEcrSize) const
{
if (m_hProvider == NULL)
{
throw ("Cannot encrypt data with wrong provider!!");
}
if (m_hKey == NULL)
{
throw ("Cannot encrypt data with a wrong key!!");
}
size_t nBlockLength = GetBlockLength();
size_t nPaddingSize = nBlockLength - 11;
size_t nRemain = nDataSize % nBlockLength;
size_t nBlockProcess = (nDataSize / nPaddingSize + (nRemain != 0 ? 1 : 0));
size_t nResultSize = nBlockProcess * nBlockLength;
(*ppcbEcrData) = new char[nResultSize];
DWORD dwBufferLength = nBlockLength;
DWORD dwDataLength;
for (int iBlock = 0; iBlock < nBlockProcess - 1; iBlock++)
{
memcpy((*ppcbEcrData) + (iBlock * nBlockLength),
pcbRawData + (iBlock * nPaddingSize), nPaddingSize);
dwDataLength = nPaddingSize;
if (!CryptEncrypt(m_hKey, NULL, FALSE, 0,
(BYTE*)((*ppcbEcrData) + (iBlock * nBlockLength)),
&dwDataLength, dwBufferLength))
{
throw ("Cannot encrypt data!!");
}
}
memcpy((*ppcbEcrData) + ((nBlockProcess - 1) * nBlockLength),
pcbRawData + ((nBlockProcess - 1) * nPaddingSize), (nRemain ? nRemain : nPaddingSize));
dwDataLength = (nRemain ? nRemain : nPaddingSize);
if (!CryptEncrypt(m_hKey, NULL, TRUE, 0,
(BYTE*)((*ppcbEcrData) + ((nBlockProcess - 1) * nBlockLength)),
&dwDataLength, dwBufferLength))
{
throw ("Cannot encrypt data!!");
}
rnEcrSize = nResultSize;
}
解密:
void CWinRSA::FinishDecrypt(const char* pcbRawData, const size_t nDataSize, char** ppcbDecData, size_t& rnDecSize) const
{
if (m_hProvider == NULL)
{
throw ("Cannot decrypt data with wrong provider!!");
}
if (m_hKey == NULL)
{
throw ("Cannot decrypt data with a wrong key!!");
}
size_t nBlockLength = GetBlockLength();
if ((nDataSize % nBlockLength) != 0)
{
throw ("Cannot decrypt data!! Probably data is corrupted!!");
}
size_t nPaddingSize = nBlockLength - 11;
size_t nBlockProcess = nDataSize / nBlockLength;
size_t nResultSize = nBlockProcess * nPaddingSize;
(*ppcbDecData) = new char[nResultSize];
DWORD dwDataLength;
char* pcbComputeResult = new char[nBlockLength];
for (int iBlock = 0; iBlock < nBlockProcess - 1; iBlock++)
{
memcpy(pcbComputeResult, pcbRawData + (iBlock * nBlockLength), nBlockLength);
if (!CryptDecrypt(m_hKey, NULL, FALSE, 0, (BYTE*)pcbComputeResult, &dwDataLength))
{
throw ("Cannot decrypt data!!");
}
memcpy((*ppcbDecData) + (iBlock * nPaddingSize), pcbComputeResult, nPaddingSize);
}
memcpy(pcbComputeResult, pcbRawData + ((nBlockProcess - 1) * nBlockLength), nBlockLength);
if (!CryptDecrypt(m_hKey, NULL, TRUE, 0, (BYTE*)pcbComputeResult, &dwDataLength))
{
DWORD dwError = GetLastError();
throw ("Cannot decrypt data!!");
}
memcpy((*ppcbDecData) + ((nBlockProcess - 1) * nPaddingSize), pcbComputeResult, nPaddingSize);
rnDecSize = ((nBlockProcess - 1) * nPaddingSize) + dwDataLength;
delete[] pcbComputeResult;
pcbComputeResult = NULL;
}
RSA不应该这样使用。它真的不是一个分组密码(或者流密码)。我的理解是,除了一条"短"消息外,它真的没有任何密码学用途,因此,在从密钥解密一次后,库失败并不令我感到惊讶。
如果你需要保护任意大小的数据,使用RSA交换对称密钥为流或块密码(如AES)
我找到了答案。在所有解密调用之前,我必须初始化dwDataLength,以字节为单位的块长度。
dwDataLength = nBlockLength;
if (!CryptDecrypt(m_hKey, NULL, TRUE, 0, (BYTE*)pcbComputeResult, &dwDataLength))
{
DWORD dwError = GetLastError();
throw ("Cannot decrypt data!!");
}
完整的解密方法
void CWinRSA::FinishDecrypt(const char* pcbRawData, const size_t nDataSize, char** ppcbDecData, size_t& rnDecSize) const
{
if (m_hProvider == NULL)
{
throw ("Cannot decrypt data with wrong provider!!");
}
if (m_hKey == NULL)
{
throw ("Cannot decrypt data with a wrong key!!");
}
size_t nBlockLength = GetBlockLength();
if ((nDataSize % nBlockLength) != 0)
{
throw ("Cannot decrypt data!! Probably data is corrupted!!");
}
size_t nPaddingSize = nBlockLength - 11;
size_t nBlockProcess = nDataSize / nBlockLength;
size_t nResultSize = nBlockProcess * nPaddingSize;
(*ppcbDecData) = new char[nResultSize];
DWORD dwDataLength;
char* pcbComputeResult = new char[nBlockLength];
for (int iBlock = 0; iBlock < nBlockProcess - 1; iBlock++)
{
memcpy(pcbComputeResult, pcbRawData + (iBlock * nBlockLength), nBlockLength);
dwDataLength = nBlockLength;
if (!CryptDecrypt(m_hKey, NULL, FALSE, 0, (BYTE*)pcbComputeResult, &dwDataLength))
{
throw ("Cannot decrypt data!!");
}
memcpy((*ppcbDecData) + (iBlock * nPaddingSize), pcbComputeResult, nPaddingSize);
}
memcpy(pcbComputeResult, pcbRawData + ((nBlockProcess - 1) * nBlockLength), nBlockLength);
dwDataLength = nBlockLength;
if (!CryptDecrypt(m_hKey, NULL, TRUE, 0, (BYTE*)pcbComputeResult, &dwDataLength))
{
throw ("Cannot decrypt data!!");
}
memcpy((*ppcbDecData) + ((nBlockProcess - 1) * nPaddingSize), pcbComputeResult, nPaddingSize);
rnDecSize = ((nBlockProcess - 1) * nPaddingSize) + dwDataLength;
delete[] pcbComputeResult;
pcbComputeResult = NULL;
}
相关文章:
- 我想在 Main 中用 C++ 调用其他类中的一个类,但我做不到
- 没有头文件如何使用c ++调用其他模块中的函数?
- 如何在调用其他使用 unique_lock 函数的类中使用unique_lock?
- 如何确保类的每个方法都首先调用其他方法
- 模板类根据其他类的存在性和优先级以及更多的类型限制(如常量和区分大小写)调用其他类的某些函数
- 如何调用将写入文件的函数,并在该函数中调用其他函数
- 创建模板函数以使用该功能参数调用其他函数
- 构造函数调用其他构造函数
- 调用其他专业功能
- 如何从VCL项目的消息循环中调用其他功能
- 无法调用其他类C++的析构函数
- 从C++构造函数调用其他函数
- 如何从c++中的静态线程入口点函数调用其他函数
- 用std::vector从dll调用其他dll的C++
- 定义一个调用其他函数的内联函数是否有意义
- 以下4种样式调用其他成员方法有什么区别?
- app.exec() 不能调用其他方法(static lib Qt)
- 内联类方法,用于调用其他文件的 anon 命名空间中的函数
- 我可以调用其他无关类的函数吗
- 调用其他类函数c++中的类函数