Qt多线程编程实战:MD5单项加密

2020-09-10 12:04:01 浏览数 (1)

在MD5正向加密之前,普及一下加密技术

现在的加密/解密技术主要有三种:对称加密,非对称加密,和单向加密,这三种加密解密技术的组合就是现在电子商务的基础,它们三个有各自最适合的领域

对称加密:指的是加密方和解密方使用的是同一个密钥

非对称加密:非对称加密方式解决了对称加密的缺陷,它的加密和解密密钥是不同的,比如对一组数字加密,我们可以用公钥对其加密,然后我们想要将其还原,就必须用私钥进行解密,公钥和私钥是配对使用的,常见的非对称加密算法有:

公钥加密 私钥解密

RSA:既可以用来加密解密,又可以用来实现用户认证

DSA:只能用来加密解密,所以使用范围没有RSA广

非对称加密长度通常有512,1024,2048,4096位,最常用的就是2048位,长度固然可以增加安全性但是需要花费很长时间来进行加密/解密,和对称加密相比,加密/解密的时间差不多是对称加密的1000倍,所以我们通常用其作为用户认证,用对称加密来实现数据的加密/解密

ps:加密长度512位可以暴力破解

单项加密:单向加密就是用来计算一段数据的特征码的,为了防止用户通过“暴力破解”的方式解密,所以单向加密一般具有“雪崩效应”就是说:只要被加密内容有一点点的不同,加密所得结果就会有很大的变化。单项加密还有一个特点就是无论被加密的内容多长/短,加密的结果(就是提取特征码)是定长的,用途:用于验证数据的完整性,常用的单项加密算法

MD5:这种加密算法固定长度为128位

SHA1:这种加密算法固定长度是160位

本期通过Qt QCryptographicHash::Md5 对磁盘上的文件进行单项加密

效果展示:

对2.86 GB (3,076,476,328 字节)的文件在线程中进行单项加密,不卡主界面,加密进度通过信号/槽返回给主界面显示。

QCryptographicHash加密方式

详情看官网文档,只列举少部分

代码语言:javascript复制
enum Algorithm { Md4, Md5, Sha1, Sha224, ..., Keccak_512 }

两种处理数据的方式

少量数据的加密

代码语言:javascript复制
QByteArray hash(const QByteArray &data, QCryptographicHash::Algorithm method)

示例:

代码语言:javascript复制
QByteArray temp=file.readAll();	/*读取数据*/
QByteArray md5=QCryptographicHash::hash(temp,QCryptographicHash::Md5);
ui->textEdit->setText(md5.toHex());/*MD5:这种加密算法固定长度为128位,32字节*/
  • 缺陷:当文档很大时readAll会出错

大量数据的加密

代码语言:javascript复制
void addData(const QByteArray &data)

示例:

代码语言:javascript复制
QCryptographicHash hash(QCryptographicHash::Md5);
while(!file.atEnd())
{
 	QByteArray content = file.read(1024*1024);	/*读取1M数据*/
  	hash.addData(content);						/*多次计算*/
 }
 QByteArray md5 = hash.result().toHex();		/*MD5:这种加密算法固定长度为128位,32字节*/

Md5单项加密对象设计

signals:

代码语言:javascript复制
signals:
    void sendMd5CheckSumSignal(QByteArray);         //反馈md5值到界面
    void sendProgressBarSignal(int, int);           //反馈进度到界面 以生成进度条

public slots:

代码语言:javascript复制
public slots:
    void getMd5CheckSumSlot(const QString &filePath);	/*Md5单项加密计算槽函数*/

md5check.h

代码语言:javascript复制
#ifndef MD5CHECK_H
#define MD5CHECK_H

#include <QObject>
#include <QCryptographicHash>
#include <QFile>
#include <QFileInfo>
#include <QDebug>

class Md5Check : public QObject
{
    Q_OBJECT
public:
    explicit Md5Check(QObject *parent = nullptr);

signals:
    void sendMd5CheckSumSignal(QByteArray);         //反馈md5值到界面
    void sendProgressBarSignal(int, int);           //反馈进度到界面 以生成进度条
    //已经处理的数据量 待处理的总量

public slots:
    void getMd5CheckSumSlot(const QString &filePath);
};

#endif // MD5CHECK_H

md5check.cpp

代码语言:javascript复制
#include "md5check.h"

Md5Check::Md5Check(QObject *parent) : QObject(parent){}

void Md5Check::getMd5CheckSumSlot(const QString &filePath)
{
    QFile file(filePath);
    QByteArray md5Result;
    QFileInfo md5FileInfo;
    md5FileInfo = QFileInfo(filePath);  /*获取文件信息,考虑到文件过大*/

    int totalSize = md5FileInfo.size()/(1024*1024); /*   把Byte字节转换成M兆    */
    if(md5FileInfo.size()%(1024*1024)>0)
        totalSize =1;                               /*   多余补一    */
    int currentSize = 0;                /*当前进度,读取的M兆数*/

    if(file.open(QIODevice::ReadOnly))
    {
        QCryptographicHash hash(QCryptographicHash::Md5);
        while (!file.atEnd()) {         //读取文件直到读物完整
            QByteArray content = file.read(1024*1024);  /*每次读取一兆M*/
            hash.addData(content);      /*分段进程MD5累加*/
            currentSize  ;              /*当前进度,进度加一*/
            emit sendProgressBarSignal(totalSize,currentSize);  /*传送百分比信号*/
        }
        md5Result = hash.result().toHex();      /*MD5值为32位的十六进制数*/
        emit sendMd5CheckSumSignal(md5Result);  /*发送MD5结果*/
        file.close();
    }
}

线程处理IO操作

定义Md5Check对象以及处理线程

代码语言:javascript复制
QThread md5Thread;          //线程
Md5Check mMd5CheckSum;

将对象移至线程

代码语言:javascript复制
mMd5CheckSum.moveToThread(&md5Thread);      /*从一个object 移动到 一个thread*/
md5Thread.start();                          /*开启线程*/

关联信号与槽

代码语言:javascript复制
/* 关联MD5计算槽函数 让Md5Check对象开始计算MD5值 */
connect(this,SIGNAL(checkMd5SumSignal(QString)),&mMd5CheckSum,SLOT(getMd5CheckSumSlot(QString)));
/*关联MD5结果返回信号,将MD5计算结果传递给Widget定义的槽函数recvMd5CheckSumSlot*/
connect(&mMd5CheckSum, SIGNAL(sendMd5CheckSumSignal(QByteArray)),this, SLOT(recvMd5CheckSumSlot(QByteArray)));
/*关联MD5计算进度,将进度返回给Widget定义的槽函数recvProgressBarSlot*/
connect(&mMd5CheckSum, SIGNAL(sendProgressBarSignal(int,int)),this, SLOT(recvProgressBarSlot(int,int)));

开启md5单项加密任务

代码语言:javascript复制
emit checkMd5SumSignal(md5Filename); /*将打开的文件路径通过信号传递给Md5Check对象*/

关键字【MD5单项加密】

End

0 人点赞