《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图片加密

项目部分代码如下所示:

cpp 复制代码
#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
cpp 复制代码
#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();
}

源码下载

相关推荐
Theodore_1022几秒前
4 设计模式原则之接口隔离原则
java·开发语言·设计模式·java-ee·接口隔离原则·javaee
‘’林花谢了春红‘’2 小时前
C++ list (链表)容器
c++·链表·list
----云烟----2 小时前
QT中QString类的各种使用
开发语言·qt
lsx2024062 小时前
SQL SELECT 语句:基础与进阶应用
开发语言
开心工作室_kaic2 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
向宇it2 小时前
【unity小技巧】unity 什么是反射?反射的作用?反射的使用场景?反射的缺点?常用的反射操作?反射常见示例
开发语言·游戏·unity·c#·游戏引擎
武子康3 小时前
Java-06 深入浅出 MyBatis - 一对一模型 SqlMapConfig 与 Mapper 详细讲解测试
java·开发语言·数据仓库·sql·mybatis·springboot·springcloud
转世成为计算机大神3 小时前
易考八股文之Java中的设计模式?
java·开发语言·设计模式
机器视觉知识推荐、就业指导3 小时前
C++设计模式:建造者模式(Builder) 房屋建造案例
c++
宅小海3 小时前
scala String
大数据·开发语言·scala