C++ MFC 标准库 加密解密解惑

🏆本文收录于《全栈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;
        }
}

解决方案

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

在你的描述中,问题出现在加密和解密函数之间不完全匹配,导致最终的结果与原始密钥加密数据不一致。你提到 encryptBlockdecryptBlock 是可逆的,也就是在加密和解密中,它们应该正确配对工作。但是,根据你的实现,可能存在以下几方面的问题:

问题点和原因分析

  1. 加密和解密过程中,初始向量的使用不同

    • encrypt 函数中,似乎使用了不同的初始化逻辑,尤其是对第一个块的处理。你在解密函数的第一个块处理时使用 prev_block 进行了异或操作,而在加密过程中,第一个块的处理没有对应的逻辑一致性。
  2. 解密和加密的头部偏移逻辑不一致

    • decrypt 函数中,使用了一个 header_offset 来确定从哪个字节开始处理。然而在 encrypt 函数中,虽然有类似的处理,但实际的加密流程中可能没有正确实现对应的偏移。尤其是 encrypt 函数中的 j 计算可能导致数据的不一致。
  3. 剩余字节 (remain_j) 的处理问题

    • encryptdecrypt 函数中,remain_j 计算和处理可能存在不匹配的逻辑。在加密过程中,未完全处理的数据块可能导致解密后的数据与原始数据不一致。
  4. 异或操作的顺序和逻辑

    • 异或操作在加密和解密过程中可能没有严格遵守逆运算的顺序。例如,在加密过程中,首先异或后再进行加密,而在解密过程中,先解密再异或,顺序上可能会有误差。

修改建议:

要确保加密和解密是完全逆向的,可以做以下几个调整:

  1. 初始化块处理
    encryptdecrypt 函数中保持初始化向量处理逻辑一致。每次加密和解密的第一块应当严格按照相同的逻辑进行初始化,确保加密和解密的第一步是可逆的。

  2. 偏移处理一致性
    确保偏移(header_offset)的计算和使用在加密和解密中一致。encryptdecryptj 处理时,应该确保两者的逻辑相同。

  3. 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;
}

结论:

通过调整加密和解密逻辑,确保初始化块的处理、偏移计算、以及异或操作的顺序一致性,应该能够确保 encryptdecrypt 函数是完全逆向的。

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

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


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/894507.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

第五届光学与图像处理国际学术会议(ICOIP 2025)征稿中版面有限!

第五届光学与图像处理国际学术会议&#xff08;ICOIP 2025&#xff09; 2025 5th International Conference on Optics and Image Processing (ICOIP 2025&#xff09; 重要信息 时间地点&#xff1a;2025年4月25-27日丨中国西安 截稿日期&#xff1a;2024年12月16日23:59 …

Java项目-基于Springboot的应急救援物资管理系统项目(源码+说明).zip

作者&#xff1a;计算机学长阿伟 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、ElementUI等&#xff0c;“文末源码”。 开发运行环境 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBoot、Vue、Mybaits Plus、ELementUI工具&#xff1a;IDEA/…

【数据结构与算法】力扣 54. 螺旋矩阵

问题描述 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例 1&#xff1a; 输入&#xff1a; matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a; [1,2,3,6,9,8,7,4,5]示例 2&#xff1a; 输入&#xff1a; ma…

【C++】deque(空间适配器))

适配器 适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结)&#xff0c;该种模式是将一个类的接口转换成客户希望的另外一个接口。 STL标准库中stack和queue的底层结构 deque原理介绍 deque(双端队列)&#xff1a;是一种…

Visual Studio2022 无法打开源文件

今天在新电脑上安装了Visual Studio2022&#xff0c;但是无法打开多个源文件&#xff0c;网上搜索都是说重新安装Windows SDK 我最开始安装的sdk版本是win11SDK 修改成其他版本后也没有解决问题 最后安装了Windows 10 SDK 10.0.20348.0 这个版本&#xff0c;成功解决问题。 有…

快速了解kubernetes中的存储管理

目录 一 configmap 1.1 configmap的功能 1.2 configmap的使用场景 1.3 configmap创建方式 1.3.1 字面值创建 1.3.2 通过文件创建 1.3.3 通过目录创建 1.3.4 通过yaml文件创建 1.3.5 configmap的使用方式 1.3.5.1 使用configmap填充环境变量 1.3.5.2 通过数据卷使用c…

大数据-173 Elasticsearch 索引操作 增删改查 详细 JSON 操作

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

【ESP32-IDFV5.3.1开发】带SSL的MQTT-demo连接教程

目录 1.VSCODE以及IDF环境配置(略) 2.准备demo 2.1打开VSCODE,主菜单创建示例 找到SSL对应demo,点击创建,并成功创建项目,点击编译,显示编译成功即可以下一步。 确认该demo支持的开发板是你手上的开发板 3.修改demo配置项 3.1插上开发板,点击底部开发工具,分别配置好烧…

