当前位置: 首页 > news >正文

C++加密解密问题解惑答疑

🏆本文收录于《全栈Bug调优(实战版)》专栏,主要记录项目实战过程中所遇到的Bug或因后果及提供真实有效的解决方案,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!

问题描述

给了一个加密文件 自行去构建加密解密
然后就是 写的解密函数是正确的 可以解出来,但是 加密回去,再次解密的时候就是乱码了
解密函数应该是没错的,不需要修改 那么加密函数错在哪了呢?
并且 加密回去再次解密的时候,前8个字节是正确的
就是从这以后是乱码

输出信息如下:

/*
解密过程 header_offset:7
--快捷纀?韐f?S?G?C揋播彚筈M6蜧T[??P:}?V?杙l粕|b~孂py阨?}耴?乫?餵∽A疤?墍.衒?敯犕棱呀杬@[橢?觼c??ue収嵮)d?xD?S[oC琱?`dURA????{{35t緥?I?砫k*/

原加密的txt 是:
–快捷方式: 复制 粘贴 增添 删除
可以私下解决酬谢,只要我能承担

std::vector<uint8_t> decryptBlock(const std::vector<uint8_t>& buffer, const std::vector<uint8_t>& key)
{if (buffer.size() != 8 || key.size() < 16){return {};}uint32_t value1 = _byteswap_ulong(*reinterpret_cast<const uint32_t*>(buffer.data()));uint32_t value2 = _byteswap_ulong(*reinterpret_cast<const uint32_t*>(buffer.data() + 4));uint32_t matrix[4];for (int i = 0; i < 4; ++i){matrix[i] = _byteswap_ulong(*reinterpret_cast<const uint32_t*>(key.data() + i * 4));}uint32_t rnd = 0xE3779B90;for (int i = 16; i > 0; --i){value2 -= (rnd + value1) ^ (matrix[2] + 16 * value1) ^ (matrix[3] + (value1 >> 5));uint32_t tmp = (rnd + value2) ^ (matrix[0] + 16 * value2) ^ (matrix[1] + (value2 >> 5));rnd += 1640531527;value1 -= tmp;}std::vector<uint8_t> result(8);*reinterpret_cast<uint32_t*>(result.data()) = _byteswap_ulong(value1);*reinterpret_cast<uint32_t*>(result.data() + 4) = _byteswap_ulong(value2);return result;
}
std::vector<uint8_t> 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;std::cout << "解密过程 header_offset:" << header_offset << std::endl;}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);}int byteword = 0;while (resultIndex > 0 && result[resultIndex - 1] == 0x0){byteword++;/*    --resultIndex;result.resize(resultIndex);*/}/*if (byteword != 7){AfxMessageBox(_T("删除字节数不为7!"));}*/return result;
}
std::vector<uint8_t> encryptBlock(const std::vector<uint8_t>& buffer, const std::vector<uint8_t>& key)
{if (buffer.size() != 8 || key.size() < 16){return {};}uint32_t value1 = _byteswap_ulong(*reinterpret_cast<const uint32_t*>(buffer.data()));uint32_t value2 = _byteswap_ulong(*reinterpret_cast<const uint32_t*>(buffer.data() + 4));uint32_t matrix[4];for (int i = 0; i < 4; ++i){matrix[i] = _byteswap_ulong(*reinterpret_cast<const uint32_t*>(key.data() + i * 4));}uint32_t rnd = 0xE3779B90 + (16 * 1640531527);for (int i = 0; i < 16; ++i){rnd -= 1640531527;uint32_t tmp = (rnd + value2) ^ (matrix[0] + 16 * value2) ^ (matrix[1] + (value2 >> 5));value1 += tmp;value2 += (rnd + value1) ^ (matrix[2] + 16 * value1) ^ (matrix[3] + (value1 >> 5));}std::vector<uint8_t> result(8);*reinterpret_cast<uint32_t*>(result.data()) = _byteswap_ulong(value1);*reinterpret_cast<uint32_t*>(result.data() + 4) = _byteswap_ulong(value2);return result;
}
std::vector<uint8_t> encrypt(const std::vector<uint8_t>& body, const std::vector<uint8_t>& key)
{int m = 7; // 你可以根据需要动态生成if (key.size() != 16){return {};}// 计算 jint j = m + 3;std::vector<uint8_t> padded_plaintext(body.size() + j);for (int k = 0; k < j; k++){padded_plaintext[k] = 0xFF; // 填充 0x00 或其他任意值(填充的值不能小于7,不然后续有影响)}for (size_t k = 0; k < body.size(); k++){padded_plaintext[k + j] = body[k];}padded_plaintext[0] = (padded_plaintext[0] & 0xF8) | (m & 0x07);std::vector<uint8_t> prev_block(8, 0);std::vector<uint8_t> encrypted(padded_plaintext.size());std::vector<uint8_t> prev_original_block(8, 0);for (size_t i = 0; i < padded_plaintext.size(); i += 8){std::vector<uint8_t> block(8);for (int k = 0; k < 8; k++){block[k] = padded_plaintext[i + k] ^ prev_block[k];}std::vector<uint8_t> encrypted_block = encryptBlock(block, key);for (int k = 0; k < 8; k++){encrypted[i + k] = encrypted_block[k] ^ prev_original_block[k];}prev_block = encrypted_block;prev_original_block = std::vector<uint8_t>(padded_plaintext.begin() + i, padded_plaintext.begin() + i + 8);}return encrypted;}
void OnBnClickedEncript() {std::string privateKey = "woshizhongguoren";std::vector<uint8_t> key(privateKey.begin(), privateKey.end());std::string XXX;std::ifstream file(m_outputPath, std::ios::binary);if (file.is_open()){std::string content((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());file.close();XXX = content;}std::vector<uint8_t> 文档测试(XXX.begin(), XXX.end());std::vector<uint8_t> 文档加密;std::vector<uint8_t> 文档解密;文档加密 = encrypt(文档测试, key);文档解密 = decrypt(文档加密, key);std::cout << 文档解密.data() << std::endl;}

解决方案

  如下是上述问题的解决方案,仅供参考:

从你提供的信息来看,加密后的数据在解密时出现乱码,特别是前8个字节正确,后面出现问题。这种情况很可能是由于加密和解密过程中某些部分的逻辑不一致。常见的问题可能出现在以下几个方面:

问题排查方向:

  1. 填充处理问题
    你的 encrypt 函数中有一个填充操作(填充了 0xFF)。而在解密过程中,可能没有正确处理这些填充值。具体体现在:

    padded_plaintext[k] = 0xFF;
    

    填充时,确保填充规则的一致性,比如在解密时是否正确处理了填充位。如果填充不正确,解密后得到的内容可能会有额外的无意义字符或者乱码。

    建议:查看加密和解密两边对填充字节的处理逻辑是否一致,并确保解密时能够正确去掉填充位。

  2. 前向反馈链 (CBC) 模式的逻辑问题
    加密和解密的算法是基于一种类似于 CBC(Cipher Block Chaining)的模式,每一个加密块与前一个块相关。你在加密和解密过程中分别维护了两个前一个块的变量 prev_blockprev_original_block。在加密时,你使用了 prev_original_block 来异或,但在解密时,可能并没有正确处理这个前向反馈链。

    例如,在加密函数中:

    encrypted[i + k] = encrypted_block[k] ^ prev_original_block[k];
    

    而解密时的相同部分是否对应上是需要检查的重点。如果反馈链的逻辑不对,后面的块解密会出现错误。

    建议:仔细对比加密和解密过程中对 prev_blockprev_original_block 的处理,确保它们在两边的使用是对称的。错误的块反馈会导致后续的块解密出错。

  3. 块加密和解密逻辑一致性
    你的 encryptBlockdecryptBlock 函数实现了基于简单算法的加密解密。这部分代码中使用了常量 0xE3779B901640531527 来计算加密轮次。

    需要确认 encryptBlockdecryptBlock 中的轮次和加密算法的一致性。解密时使用的算法和加密时需要严格对称,如果有任何小的差异,解密的结果就会不正确。

  4. 块大小和数据对齐问题
    加密时,你的文本数据可能没有刚好是8字节的倍数,因此需要进行填充(如你使用的 0xFF 填充)。解密时确保正确去除这些填充字节,否则会导致解密后包含了多余的字节。

    decrypt 函数中,你的代码尝试去除结尾的 0 字节:

    while (resultIndex > 0 && result[resultIndex - 1] == 0x0) {byteword++;
    }
    

    建议:确认填充的字节值与解密时去除的字节匹配。如果加密时填充了 0xFF,但解密时去掉的是 0x00,这将导致解密失败。

针对性调整建议:

  1. 调整填充策略:确保加密和解密过程中使用的填充值一致,特别是你在 encrypt 中使用 0xFF 填充的部分。在解密时,你应该去掉这些特定的填充位。

  2. 检查 CBC 链接:确保 prev_blockprev_original_block 在加密和解密中对应正确,特别是在解密时如何使用和更新这些变量。也可以尝试在加密和解密每个块时打印 prev_blockprev_original_block 来确保它们在两边是对称的。

  3. 对比加密解密块逻辑:仔细检查 encryptBlockdecryptBlock 中的逻辑,特别是加密轮次是否一致,以及使用的常量是否完全相同。

调整示例:

std::vector<uint8_t> encrypt(const std::vector<uint8_t>& body, const std::vector<uint8_t>& key)
{int m = 7;if (key.size() != 16){return {};}int j = m + 3;std::vector<uint8_t> padded_plaintext(body.size() + j);// 填充 0xFFfor (int k = 0; k < j; k++){padded_plaintext[k] = 0xFF; }for (size_t k = 0; k < body.size(); k++){padded_plaintext[k + j] = body[k];}// 确保填充正确设置padded_plaintext[0] = (padded_plaintext[0] & 0xF8) | (m & 0x07);std::vector<uint8_t> prev_block(8, 0);std::vector<uint8_t> encrypted(padded_plaintext.size());std::vector<uint8_t> prev_original_block(8, 0);for (size_t i = 0; i < padded_plaintext.size(); i += 8){std::vector<uint8_t> block(8);for (int k = 0; k < 8; k++){block[k] = padded_plaintext[i + k] ^ prev_block[k];}std::vector<uint8_t> encrypted_block = encryptBlock(block, key);for (int k = 0; k < 8; k++){encrypted[i + k] = encrypted_block[k] ^ prev_original_block[k];}prev_block = encrypted_block;prev_original_block = std::vector<uint8_t>(padded_plaintext.begin() + i, padded_plaintext.begin() + i + 8);}return encrypted;
}

总结:

通过这些步骤,确保加密和解密中的逻辑和流程一致性,并特别留意填充、块反馈链以及加密解密算法中的轮次和常量的使用。

  希望如上措施及解决方案能够帮到有需要的你。

  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电子书籍、简历模板等海量资料,你想要的我都有,关键是你不来拿哇。



http://www.mrgr.cn/news/56014.html

相关文章:

  • 每日一道算法题(Leetcode 20)
  • C++基础与实用技巧第三课:内存管理与性能优化
  • mysql用户密码基础
  • 【MySQL数据库】MySQL高级语句(SQL语句进阶版)
  • 【exceljs】纯前端如何实现Excel导出下载和上传解析?
  • k8s 配置私有镜像仓库认证
  • 赢得3K下载!专为RAG打造的数据清洗利器
  • 【sshpass】sshpass安装使用
  • 企业文件怎么管控?这几个软件你一定要知道!
  • DBeaver + Oracle 数据库修改CLOB类型字段内容
  • 梦熊 CSP—S模拟赛 T2youyou不喜欢夏天
  • 蒙提霍尔问题
  • Claude Financial Data Analyst:基于Claude的金融数据分析工具!免费开源!
  • Java项目-基于springboot框架的校园医疗保险管理系统项目实战(附源码+文档)
  • element-时间选择器单独写两个时间选择器并按照规则进行置灰选择,精确到时分秒
  • 阿里云的 ALB (Application Load Balancer) 然后到 nginx 和具体服务时,如果超过 60 秒请求失败
  • 电子仪表计量检测产生误差的原因有哪些?数据误差原因分析
  • 【小白学机器学习19】统计基础:什么是定量分析,量化的4个层级,因果关系分类等
  • set笔记
  • HTTP错误代码解决详解
  • 雅迪控股营收、净利润和毛利下滑:销量大幅减少,屡屡抽查不合格
  • 如何成功报考PMP:5个必备步骤
  • 小型内衣裤洗衣机哪个牌子好?揭晓五款巅峰热门机型,精心挑选
  • 双十一有哪些值得买的东西?2024年最全双十一好物推荐榜单来了!
  • 宠物用品电商网站:SpringBoot框架设计与开发
  • 基于SpringBoot+Vue的网上超市系统的设计与实现(带文档)