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