在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加密方式

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

enum Algorithm { Md4, Md5, Sha1, Sha224, ..., Keccak_512 }
两种处理数据的方式

少量数据的加密

QByteArray hash(const QByteArray &data, QCryptographicHash::Algorithm method)

示例:

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

大量数据的加密

void addData(const QByteArray &data)

示例:

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:

signals:
   void sendMd5CheckSumSignal(QByteArray);         //反馈md5值到界面
   void sendProgressBarSignal(int, int);           //反馈进度到界面 以生成进度条

public slots:

public slots:
   void getMd5CheckSumSlot(const QString &filePath); /*Md5单项加密计算槽函数*/

md5check.h

#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

#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对象以及处理线程

QThread md5Thread;          //线程
Md5Check mMd5CheckSum;

将对象移至线程

mMd5CheckSum.moveToThread(&md5Thread);      /*从一个object 移动到 一个thread*/
md5Thread.start();                          /*开启线程*/

关联信号与槽

/* 关联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单项加密任务

emit checkMd5SumSignal(md5Filename); /*将打开的文件路径通过信号传递给Md5Check对象*/