《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();
}

源码下载

相关推荐
亲爱的非洲野猪4 分钟前
Java锁机制八股文
java·开发语言
LawrenceLan10 分钟前
Flutter 零基础入门(十二):枚举(enum)与状态管理的第一步
开发语言·前端·flutter·dart
charlie1145141911 小时前
从 0 开始的机器学习——NumPy 线性代数部分
开发语言·人工智能·学习·线性代数·算法·机器学习·numpy
王老师青少年编程1 小时前
2025年12月GESP真题及题解(C++七级): 城市规划
c++·gesp·csp·信奥赛·七级·csp-s·提高组
catchadmin2 小时前
Laravel12 + Vue3 的免费可商用商业级管理后台 CatchAdmin V5 正式发布
开发语言·php
袁气满满~_~2 小时前
Python数据分析学习
开发语言·笔记·python·学习
寻星探路3 小时前
【算法专题】滑动窗口:从“无重复字符”到“字母异位词”的深度剖析
java·开发语言·c++·人工智能·python·算法·ai
程序员小白条3 小时前
面试 Java 基础八股文十问十答第八期
java·开发语言·数据库·spring·面试·职场和发展·毕设
Dxy12393102163 小时前
python连接minio报错:‘SSL routines‘, ‘ssl3_get_record‘, ‘wrong version number‘
开发语言·python·ssl
大王小生3 小时前
C# CancellationToken
开发语言·c#·token·cancellation