《QT从基础到进阶·七十二》基于Qt开发的文件保险柜工具并支持文件各种加密和解密

1、概述
源码放在文章末尾

该项目实现了文件各种加密和解密的功能,能够有效的保障文件的安全,主要包含如下功能:
1、支持所有 AES 密钥长度;
AES_128
AES_192
AES_256
2、支持ECB、CBC、CFB、OFB四种模式;
3、支持ZERO、PKCS7、ISO三种填充方式;
4、支持md5文件损毁检测
5、支持输入任意长度密钥进行加解密;
6、将.bmp格式图片加密后可正常打开图片,不破坏图片格式。

项目截图效果如下所示:
(1)文件加密
在这里插入图片描述
(2)文件解密
在这里插入图片描述

(3)bmp图片加密
在这里插入图片描述

项目部分代码如下所示:

#ifndef FILEENCRYPTION_H
#define FILEENCRYPTION_H

#include <QObject>
#include "qaesencryption.h"

class FileEncryption : public QObject
{
    Q_OBJECT
public:
    explicit FileEncryption(QObject *parent = nullptr);
    void setFile(const QString& strIn, const QString& strOut);
    void setKey(const QByteArray& key);
    void setEncryption(bool flag);
    void setAESParameter(QAESEncryption::Aes aes, QAESEncryption::Mode mode, QAESEncryption::Padding padding);
    void stop();                        // 停止

signals:
    void start();                       // 开始
    void showLog(QString log);          // 日志

private:
    void startEncryption();
    void encryption();
    void decrypt();
    bool readFile(const QString& fileName);
    void dataOperation();
    void check();
    bool writeFile(const QString& fileName);
    void clear();

private:
    QString m_strIn;          // 输入文件路径
    QString m_strOut;         // 输出文件路径
    QString m_fileSuffix;     // 文件后缀
    QByteArray m_key;         // 密钥
    QByteArray m_iv;          // 偏移
    bool m_encryption = true;
    QAESEncryption::Aes m_aes;
    QAESEncryption::Mode m_mode;
    QAESEncryption::Padding m_padding;

    QByteArray m_dataIn;     // 输入内容
    QByteArray m_dataOut;    // 输出内容
    QByteArray m_md5;        // MD5值

    QByteArray m_head;       // bmp图片的文件信息
};

#endif // FILEENCRYPTION_H
#include "fileencryption.h"

#include <QDir>
#include <QFileInfo>
#include <QImage>
#include <qcryptographichash.h>
#include <qdebug.h>
#include <qfile.h>
#include <qthread.h>

FileEncryption::FileEncryption(QObject *parent) : QObject(parent)
{
    connect(this, &FileEncryption::start, this, &FileEncryption::startEncryption);
    for(int i = 0; i < 16; i++)
    {
        m_iv.append((uchar)i);
    }
}

/**
 * @brief         设置输入输出文件路径
 * @param strIn   输入文件路径
 * @param strOut  输出文件路径
 */
void FileEncryption::setFile(const QString& strIn, const QString& strOut)
{
    if(!strIn.isEmpty() && !strOut.isEmpty())
    {
        this->m_strIn = strIn;
        this->m_strOut = strOut;

        QFileInfo info(strIn);
        m_fileSuffix = info.suffix();
    }
}

/**
 * @brief      设置使用的密钥
 * @param key
 */
void FileEncryption::setKey(const QByteArray &key)
{
    this->m_key = key;
}

/**
 * @brief        设置加密或者解密
 * @param flag   true:加密 false:解密
 */
void FileEncryption::setEncryption(bool flag)
{
    this->m_encryption = flag;
}

/**
 * @brief           设置AES加解密参数
 * @param aes
 * @param mode
 * @param padding
 */
void FileEncryption::setAESParameter(QAESEncryption::Aes aes, QAESEncryption::Mode mode, QAESEncryption::Padding padding)
{
    this->m_aes = aes;
    this->m_mode = mode;
    this->m_padding = padding;
}

/**
 * @brief 加解密操作
 */
