提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
QT 5.14.1 文件加密
前言
按照一定的加密算法对需要加密的文件进行加密,需要设置密钥、加密向量、匹配码等内容。
–
一、工程目录
二、内容
1.mainwindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QDebug"
QString SourceFilePath="";//目标文件路径
QString TargetFilePath="";//存储输出文件路径
QString TarFile = ""; //存储输出文件夹路径
QByteArray byteArray(16,0); //十六个字节大小,初始值为0,存储首地址数据
unsigned char IV_IN[16]={0}; //向量
unsigned char key[32]={0}; //密钥
uchar lastindex=0;
QString filename="";//文件名
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
setLineEdit();
QDir dir(".");
// 设置数据库路径
QString dbPath = QString("%1/Data.db").arg(dir.absolutePath()); // 使用资源路径
// 添加数据库连接
db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(dbPath);
//[2] 打开数据库
if(!db.open())
{
qDebug()<<"open error"<<db.lastError().driverText();
}
else
{
createTable(); //创建参数表 只用创建一次
}
ui->tabWidget->setCurrentIndex(0);
for(uchar i=0;i<5;i++)//读取数据库数据
readData(i);
}
MainWindow::~MainWindow()
{
delete ui;
}
// 重写窗口大小函数,使tabwidget的tab宽度与总宽度保持一致
void MainWindow::resizeEvent(QResizeEvent *event)
{
// Q_UNUSED(event);
// //设置tabWidget 的Tab自动拉宽
// QRect rect = ui->tabWidget->geometry();
// ui->tabWidget->setStyleSheet(QString("QTabBar::tab{width:%1}QTabBar::tab{height:30}").arg(rect.width()/5));
}
//列表按照工程名称排序
QList<QLineEdit *> MainWindow::listSort(QList<QLineEdit *> lineEdit)
{
QCollator c;
c.setNumericMode(true);
std::sort(lineEdit.begin(), lineEdit.end(), [&c](QLineEdit* lhs, QLineEdit* rhs)
{
if(c.compare(lhs->objectName(), rhs->objectName()) < 0)
return true;
return false;
});
return lineEdit;
}
QStringList MainWindow::getUSBPaths()// 获取U盘路径
{
QFileInfoList drvList = QDir::drives();
QStringList validUSBPathList;
validUSBPathList.clear();
foreach (QFileInfo info, drvList)
{
#ifdef UNICODE
if ( DRIVE_REMOVABLE == GetDriveTypeW((WCHAR *)info.filePath().utf16()) )
#else
if ( DRIVE_REMOVABLE == GetDriveTypeA(info.filePath().toStdString().c_str()) )
#endif
{
validUSBPathList.append(info.absolutePath());
}
}
return validUSBPathList ;
}
void MainWindow::setLineEdit()//设置编辑框输入内容范围
{
QRegExp regx1("^(?:[0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$");
QRegExp regx2("^(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|[1-9])$");
QRegExp regx3("^(0\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|[1-9])$");
QRegExp regx4("^[0-9A-Fa-f]{2}( [0-9A-Fa-f]{2}){15}$");
QRegExp regx5("^[0-9A-Fa-f]{2}( [0-9A-Fa-f]{2}){31}$");
QRegExp regx6("^[0-9A-Fa-f]{2}( [0-9A-Fa-f]{2}){3}$");// 创建一个正则表达式,限制输入内容为 4 个十六进制字节,用空格隔开
ui->lineEdit11->setValidator(new QRegExpValidator(regx1, this));
ui->lineEdit12->setValidator(new QRegExpValidator(regx2, this));
ui->lineEdit14->setValidator(new QRegExpValidator(regx3, this));
ui->lineEdit15->setValidator(new QRegExpValidator(regx4, this));
ui->lineEdit16->setValidator(new QRegExpValidator(regx5, this));
ui->lineEdit17->setValidator(new QRegExpValidator(regx6, this));
ui->lineEdit18->setValidator(new QRegExpValidator(regx2, this));
ui->lineEdit11_2->setValidator(new QRegExpValidator(regx1, this));
ui->lineEdit12_2->setValidator(new QRegExpValidator(regx2, this));
ui->lineEdit14_2->setValidator(new QRegExpValidator(regx3, this));
ui->lineEdit15_2->setValidator(new QRegExpValidator(regx4, this));
ui->lineEdit16_2->setValidator(new QRegExpValidator(regx5, this));
ui->lineEdit17_2->setValidator(new QRegExpValidator(regx6, this));
ui->lineEdit18_2->setValidator(new QRegExpValidator(regx2, this));
ui->lineEdit11_3->setValidator(new QRegExpValidator(regx1, this));
ui->lineEdit12_3->setValidator(new QRegExpValidator(regx2, this));
ui->lineEdit14_3->setValidator(new QRegExpValidator(regx3, this));
ui->lineEdit15_3->setValidator(new QRegExpValidator(regx4, this));
ui->lineEdit16_3->setValidator(new QRegExpValidator(regx5, this));
ui->lineEdit17_3->setValidator(new QRegExpValidator(regx6, this));
ui->lineEdit18_3->setValidator(new QRegExpValidator(regx2, this));
ui->lineEdit11_4->setValidator(new QRegExpValidator(regx1, this));
ui->lineEdit12_4->setValidator(new QRegExpValidator(regx2, this));
ui->lineEdit14_4->setValidator(new QRegExpValidator(regx3, this));
ui->lineEdit15_4->setValidator(new QRegExpValidator(regx4, this));
ui->lineEdit16_4->setValidator(new QRegExpValidator(regx5, this));
ui->lineEdit17_4->setValidator(new QRegExpValidator(regx6, this));
ui->lineEdit18_4->setValidator(new QRegExpValidator(regx2, this));
ui->lineEdit11_5->setValidator(new QRegExpValidator(regx1, this));
ui->lineEdit12_5->setValidator(new QRegExpValidator(regx2, this));
ui->lineEdit14_5->setValidator(new QRegExpValidator(regx3, this));
ui->lineEdit15_5->setValidator(new QRegExpValidator(regx4, this));
ui->lineEdit16_5->setValidator(new QRegExpValidator(regx5, this));
ui->lineEdit17_5->setValidator(new QRegExpValidator(regx6, this));
ui->lineEdit18_5->setValidator(new QRegExpValidator(regx2, this));
}
void MainWindow::getLineEditData(uint index)//获取当前页LineEdit数据
{
bool ok;
QList<QLineEdit *> lineEdit;
switch(index)
{
case 0: lineEdit = ui->tab1->findChildren<QLineEdit *>(); break;
case 1: lineEdit = ui->tab2->findChildren<QLineEdit *>(); break;
case 2: lineEdit = ui->tab3->findChildren<QLineEdit *>(); break;
case 3: lineEdit = ui->tab4->findChildren<QLineEdit *>(); break;
case 4: lineEdit = ui->tab5->findChildren<QLineEdit *>(); break;
}
lineEdit = listSort(lineEdit);
QString str1 = lineEdit.at(0)->text(); //仪器ID
byteArray[5] = static_cast<char>((str1.toInt() >> 8) & 0xFF); // 高字节
byteArray[6] = static_cast<char>(str1.toInt() & 0xFF); // 低字节
QString str2 = lineEdit.at(1)->text(); //刷写次数
byteArray[7] = static_cast<char>(str2.toInt());
filename = lineEdit.at(2)->text();//文件名
QString str4 = lineEdit.at(3)->text();//仪器类型 1:绕组 2:变。3:工频
byteArray[4] = static_cast<char>(str4.toInt());
QString str5 = lineEdit.at(4)->text(); //加密向量
str5.remove(' ');
for (int i = 0; i < 16; ++i) {
QString hexValue = str5.mid(i * 2, 2); // 提取两个字符
quint8 value = hexValue.toUInt(&ok, 16); // 转换为十六进制数值
IV_IN[i] = value;
}
QString str6 = lineEdit.at(5)->text(); // 密钥
str6.remove(' ');
for (int i = 0; i < 32; ++i) {
QString hexValue = str6.mid(i * 2, 2); // 提取两个字符
quint8 value = hexValue.toUInt(&ok, 16); // 转换为十六进制数值
key[i] = value;
}
QString str7 = lineEdit.at(6)->text(); //匹配码
str7.remove(' ');
for (int i = 0; i < 4; ++i) {
QString hexValue = str7.mid(i * 2, 2); // 提取两个字符
quint8 value = hexValue.toUInt(&ok, 16); // 转换为十六进制数值
byteArray[i]=value;
}
QString str8 = lineEdit.at(7)->text(); //版本号
byteArray[14] = static_cast<char>(str8.toInt());
}
void MainWindow::setRangepeogressbar(uint range)
{
ui->progressBar->setRange(0,range);
}
void MainWindow::processbar(uint index)//更新进度条
{
ui->progressBar->setValue(index);
}
void MainWindow::createTable() //创建参数表
{
// 根据需求,创建数据库所需求的表,通常只需创建一次
QSqlQuery query;
//定义一条创建表的sql语句,表名:Parameter
QString sqlCreateTable = QString("create table Parameter(id integer primary key,"
"IDn vachar," //仪器ID号
"number vachar," //刷写次数
"name vachar," //文件名
"type vachar," //仪器类型
"vector vachar," //加密向量
"secret_key vachar," //密钥
"code vachar," //匹配码
"version vachar);" ); //版本号
query.exec(sqlCreateTable);
}
void MainWindow::readData(uint index)//从数据库中读取数据
{
QList<QLineEdit *> lineEdit;
switch(index)
{
case 0: lineEdit = ui->tab1->findChildren<QLineEdit *>(); break;
case 1: lineEdit = ui->tab2->findChildren<QLineEdit *>(); break;
case 2: lineEdit = ui->tab3->findChildren<QLineEdit *>(); break;
case 3: lineEdit = ui->tab4->findChildren<QLineEdit *>(); break;
case 4: lineEdit = ui->tab5->findChildren<QLineEdit *>(); break;
}
lineEdit=listSort(lineEdit);
if(!db.open())
{
qDebug()<<"open error"<<db.lastError().driverText();
}
else
{
QSqlQuery query;
QString sqlSelect = QString("select * from Parameter where id==%1").arg(index+1); //查询对应序列号的数据
if(!query.exec(sqlSelect))
{
qDebug()<<"Error select in select"<<db.lastError();
}
else
{
//遍历数据库记录
while(query.next())
{
lineEdit.at(0)->setText(query.value("IDn").toString());
lineEdit.at(1)->setText(query.value("number").toString());
lineEdit.at(2)->setText(query.value("name").toString());
lineEdit.at(3)->setText(query.value("type").toString());
lineEdit.at(4)->setText(query.value("vector").toString());
lineEdit.at(5)->setText(query.value("secret_key").toString());
lineEdit.at(6)->setText(query.value("code").toString());
lineEdit.at(7)->setText(query.value("version").toString());
}
}
}
}
void MainWindow::writeData(uint index)//向数据库中写入数据
{
QList<QLineEdit *> lineEdit;
switch(index)
{
case 0: lineEdit = ui->tab1->findChildren<QLineEdit *>(); break;
case 1: lineEdit = ui->tab2->findChildren<QLineEdit *>(); break;
case 2: lineEdit = ui->tab3->findChildren<QLineEdit *>(); break;
case 3: lineEdit = ui->tab4->findChildren<QLineEdit *>(); break;
case 4: lineEdit = ui->tab5->findChildren<QLineEdit *>(); break;
}
lineEdit=listSort(lineEdit);
QString str1 = lineEdit.at(0)->text(); //仪器ID
QString str2 = lineEdit.at(1)->text(); //刷写次数
QString str3 = lineEdit.at(2)->text(); //刷写次数
QString str4 = lineEdit.at(3)->text();//仪器类型 1:绕组 2:变。3:工频
QString str5 = lineEdit.at(4)->text(); //加密向量
QString str6 = lineEdit.at(5)->text(); // 密钥
QString str7 = lineEdit.at(6)->text(); //匹配码
QString str8 = lineEdit.at(7)->text(); //版本号
if(!db.open())
{
qDebug()<<"open error"<<db.lastError().driverText();
}
else
{
QSqlQuery query;
QString sqlupdata = QString("update Parameter set IDn='%1',number='%2',name='%3',type='%4',vector='%5',secret_key='%6',code='%7',version='%8' where id='%9';")
.arg(str1).arg(str2).arg(str3).arg(str4).arg(str5).arg(str6).arg(str7).arg(str8).arg(index+1);
if(!query.exec(sqlupdata))
{
qDebug()<<"Error update"<<db.lastError();
}
}
}
void MainWindow::on_pushButton_clicked()//选择待加密文件
{
QString newPath;
QStringList list=getUSBPaths();
if(list.count()>0)
SourceFilePath = QFileDialog :: getOpenFileName(this,tr("选择待加密文件"),list.at(0),"file(*)");
else
SourceFilePath = QFileDialog :: getOpenFileName(this,tr("选择待加密文件"),"C:/Users/123/Desktop","file(*)");
if(!SourceFilePath.isEmpty()){
//通过comboBox控件显示选择的指定文件夹路径
ui->comboBox->insertItem(0,SourceFilePath);
ui->comboBox->setCurrentIndex(0);
int lastSlashIndex = SourceFilePath.lastIndexOf('/');//查找最后一个/位置
if (lastSlashIndex != -1)
TarFile = SourceFilePath.left(lastSlashIndex);// 删除最后一个斜杠后的内容
ui->comboBox_2->insertItem(0,TarFile);
ui->comboBox_2->setCurrentIndex(0);
//初始化进度条为0
ui->progressBar->setValue(0);
}
}
void MainWindow::on_pushButton_2_clicked()//选择输出文件夹
{
QString curPath;
if(SourceFilePath.isEmpty()){
curPath = QString("C:/Users/123/Desktop");
}
else{
curPath = TargetFilePath;
}
QString dlaTitle = "选择输出文件夹";
//选择指定文件夹,并保存该文件夹的路径
TarFile = QFileDialog::getExistingDirectory(this, dlaTitle, curPath, QFileDialog::ShowDirsOnly);
ui->comboBox_2->insertItem(0,TarFile);
ui->comboBox_2->setCurrentIndex(0);
}
void MainWindow::on_pushButton_3_clicked()//一键加密
{
uint index = ui->tabWidget->currentIndex();
getLineEditData(index);
writeData(index);
if(!TarFile.isEmpty())
{
TargetFilePath = TarFile + '/' +filename;
QFile TargetFile(TargetFilePath);
if(TargetFile.exists()) {
//文件存在
} else {
//文件不存在,直接创建新文件
TargetFile.open(QIODevice::ReadWrite);
TargetFile.close();
}
}
EncryptionFile *NewThreadFile = new EncryptionFile;
connect(NewThreadFile,SIGNAL(finished()),NewThreadFile,SLOT(deleteLater()));
QObject::connect(NewThreadFile,SIGNAL(UpdateProgressBar(uint)),this,SLOT(processbar(uint)));
QObject::connect(NewThreadFile,SIGNAL(setRangePro(uint)),this,SLOT(setRangepeogressbar(uint)));
//启动线程,开始执行工作线程的任务
NewThreadFile->start();
}
void MainWindow::on_pushButton_4_clicked()
{
uint index = ui->tabWidget->currentIndex();
getLineEditData(index);
if(!TarFile.isEmpty())
{
TargetFilePath = TarFile + '/' +filename;
QFile TargetFile(TargetFilePath);
if(TargetFile.exists()) {
//文件存在
} else {
//文件不存在,直接创建新文件
TargetFile.open(QIODevice::ReadWrite);
TargetFile.close();
}
}
DecodeFile *decode = new DecodeFile;
QObject::connect(decode,SIGNAL(UpdateProgress(uint)),this,SLOT(processbar(uint)));
QObject::connect(decode,SIGNAL(setRange(uint)),this,SLOT(setRangepeogressbar(uint)));
decode->start();
}
void MainWindow::on_tabWidget_currentChanged(int index)
{
writeData(lastindex);
lastindex=index;
ui->progressBar->setValue(0);
}
2.encryptionfile.cpp
#include "encryptionfile.h"
#include "QDebug"
EncryptionFile::~EncryptionFile()
{
qDebug()<<3;
}
void EncryptionFile::run()
{
settleDocument(SourceFilePath,TargetFilePath);
// decodeDocument(SourceFilePath,TargetFilePath);
}
//当主线通过CustomThread对象调用quit接口,需要将m_exist设置为false,所以m_exist也可算是一个flag
void EncryptionFile::quit()
{
m_mutex.lock();
m_exist= false;
m_mutex.unlock();
}
bool EncryptionFile::settleDocument(const QString& SourceFile, const QString& TargetFile)
{
unsigned char data[16]={0}; //待加密的数组
unsigned char INO[16]={0};
uint index; //待加密数据在文件中的位置
// 打开文件
QFile file(SourceFile);
if (file.open(QIODevice::ReadOnly))
{
QByteArray byt = file.readAll(); // 读取文件内容到QByteArray
file.close(); // 关闭文件
const char *bytData = byt.data();// 获取QByteArray的数据指针
quint32 length = byt.size();
if(length>512512)
{
emit setRangePro(1000);
quint32 count = length/512;
if(count>=1)
{
QByteArray dataToCopy = byt.mid(index, 4);// 从源数组中复制数据
byteArray.replace(10, 4, dataToCopy);// 将数据复制到目标数组的第10到13个字节位置
// 将高字节放在第8个字节,低字节放在第9个字节
byteArray[8] = static_cast<char>((randomValue >> 8) & 0xFF);
byteArray[9] = static_cast<char>(randomValue & 0xFF);
memcpy(data,byteArray,16);
memcpy(INO,IV_IN,16);
aes->Aes_IV_key256bit_Encrypt(INO,data,key);//加密
byteArray.replace(0, 16, reinterpret_cast<const char*>(data), 16);
for(uint i=0;i<1000;i++)
{
for(uint j=0;j<32;j++)
{
index = randomValue*512+i*512+j*16;
memcpy(data,bytData+index,16);
aes->Aes_IV_key256bit_Encrypt(IV_IN,data,key);//加密
// 将unsigned char数组复制到QByteArray的第8个字节开始的位置
byt.replace(index, 16, reinterpret_cast<const char*>(data), 16);
}
emit UpdateProgressBar(i+1);
}
byt.prepend(byteArray);
}
}
else
{
emit setRangePro(length/16);
QByteArray dataToCopy = byt.mid(0, 4);// 从源数组中复制数据
byteArray.replace(9, 4, dataToCopy);// 将数据复制到目标数组的第10到13个字节位置
memcpy(data,byteArray,16);
memcpy(INO,IV_IN,16);
for(uint i=0;i<length/16;i++)
{
index=i*16;
memcpy(data,bytData+index,16);
aes->Aes_IV_key256bit_Encrypt(IV_IN,data,key);//加密
// 将unsigned char数组复制到QByteArray的第8个字节开始的位置
byt.replace(index, 16, reinterpret_cast<const char*>(data), 16);
emit UpdateProgressBar(i+1);
}
byt.prepend(byteArray);
}
QFile TarFile(TargetFile);
if(TarFile.open(QIODevice::ReadWrite)) {
TarFile.write(byt);
TarFile.close();
} else {
qDebug() << "read file faile";
}
} else {
qDebug() << "File opening failure";
// 处理文件打开失败的情况
}
return true;
}