基于qt的文件加密程序

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


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

  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是使用 Qt 语言实现 RSA 算法加密文件的示例代码: ```cpp #include <QCoreApplication> #include <QFile> #include <QDataStream> #include <QDebug> #include <openssl/rsa.h> #include <openssl/pem.h> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); // 加载公钥 RSA *rsa = RSA_new(); FILE *fp = fopen("public_key.pem", "r"); rsa = PEM_read_RSA_PUBKEY(fp, &rsa, NULL, NULL); fclose(fp); // 打开待加密文件 QFile file("plaintext.txt"); if (!file.open(QIODevice::ReadOnly)) { qDebug() << "Failed to open file."; return -1; } // 读取待加密数据 QByteArray plaintext = file.readAll(); file.close(); // 计算加密后数据长度并分配内存 int plaintextLen = plaintext.size(); int keyLen = RSA_size(rsa); int cipherLen = 0; if (plaintextLen % keyLen == 0) { cipherLen = plaintextLen / keyLen * RSA_size(rsa); } else { cipherLen = (plaintextLen / keyLen + 1) * RSA_size(rsa); } unsigned char *ciphertext = new unsigned char[cipherLen]; // 使用公钥加密数据 int cipherBlockLen = RSA_public_encrypt(keyLen - 11, (unsigned char*)plaintext.constData(), ciphertext, rsa, RSA_PKCS1_PADDING); int totalCipherLen = cipherBlockLen; for (int i = keyLen - 11; i < plaintextLen; i += keyLen - 11) { cipherBlockLen = RSA_public_encrypt(keyLen - 11, (unsigned char*)plaintext.constData() + i, ciphertext + totalCipherLen, rsa, RSA_PKCS1_PADDING); totalCipherLen += cipherBlockLen; } // 保存加密后数据到文件 QFile cipherFile("ciphertext.bin"); if (!cipherFile.open(QIODevice::WriteOnly)) { qDebug() << "Failed to create cipher file."; return -1; } QDataStream out(&cipherFile); out.writeRawData((const char*)ciphertext, totalCipherLen); cipherFile.close(); // 释放内存 delete[] ciphertext; RSA_free(rsa); return a.exec(); } ``` 在示例代码中,我们使用 OpenSSL 库中提供的 `RSA` 类型和 `PEM_read_RSA_PUBKEY` 函数加载公钥文件。然后打开待加密文件,读取文件中的数据。接着计算加密后数据的长度,并分配内存。最后,使用公钥对数据进行加密,保存加密后数据到文件中。 需要注意的是,在使用 RSA 算法加密数据时,每次加密的数据长度不能超过公钥长度减去 11,因此我们需要对待加密数据进行分块加密。在示例代码中,我们使用一个循环来实现分块加密。 需要使用的 OpenSSL 库头文件为 `openssl/rsa.h` 和 `openssl/pem.h`。在编译时需要链接 OpenSSL 库,可以在项目文件中添加以下配置: ```qmake LIBS += -lssl -lcrypto ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值