void FileEncryption::startEncryption()
{
    clear();
    emit showLog("开始输入原文件!");
    if(readFile(m_strIn))
    {
        emit showLog("文件读取完成!");
        if(m_encryption)
        {
            encryption();
        }
        else
        {
            decrypt();
        }
        if(writeFile(m_strOut))
        {
            emit showLog("数据写入成功!");
        }
        clear();
    }
    else
    {
        emit showLog("输入文件读取失败!");
    }
}

/**
 * @brief 加密
 */
void FileEncryption::encryption()
{
    QAESEncryption encryption(m_aes, m_mode, m_padding);
    emit showLog("开始加密!");

    if(m_mode == QAESEncryption::ECB)
    {
        m_dataOut.append(encryption.encode(m_dataIn, m_key));
    }
    else
    {
         m_dataOut.append(encryption.encode(m_dataIn, m_key, m_iv));
    }
    m_dataOut.insert(0, m_head);

    m_dataOut.append(m_md5);
    emit showLog("加密完成,开始写入!");

}

/**
 * @brief  解密
 */
void FileEncryption::decrypt()
{
    QAESEncryption encryption(m_aes, m_mode, m_padding);
    emit showLog("开始解密!");

    if(m_mode == QAESEncryption::ECB)
    {
        m_dataOut.append(encryption.decode(m_dataIn, m_key));
    }
    else
    {
         m_dataOut.append(encryption.decode(m_dataIn, m_key, m_iv));
    }
    m_dataOut = encryption.removePadding(m_dataOut);        // 移除填充数据
    m_dataOut.insert(0, m_head);

    emit showLog("解密完成,开始写入!");
    check();
}

/**
 * @brief           读取文件内容
 * @param fileName
 */
bool FileEncryption::readFile(const QString &fileName)
{
    QFile file(fileName);
    if(file.open(QIODevice::ReadOnly))
    {
        m_dataIn = file.readAll();
        file.close();
        dataOperation();
        return true;
    }
    else
    {
        emit showLog(QString("%1打开失败!").arg(fileName));
        return false;
    }
}

/**
 * @brief 操作数据内容
 */
void FileEncryption::dataOperation()
{
    // 获取md5值
    if(m_encryption)
    {
        m_md5 = QCryptographicHash::hash(m_dataIn, QCryptographicHash::Md5).toHex();
    }
    else                  // 解密时读取md5值
    {
        m_md5 = m_dataIn.mid(m_dataIn.count() - 32, 32);
        m_dataIn.remove(m_dataIn.count() - 32, 32);
    }

    // 读取bmo文件头信息
    if(m_fileSuffix.compare("bmp", Qt::CaseInsensitive) == 0)
    {
        m_head = m_dataIn.mid(0, 54);        // bmp文件头:共14字节;位图信息头:共40字节;
        m_dataIn.remove(0, 54);
    }
}

/**
 * @brief  使用md5校验文件是否损毁
 */
void FileEncryption::check()
{
    QByteArray arr = QCryptographicHash::hash(m_dataOut, QCryptographicHash::Md5).toHex();
    if(arr == m_md5)
    {
        emit showLog("文件未损毁!");
    }
    else
    {
        emit showLog("文件存在不同,可能已损毁!");
    }
}


/**
 * @brief           写文件内容
 * @param fileName
 * @param data
 */
bool FileEncryption::writeFile(const QString &fileName)
{
    QFileInfo info(fileName);
    QString filePath = info.absolutePath();
    QDir dir;
    if(!dir.exists(filePath))
    {
        dir.mkpath(filePath);
    }

    QFile file(fileName);
    if(file.open(QIODevice::WriteOnly))
    {
        file.write(m_dataOut);
        file.close();
        return true;
    }
    else
    {
        emit showLog(QString("%1打开失败!").arg(fileName));
        return false;
    }
}

/**
 * @brief 清空数据
 */
void FileEncryption::clear()
{
    m_dataIn.clear();
    m_dataOut.clear();
    m_head.clear();
    m_md5.clear();
}

