🏆本文收录于《全栈Bug调优(实战版)》专栏,主要记录项目实战过程中所遇到的Bug或因后果及提供真实有效的解决方案,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
问题描述
解密函数decrypt 以及加密块函数encryptBlock与解密块函数decryptBlock 是正确的,
并且已知 加密块函数encryptBlock与解密块函数decryptBlock 是完全可逆的函数;
但是运行测试代码 ,输出信息如下:
16|16|16
密钥加密数据: 12 34 56 78 9a bc de f0 23 45 67 89 ab cd ef 01
验证加密数据: 00 00 00 00 00 00 00 7d 29 4f 48 72 03 62 e8 b9
信息框提示 信息不匹配
请为我检查加密函数 encrypt 是否为decrypt 的完全逆向函数。 并给出decrypt 的逆向版本。
std::vector<uint8_t> 密钥加密 = {
0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01
};//假设这个是被密钥加密过的数据,长度合适 且为8的倍数;
//本文以16字节伪数据代表 ;并且 加密块函数encryptBlock与解密块函数decryptBlock 是完全可逆的函数
std::vector<uint8_t> CMFCPKGDlg::decrypt(const std::vector<uint8_t>& body, const std::vector<uint8_t>& key)
{
if (body.size() % 8 != 0 || key.size()!=16)
{
return{};
}
std::vector<uint8_t> prev_block(8, 0);
std::vector<uint8_t> prev_original_block(8, 0);
std::vector<uint8_t> result(body.size());
int resultIndex = 0;
int remain_j = 0;
for (size_t i = 0; i < body.size(); i += 8)
{
std::vector<uint8_t> decrypt_block(8);
for (int k = 0; k < 8; k++)
{
decrypt_block[k] = prev_block[k] ^ body[i + k];
}
std::vector<uint8_t> block = decryptBlock(decrypt_block, key);
int j = remain_j;
if (i == 0)
{
int header_offset = block[0] & 0x07;
j = header_offset + 3;
}
for (; j < 8; j++)
{
result[resultIndex++] = block[j] ^ prev_original_block[j];
}
if (j > 8)
{
remain_j = j % 8;
}
else
{
remain_j = 0;
}
prev_block = block;
prev_original_block = std::vector<uint8_t>(body.begin() + i, body.begin() + i + 8);
}
//while (resultIndex > 0 && result[resultIndex - 1] == 0x0)
//{
// --resultIndex;
//}
//result.resize(resultIndex);
return result;
}
std::vector<uint8_t> CMFCPKGDlg::encrypt(const std::vector<uint8_t>& body, const std::vector<uint8_t>& key)
{
if (body.size() % 8 != 0 || key.size() != 16)
{
return {};
}
std::vector<uint8_t> prev_block(8, 0);
std::vector<uint8_t> prev_original_block(8, 0);
std::vector<uint8_t> result(body.size());
int resultIndex = static_cast<int>(body.size()) - 1;
int remain_j = 0;
for (size_t i = body.size(); i > 0; i -= 8)
{
size_t current_index = i - 8;
std::vector<uint8_t> block(8);
if (i == body.size())
{
block = prev_block;
}
else
{
for (int k = 0; k < 8; k++)
{
block[k] = body[current_index + k] ^ prev_block[k];
}
}
std::vector<uint8_t> encrypt_block = encryptBlock(block, key);
int j = remain_j;
if (i == 8) // 处理最后一个块
{
int header_offset = block[0] & 0x07;
j = header_offset + 3;
}
for (int k = 7; k >= 0; k--)
{
if (k >= j)
{
result[resultIndex--] = encrypt_block[k] ^ prev_block[k];
}
}
if (j > 8)
{
remain_j = j % 8;
}
else
{
remain_j = 0;
}
prev_block = encrypt_block;
prev_original_block = std::vector<uint8_t>(body.begin() + current_index, body.begin() + current_index + 8);
}
return result;
}
void OnBnClickedEncript()
{
std::vector<uint8_t> originalData = 密钥加密;
std::string privateKey = "woreaishenghuo!!";
std::vector<uint8_t> key(privateKey.begin(), privateKey.end());
std::vector<uint8_t> encryptedData = decrypt(originalData, key);
//此处经过手动检验 解密数据正确
std::vector<uint8_t> decryptedData = encrypt(encryptedData, key);
if (decryptedData != 密钥加密)
{
AfxMessageBox(_T("数据不匹配!"));
std::cout << originalData.size() << "|" << 密钥加密.size() << "|" << decryptedData.size() << std::endl;
std::cout << "密钥加密数据: ";
for (const auto& byte : 密钥加密) {
std::cout << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(byte) << " ";
}
std::cout << std::endl;
std::cout << "验证加密数据: ";
for (const auto& byte : decryptedData) {
std::cout << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(byte) << " ";
}
std::cout << std::endl;
}
}
解决方案
如下是上述问题的解决方案,仅供参考:
在你的描述中,问题出现在加密和解密函数之间不完全匹配,导致最终的结果与原始密钥加密数据不一致。你提到 encryptBlock
和 decryptBlock
是可逆的,也就是在加密和解密中,它们应该正确配对工作。但是,根据你的实现,可能存在以下几方面的问题:
问题点和原因分析
-
加密和解密过程中,初始向量的使用不同:
- 在
encrypt
函数中,似乎使用了不同的初始化逻辑,尤其是对第一个块的处理。你在解密函数的第一个块处理时使用prev_block
进行了异或操作,而在加密过程中,第一个块的处理没有对应的逻辑一致性。
- 在
-
解密和加密的头部偏移逻辑不一致:
- 在
decrypt
函数中,使用了一个header_offset
来确定从哪个字节开始处理。然而在encrypt
函数中,虽然有类似的处理,但实际的加密流程中可能没有正确实现对应的偏移。尤其是encrypt
函数中的j
计算可能导致数据的不一致。
- 在
-
剩余字节 (
remain_j
) 的处理问题:- 在
encrypt
和decrypt
函数中,remain_j
计算和处理可能存在不匹配的逻辑。在加密过程中,未完全处理的数据块可能导致解密后的数据与原始数据不一致。
- 在
-
异或操作的顺序和逻辑:
- 异或操作在加密和解密过程中可能没有严格遵守逆运算的顺序。例如,在加密过程中,首先异或后再进行加密,而在解密过程中,先解密再异或,顺序上可能会有误差。
修改建议:
要确保加密和解密是完全逆向的,可以做以下几个调整:
-
初始化块处理:
在encrypt
和decrypt
函数中保持初始化向量处理逻辑一致。每次加密和解密的第一块应当严格按照相同的逻辑进行初始化,确保加密和解密的第一步是可逆的。 -
偏移处理一致性:
确保偏移(header_offset
)的计算和使用在加密和解密中一致。encrypt
和decrypt
对j
处理时,应该确保两者的逻辑相同。 -
remain_j 的处理修正:
处理剩余字节时,要确保加密和解密中的remain_j
逻辑是对称的。
可能的修正代码片段
解密函数修正
std::vector<uint8_t> CMFCPKGDlg::decrypt(const std::vector<uint8_t>& body, const std::vector<uint8_t>& key)
{
if (body.size() % 8 != 0 || key.size() != 16)
{
return {};
}
std::vector<uint8_t> prev_block(8, 0);
std::vector<uint8_t> prev_original_block(8, 0);
std::vector<uint8_t> result(body.size());
size_t resultIndex = 0;
for (size_t i = 0; i < body.size(); i += 8)
{
std::vector<uint8_t> decrypt_block(8);
for (int k = 0; k < 8; ++k)
{
decrypt_block[k] = prev_block[k] ^ body[i + k];
}
std::vector<uint8_t> block = decryptBlock(decrypt_block, key);
int j = 0;
if (i == 0)
{
int header_offset = block[0] & 0x07;
j = header_offset + 3;
}
for (; j < 8; ++j)
{
result[resultIndex++] = block[j] ^ prev_original_block[j];
}
prev_block = decrypt_block;
prev_original_block.assign(body.begin() + i, body.begin() + i + 8);
}
return result;
}
加密函数修正
std::vector<uint8_t> CMFCPKGDlg::encrypt(const std::vector<uint8_t>& body, const std::vector<uint8_t>& key)
{
if (body.size() % 8 != 0 || key.size() != 16)
{
return {};
}
std::vector<uint8_t> prev_block(8, 0);
std::vector<uint8_t> result(body.size());
size_t resultIndex = 0;
for (size_t i = 0; i < body.size(); i += 8)
{
std::vector<uint8_t> block(8);
for (int k = 0; k < 8; ++k)
{
block[k] = body[i + k] ^ prev_block[k];
}
std::vector<uint8_t> encrypt_block = encryptBlock(block, key);
for (int j = 0; j < 8; ++j)
{
result[resultIndex++] = encrypt_block[j] ^ prev_block[j];
}
prev_block = block;
}
return result;
}
结论:
通过调整加密和解密逻辑,确保初始化块的处理、偏移计算、以及异或操作的顺序一致性,应该能够确保 encrypt
和 decrypt
函数是完全逆向的。
希望如上措施及解决方案能够帮到有需要的你。
PS:如若遇到采纳如下方案还是未解决的同学,希望不要抱怨&&急躁,毕竟影响因素众多,我写出来也是希望能够尽最大努力帮助到同类似问题的小伙伴,即把你未解决或者产生新Bug黏贴在评论区,我们大家一起来努力,一起帮你看看,可以不咯。
若有对当前Bug有与如下提供的方法不一致,有个不情之请,希望你能把你的新思路或新方法分享到评论区,一起学习,目的就是帮助更多所需要的同学,正所谓「赠人玫瑰,手留余香」。
☀️写在最后
如上问题有的来自我自身项目开发,有的收集网站,有的来自读者…如有侵权,立马删除。再者,针对此专栏中部分问题及其问题的解答思路或步骤等,存在少部分搜集于全网社区及人工智能问答等渠道,若最后实在是没能帮助到你,还望见谅!并非所有的解答都能解决每个人的问题,在此希望屏幕前的你能够给予宝贵的理解,而不是立刻指责或者抱怨!如果你有更优解,那建议你出教程写方案,一同学习!共同进步。
ok,以上就是我这期的Bug修复内容啦,如果还想查找更多解决方案,你可以看看我专门收集Bug及提供解决方案的专栏《CSDN问答解惑-专业版》,都是实战中碰到的Bug,希望对你有所帮助。到此,咱们下期拜拜。
码字不易,如果这篇文章对你有所帮助,帮忙给 bug菌 来个一键三连(关注、点赞、收藏) ,您的支持就是我坚持写作分享知识点传播技术的最大动力。
同时也推荐大家关注我的硬核公众号:「猿圈奇妙屋」 ;以第一手学习bug菌的首发干货,不仅能学习更多技术硬货,还可白嫖最新BAT大厂面试真题、4000G Pdf技术书籍、万份简历/PPT模板、技术文章Markdown文档等海量资料,你想要的我都有!
📣关于我
我是bug菌,CSDN | 掘金 | InfoQ | 51CTO | 华为云 | 阿里云 | 腾讯云 等社区博客专家,C站博客之星Top30,华为云2023年度十佳博主,掘金多年度人气作者Top40,掘金等各大社区平台签约作者,51CTO年度博主Top12,掘金/InfoQ/51CTO等社区优质创作者;全网粉丝合计 30w+;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试真题、4000G PDF电子书籍、简历模板等海量资料,你想要的我都有,关键是你不来拿哇。