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