Maya---骨骼绑定

调节骨骼大小 回车键确认骨骼 FK子集跟父集走 IK子集不跟父集走 前视图中按shift键添加骨骼 清零、删除历史记录&#xff0c;创建新的物体

Go 设置并发控制数量 【go并发模型】

背景&#xff1a;go的并发控制也是老生常谈&#xff0c;在公司业务中也是经常出现 谈谈我们这次并发模型的适用场景&#xff1a;要处理的任务很多比如有10000个&#xff0c;没开并发的时候我们要一个一个进行执行这个时候其实无论是cpu压力还是数据库和redis压力都比较小也就是…

CTFHUB技能树之HTTP协议——响应包源代码

开启靶场&#xff0c;打开链接&#xff1a; 是个贪吃蛇小游戏&#xff0c;看不出来有什么特别的地方 用burp抓包看看情况&#xff1a; 嗯&#xff1f;点击“开始”没有抓取到报文&#xff0c;先看看网页源代码是什么情况 居然直接给出flag了&#xff0c;不知道这题的意义何在 …

C++初阶(五)--类和对象(中)--默认成员函数

目录 一、默认成员函数&#xff08;Default Member Functions&#xff09; 二、构造函数&#xff08; Constructor&#xff09; 1.构造函数的基本概念 2.构造函数的特征 3.构造函数的使用 无参构造函数 和 带参构造函数 注意事项&#xff1a; 4.默认构造函数 隐式生成的…

023_Layout_and_Containers_in_Matlab界面布局与容器

容器 基于uifigure进行的图形用户界面设计&#xff0c;可以分为以下几种容器类型&#xff1a; 图窗&#xff1a;uifigure布局&#xff1a;uigridlayout面板&#xff1a;uipanel标签页&#xff1a;uitabgroup、uitab 这几个对象除uifigure外相互可以形成嵌套的关系&#xff0…

理解TypeScript模块-声明-配置

目录 模块化内置类型导入命名空间类型查找内置类型外部定义声明第三方库自定义声明 tsconfig.json文件在Vue项目中应用在React项目中应用 模块化 在TypeScript中最主要使用的模块化方案就是ES Module&#xff0c;先理解 TypeScript 认为什么是一个模块&#xff1a; JavaScript…

【视频生成大模型】 视频生成大模型 THUDM/CogVideoX-2b

【视频生成大模型】 视频生成大模型 THUDM/CogVideoX-2b CogVideoX-2b 模型介绍发布时间模型测试生成的demo视频生成视频限制 运行环境安装运行模型下载开源协议参考 CogVideoX-2b 模型介绍 CogVideoX是 清影 同源的开源版本视频生成模型。 基础信息&#xff1a; 发布时间 2…

VScode远程服务器进行开发(三)

VScode远程服务器进行开发&#xff08;三&#xff09; 1、配置你的~/.ssh/config文件 在家目录中配置 ~/.ssh/config 文件&#xff0c;没有配置过的同学可以自行百度&#xff0c;基本上就是远程服务器的罗列&#xff1b; 同时&#xff0c;在你安装了 Remote Development 后&…

群晖使用Docker搭建NASTool自动化观影工具并实现在线远程管理

文章目录 前言1. 本地搭建Nastool2. nastool基础设置3. 群晖NAS安装内网穿透工具4. 配置公网地址5. 配置固定公网地址 前言 本文主要分享一下如何在群晖NAS中本地部署Nastool&#xff0c;并结合cpolar内网穿透工具&#xff0c;轻松实现公网环境远程管理与访问本地NAS中储存的影…

“网络协议入门:HTTP通信的四大组成部分“

White graces&#xff1a;个人主页 &#x1f649;专栏推荐:Java入门知识&#x1f649; &#x1f439;今日诗词: 春水满四泽&#xff0c;夏云多奇峰&#x1f439; ⛳️点赞 ☀️收藏⭐️关注&#x1f4ac;卑微小博主&#x1f64f; ⛳️点赞 ☀️收藏⭐️关注&#x1f4ac;卑微…

大话设计模式解读07-模板方法

上篇文章&#xff0c;介绍了《大话设计模式》的第9章——原型模式。 本篇&#xff0c;来介绍《大话设计模式》的第10章——模板方法。并通过C代码实现实例代码的功能。 1 模板方法 模板方法模式&#xff08;TemplateMethod&#xff09;&#xff1a;定义一个操作中的算法的骨架…

【简单版】通过 Window.performance 实现前端页面(性能)监控

1 背景 前端监控系统告警xx接口fetchError 问题&#xff1a;前端监控系统没有更多的错误信息&#xff0c;查询该fetch请求对应的接口日志返回200状态码、无请求异常记录&#xff0c;且后台能查到通过该fetch请求成功发送的数据。那是前端页面的错误还是前端监控系统的问题&…