源码下载

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

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

相关文章

JasperReport-Variable变量使用和求总计等计算

背景 在制作报表时&#xff0c;会经常看到Variables变量&#xff0c;里边有几个默认值&#xff0c;默认值不支持修改。其中用得最多的就是PAGE_NUMBER和PAGE_COUNT。下边接着介绍一下自定义变量的一些用法。 内置变量 Variable Name 变量名 Description 描述 PAGE_NUMBER Co…

爆赞!GitHub首本Python开发实战背记手册,标星果然百万名不虚传

Python (发音:[ paiθ(ə) n; (US) paiθɔn ] n. 蟒蛇&#xff0c;巨蛇 )&#xff0c;是一种面向对象的解释性的计算机程序设计语言&#xff0c;也是一种功能强大而完善的通用型语言&#xff0c;已经具有十多年的发展历史&#xff0c;成熟且稳定。Python 具有脚本语言中最丰富…

Java 诊断神器 Arthas使用笔记

Arthas 是一款开源在线 Java 诊断工具&#xff0c;采用命令行交互模式&#xff0c;支持 web 端在线诊断&#xff0c;同时提供丰富的 Tab 自动补全功能&#xff0c;进一步方便进行问题的定位和诊断。得益于 Arthas 强大且丰富的功能。 1.JDK原生定位工具 平时开发中会用到JDK中…

韩顺平0基础学java——第23

p460-483 常用类 包装类Wrapper 针对8种几种数据类型相应的引用类型——包装类 包装类和基本数据类型的转换 jdk5之前的手动装箱和拆箱&#xff1a; jdk5之后的自动装箱和拆箱&#xff1a; 三元运算符是一个整体&#xff1a; 这个三元运算符里&#xff0c;精度最高的是doubl…

【区块链】以太坊白皮书深度解读:构建智能合约的分布式平台

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 以太坊白皮书深度解读&#xff1a;构建智能合约的分布式平台引言1. 以太坊的诞生…

机能学实验通过ZL-620C一体化信息化生物信号采集系统具体呈现

ZL-621大屏教学试教系统为了实施机能学实验的教学改革&#xff0c;大力减轻教师的实验教学负担&#xff0c;主要功能电子白板&#xff0c;同步教学、控制、过程仿真、虚拟现实、三维动画、管理、音视频广播、PPT教材等于一体&#xff0c;大屏教学试教系统并能同时实现屏幕监视和…

权利利益方格

权利利益方格 一、定义二、分类与策略权力高、利益高&#xff08;双高&#xff09;权力高、利益低权力低、利益高权力低、利益低&#xff08;双低&#xff09; 三、应用四、总结 在项目管理中&#xff0c;权力利益方格是一种重要的工具&#xff0c;用于评估项目相关方的权力和利…

树莓派4B_OpenCv学习笔记9:图片的腐蚀与膨胀

今日继续学习树莓派4B 4G&#xff1a;&#xff08;Raspberry Pi&#xff0c;简称RPi或RasPi&#xff09; 本人所用树莓派4B 装载的系统与版本如下: 版本可用命令 (lsb_release -a) 查询: Opencv 版本是4.5.1&#xff1a; 图像的膨胀与腐蚀一般用于灰度图或者二值图,今日便来学习…

头歌资源库(13)背包问题

一、 问题描述 二、算法思想 这是一个背包问题&#xff0c;可以使用动态规划算法来解决。具体思路如下&#xff1a; 定义一个二维数组dp&#xff0c;dp[i][j]表示前i个物品在背包容量为j时能获取的最大价值。初始化dp数组的第一行和第一列为0&#xff0c;表示当只有一个物品或…

这13个常用电路基础公式,每一位电子工程师都要牢记

计算电阻电路中电流、电压、电阻和功率之间的关系。 欧姆定律解释了电压、电流和电阻之间的关系&#xff0c;即通过导体两点间的电流与这两点间的电势差成正比。说明两点间的电压差、流经该两点的电流和该电流路径电阻之间关系的定律。该定律的数学表达式为V IR&#xff0c;其中…

Qt调用第三方库的通用方式(静态链接库.a或.lib、动态链接库.dll)

目录 一、前提 二、如何引用静态链接库 三、如何引用动态链接库 四、示例代码资源 在开发项目中经常会存在需要调用第三方库的时候&#xff0c;对于Qt如何来调用第三方库&#xff0c;为了方便自己特意记录下详细过程。 一、前提 1. window 10操作系统 2. 已安装了Qt6.7.…

申万宏源:消费税改或是财政改革第一枪

消费税征收环节后移可能带来年化千亿的税收收入增长&#xff0c;地方财政压力的缓和程度取决于中央确定保留的消费税基数。申万宏源认为&#xff0c;财政改革不仅仅只涉及消费税和央地分配&#xff0c;而稳定扩大需求才是下一步改革核心。 主要内容 财政现实呼唤改革。紧迫性…

改进位删除谜题的求解方法

问题背景 给定长度为 n 的二进制向量&#xff0c;如何删除恰好 n/3 个位&#xff0c;使剩余二进制向量的不同数量最小化。该问题被称为“位删除谜题”。 以下是该问题的示例&#xff1a; 对于 n 3 的情况&#xff0c;最优解是 2&#xff0c;对应两个不同的向量 11 和 00。对…

python pytest 参数化的几种方式

一、使用pytest.mark.parametrize装饰器&#xff1a; 可以使用pytest提供的pytest.mark.parametrize装饰器来指定参数化测试的参数。下面是一个示例&#xff1a; import pytest# pytest.mark.parametrize装饰器 # 其中num expected&#xff0c;分别对应(1, 1),(2, 4),(3, 9)&…

JLINK调试妙用----读写flash

JLINK调试妙用----读写flash 前言 随着对jlink使用频率的增加&#xff0c;越发觉得它太强大了&#xff0c;可以满足好多调试功能&#xff0c;现在已经用的就是J-flash&#xff08;程序下载&#xff09;、RTT&#xff08;日志打印&#xff09;和J-flash SPI&#xff08;读写spi类…

从零基础到学完CCIE要多久?

思科认证的CCIE是网络工程师追求的顶级认证之一。 对于刚入门的初学者来说&#xff0c;从零基础到通过CCIE认证&#xff0c;这条路需要多长时间&#xff1f; 这个问题的答案因人而异&#xff0c;取决于多种因素。 这不仅是一个关于时间的问题&#xff0c;更是一个关于规划、学习…

芯片验证 | FPGA 原型验证

更多完整内容访问&#xff1a;【芯片验证 | FPGA 原型验证】

Debian12安装Nvidia官方驱动

1、下载驱动&#xff08;下载到一个英文目录例如你的用户目录/home/用户名下&#xff0c;我下载到dowload目录&#xff0c;由于默认显示中文&#xff0c;在命令行不支持中文显示的是一串数字&#xff0c;当然你仍然可以cd 那串数字进目录&#xff0c;显示有有引号就加引号&…

聚四氟乙烯提取瓶2L固废浸提用PTFE大口瓶适配FZ-4翻转震荡器

聚四氟乙烯广口瓶的口径较大&#xff0c;我司采用“直上直下”的样式设计&#xff0c;方便样品的存放和拿取。瓶身内壁平滑&#xff0c;&#xff0c;易清洗。瓶口是螺纹口设计&#xff0c;保证很好的密封性。聚四氟乙烯广口瓶特性&#xff1a;1.耐高低温&#xff1a;-200至250℃…

业务谈判的过程中多让客户做选择

之前还在工厂的时候&#xff0c;开分享会&#xff0c;经理会反复强调的一个跟进思路就是一定要学会让客户跟着我们的节奏走&#xff0c;而不是被客户牵着鼻子走。 前者会让客户顺着我们设计好的谈判路径&#xff0c;把客户引导到我们想要的结果上&#xff0c;业务员是主动角色…