QT MD4 MD5 Sha1等几种加密方式
[1] QT MD4 MD5 Sha1等几种加密方式
QT 自带有QCryptographicHash类可以进行很方便的进行 md4 、md5等加密。使用方法很简单,直接提供了一个静态的方法。
QByteArray QCryptographicHash::hash(const QByteArray &data, Algorithm method)
data就是要加密的数据, method是加密的方法,看官方文档选择加密的方式就行。
QString strCipher = QCryptographicHash::hash(strKey.toLocal8Bit(), QCryptographicHash::Md5);
QString MainWindow::fileMd5(const QString &sourceFilePath) {
QFile sourceFile(sourceFilePath);
qint64 fileSize = sourceFile.size();
const qint64 bufferSize = 10240;
if (sourceFile.open(QIODevice::ReadOnly)) {
char buffer[bufferSize];
int bytesRead;
int readSize = qMin(fileSize, bufferSize);
QCryptographicHash hash(QCryptographicHash::Md5);
while (readSize > 0 && (bytesRead = sourceFile.read(buffer, readSize)) > 0) {
fileSize -= bytesRead;
hash.addData(buffer, bytesRead);
readSize = qMin(fileSize, bufferSize);
}
sourceFile.close();
return QString(hash.result().toHex());
}
return QString();
}
[2] qt MD5 和AES 加密
一 、MD5 加密
#include <QCryptographicHash>
// MD5 加密
QString Dialog_login::MD5_encryption(const QString &data)
{
QCryptographicHash md5(QCryptographicHash::Md5); //使用MD5加密
md5.addData(data.toUtf8(),data.size()); // 添加数据
QByteArray bArry = md5.result(); //获取MD5加密后的密码
QString md5_date;
md5_data.append(bArry.toHex());
return md5_data;
}
二、AES 加密和解密
https://blog.csdn.net/chen1231985111/article/details/125748534
1. 下载库:https://github.com/bricke/Qt-AES
下载后需要下面5个文件,把这些文件复制出来放到一个文件夹下:
2. qt 工程添加这些文件
3. 编写加密解密代码
#include "aesni/qaesencryption.h"
// 加密
QString Dialog_login::AES_encryption(const QString &data, const QString &key)
{
QAESEncryption encryption(QAESEncryption::AES_128, QAESEncryption::ECB, QAESEncryption::PKCS7);
QByteArray enBA = encryption.encode(data.toUtf8(), key.toUtf8());
return QString::fromLatin1(enBA.toBase64());
}
// 解密
QString Dialog_login::AES_decryption(const QString &data, const QString &key)
{
QAESEncryption encryption(QAESEncryption::AES_128, QAESEncryption::ECB, QAESEncryption::PKCS7);
QByteArray enBA = QByteArray::fromBase64(data.toUtf8());
QByteArray deBA = encryption.decode(enBA, key.toUtf8());
return QString::fromLatin1(QAESEncryption::RemovePadding(deBA, QAESEncryption::PKCS7));
}
[3] QT中sqlite数据库数据加密/混淆—MD5/SHA1/SHA2/SHA3
原文链接:https://blog.csdn.net/qq_43533553/article/details/123416880
利用分解质因数的运算(质数取模)原理实现的,比如:给你100个数让你乘起来比较容易但是给你一个数让你求它100个质数就会比较难,所以数据加密就用这种方法来实现。
MD5是一种将任意长度的数据进行变换得到128位2进制数据,无法通过128位数据求的原始数据。
在QT中使用:
(1)创建一个加密对象
QCryptographicHash hash(QCryptographicHash::Md5);
(2)放入要加密的数据
void QCryptographicHash::addData(const QByteArray &data);
//hash.addData(password.toUft8());
(3)获取加密的结果
QByteArray QCryptographicHash::result() const;
//hash.result();
测试
//对密码进行MD5加密
//1.创建加密对象
QCryptographicHash hash(QCryptographicHash::Md5);
//2.放入要加入的数据
hash.addData(password.toUtf8());
//3.获取加密的结果
QByteArray arr = hash.result();
password = arr.toHex();
qDebug()<<password;
结果显示
[4] [Qt学习笔记]Qt程序加密,实现软件运行次数和硬件信息绑定
原文链接:https://blog.csdn.net/fengyaowuhui/article/details/126150459
前言
程序员为了防止自己的成果被白嫖,或者发布的软件在公司层面上要做一些防抄袭处理,这时就需要在软件层面上加锁、加密等操作。
1、单机终端软件
这类软件一般在未联网的情况下使用,所以不能通过网络去判定是否得到授权,一般采用绑定硬件信息来对软件进行加密,这样软件与设备绑定就无法进行随意使用。
2、远程授权监控
终端软件在启动后就会跟服务器通讯来检查当前设备是否已经得到授权,可实现远程锁定程序,设置程序的使用时间和使用次数。
以上两种方法都是最基础的软件加密方法,根据加密的算法的复杂度其破解的难度也不同,不过作为普通的一种加密方法已经够用了,市面上有比较成熟的加密加壳的软件,其安全程度要远高于软件加密的方法,下次抽时间介绍一下软件VMProtect的加、解密过程。
1、思路分析
单机软件想要每次启动前去验证是否有授权,需要从软件的配置中获取授权的验证信息,这里以软件的使用次数来举例,我们需要把软件的可使用次数写入配置文件ini或数据库中。每次在软件重新启动时,我们根据配置文件中信息来判断软件剩余的使用次数。
这里设定软件的剩余使用次数为2次,不过这里有一个很明显的缺点,就是明文写到配置文件里,就可以自己修改,然后就失去了加密的属性,这里就需要对这个信息进行加密后再写入。这里使用Qt自带的base64对字符串进行加密。
2、实现函数
//加密
QString Widget::Encode(QString row)
{
QByteArray byteArray = row.toUtf8();
byteArray = byteArray.toBase64();
return byteArray;
}
//解密
QString Widget::Decode(QString passwd)
{
QByteArray byteArray = passwd.toUtf8();
byteArray = QByteArray::fromBase64(byteArray);
return byteArray;
}
//从配置文件获取信息
QString Widget::getInfoFromIni(QString str)
{
QString info;
QFile file(str);
if(!file.exists()) { //如果文件不存在
QString times_str = "RemainTime:"+time;
WriteInfo2Ini(str, times_str);
}
file.open(QFile::ReadWrite | QFile::Text);
info = file.readAll(); //读取信息
file.close();
return info;
}
//将信息写入到配置文件
void Widget::WriteInfo2Ini(QString str, QString info_text)
{
QFile file(str);
file.open(QFile::ReadWrite | QFile::Text | QFile::Truncate);
file.write(Encode(info_text).toUtf8()); //写入信息
file.close();
}
这种方法有一种弊端,就是如果重新覆盖配置文件可以跳出限制,比如这里如果事前拷贝一份ini文件,当软件次数为0后,重新拷贝原始ini文件后又获得初始的软件使用次数。
如果考虑不使用ini文件来记录授权信息,而是使用注册表来记录授权信息,这样软件使用者就不容易去发现授权信息的位置
void Widget::WriteInfo2Registry(QString str)
{
//写入注册表
QSettings settings("HKEY_CURRENT_USER\\Software\\Code_Encryption\\Settings",QSettings::NativeFormat);
settings.setValue("remain_times",Encode(str).toUtf8());
}
QString Widget::getInfoFromRegistry()
{
QString info;
//通过写入注册表来判断
QSettings settings("HKEY_CURRENT_USER\\Software\\Code_Encryption\\Settings",QSettings::NativeFormat);
info = settings.value("remain_times").toString();
return info;
}
3、示例代码
widget.cpp
#pragma execution_character_set("utf-8")
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
QString str = getCpuId();
qDebug()<<"cpu id is"<<str;
// QString times_str = "RemainTime:"+time;
// WriteInfo2Registry(times_str);
Judge_Authorize_times(1);
}
Widget::~Widget()
{
delete ui;
}
QString Widget::getWMIC(const QString &cmd)
{
//获取cpu名称:wmic cpu get Name
//获取cpu核心数:wmic cpu get NumberOfCores
//获取cpu线程数:wmic cpu get NumberOfLogicalProcessors
//查询cpu序列号:wmic cpu get processorid
//查询主板序列号:wmic baseboard get serialnumber
//查询BIOS序列号:wmic bios get serialnumber
//查看硬盘:wmic diskdrive get serialnumber
QProcess p;
p.start(cmd);
p.waitForFinished();
QString result = QString::fromLocal8Bit(p.readAllStandardOutput());
QStringList list = cmd.split(" ");
result = result.remove(list.last(), Qt::CaseInsensitive);
result = result.replace("\r", "");
result = result.replace("\n", "");
result = result.simplified();
return result;
}
QString Widget::getCpuId() //获取CPU序列号
{
return getWMIC("wmic cpu get processorid");
}
QString Widget::getDiskNum() //获取硬盘序列号
{
return getWMIC("wmic diskdrive where index=0 get serialnumber");
}
QString Widget::Encode(QString row)
{
QByteArray byteArray = row.toUtf8();
byteArray = byteArray.toBase64();
return byteArray;
}
QString Widget::Decode(QString passwd)
{
QByteArray byteArray = passwd.toUtf8();
byteArray = QByteArray::fromBase64(byteArray);
return byteArray;
}
QString Widget::getInfoFromIni(QString str)
{
QString info;
QFile file(str);
if(!file.exists()) { //如果文件不存在
QString times_str = "RemainTime:"+time;
WriteInfo2Ini(str, times_str);
}
file.open(QFile::ReadWrite | QFile::Text);
info = file.readAll(); //读取信息
file.close();
return info;
}
void Widget::WriteInfo2Ini(QString str, QString info_text)
{
QFile file(str);
file.open(QFile::ReadWrite | QFile::Text | QFile::Truncate);
file.write(Encode(info_text).toUtf8()); //写入信息
file.close();
}
void Widget::WriteInfo2Registry(QString str)
{
//写入注册表
QSettings settings("HKEY_CURRENT_USER\\Software\\Code_Encryption\\Settings",QSettings::NativeFormat);
settings.setValue("remain_times",Encode(str).toUtf8());
}
QString Widget::getInfoFromRegistry()
{
QString info;
//通过写入注册表来判断
QSettings settings("HKEY_CURRENT_USER\\Software\\Code_Encryption\\Settings",QSettings::NativeFormat);
info = settings.value("remain_times").toString();
return info;
}
void Widget::Judge_Authorize_times(int type)
{
QString times_info;
if(type == 0)
{
//通过ini配置文件进行判断
times_info = getInfoFromIni("System.ini");
}
else
{
//通过写入注册表来判断
times_info = getInfoFromRegistry();
}
if(times_info.isEmpty())
{
QMessageBox::about(this,"提示","授权信息为空,请检查!");
exit(0);
}
else
{
QString info = Decode(times_info); //解码
if(info.contains(':')) { //信息正确
QStringList list = info.split(':');
if(list.length()>=1) {
if(list[1].toInt() <= 0) { //程序剩余使用次数不足
QMessageBox::about(this,"提示","请注册后再使用!");
exit(0); //程序退出
}else { //程序还有剩余使用次数
QString time_remain = QString::number(list[1].toInt()-1); //程序剩余使用次数减1
QString str = "RemainTime:"+time_remain;
if(type == 0) WriteInfo2Ini("System.ini", str);
else {
//写入注册表
WriteInfo2Registry(str);
}
QMessageBox::about(this,"提示","程序剩余使用次数:"+time_remain+"次");
}
}
}
}
}
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QFile>
#include <QMessageBox>
#include <QProcess>
#include <QDebug>
#include <QSettings>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private:
Ui::Widget *ui;
QString getWMIC(const QString &cmd);
QString getCpuId();
QString getDiskNum();
//加密
QString Encode(QString row);
//解密
QString Decode(QString passwd);
//判断授权信息 0:使用ini方法判断;1:使用注册表方法判断
void Judge_Authorize_times(int type);
//从ini获取授权信息
QString getInfoFromIni(QString str);
//写入授权信息到ini
void WriteInfo2Ini(QString str, QString info_text);
//从注册表获取授权信息
QString getInfoFromRegistry();
//写入授权信息到注册表
void WriteInfo2Registry(QString str);
//授权程序使用次数为2次
QString time = "2";
};
#endif // WIDGET_H
4、效果展示
[5] Qt–探讨.exe程序加密
原文链接:https://blog.csdn.net/Mr_robot_strange/article/details/108776517
一、前言
程序员随着代码写的多,难免会接到一些私活。但是又怕对方白嫖,困难总比办法多,哦不,错了,办法总比困难多。为了避免被别人白嫖,我们可以给自己的程序留后手,网上查阅资料,大概有以下两种:
1、采用远程控制:UDP指令远程锁死程序;
2、采用本地加密:提取CPU和硬盘序列号,加密生成注册码;
以上两种方法各有利弊,方法1可以本人自由控制,但是一旦设备没网,就GG了;方法2则不依赖网络,且每台设备的注册码唯一,但是本人无法直接控制。个人认为还是方法2简单有效,所以下面就方法2进行具体分析。
二、分析
采用注册码机制,我们首先要生成注册码,Qt下获取CPU和硬盘等系统信息(针对windows系统)的方法如下:
windows下执行命令除了用cmd之外,还有个东西叫WMIC,非常强大,可以通过他获取很多信息,包括硬件信息。
QString Widget::getWMIC(const QString &cmd)
{
//获取cpu名称:wmic cpu get Name
//获取cpu核心数:wmic cpu get NumberOfCores
//获取cpu线程数:wmic cpu get NumberOfLogicalProcessors
//查询cpu序列号:wmic cpu get processorid
//查询主板序列号:wmic baseboard get serialnumber
//查询BIOS序列号:wmic bios get serialnumber
//查看硬盘:wmic diskdrive get serialnumber
QProcess p;
p.start(cmd);
p.waitForFinished();
QString result = QString::fromLocal8Bit(p.readAllStandardOutput());
QStringList list = cmd.split(" ");
result = result.remove(list.last(), Qt::CaseInsensitive);
result = result.replace("\r", "");
result = result.replace("\n", "");
result = result.simplified();
return result;
}
QString Widget::getCpuName()
{
return getWMIC("wmic cpu get name");
}
QString Widget::getCpuId()
{
return getWMIC("wmic cpu get processorid");
}
QString Widget::getDiskNum()
{
return getWMIC("wmic diskdrive where index=0 get serialnumber");
}
获取注册码之后,就可以着手程序的加密了,我的策略是这样的:
如果程序没有注册,默认可以使用3次;
如果程序注册了,使用次数无限制;
那怎么限制程序的使用次数呢?我的策略是这样的:
生成一个System.ini配置文件,里面存放程序的剩余运行次数RemainTime:3;
但是RemainTime:3当然不能直接存在System.ini中,不然一眼看出来就可以自己修改次数了;
所以在对System.ini写之前,进行加密;对System.ini读之后,进行解密;
加/解密算法可以自行选取,但是要采用可逆算法;
然后判断剩余运行次数,如果小于等于0,则程序提示需注册后使用,并退出;
否则,剩余运行次数减1,程序正常运行;
三、实现(核心代码)
QString Widget::getWMIC(const QString &cmd)
{
//获取cpu名称:wmic cpu get Name
//获取cpu核心数:wmic cpu get NumberOfCores
//获取cpu线程数:wmic cpu get NumberOfLogicalProcessors
//查询cpu序列号:wmic cpu get processorid
//查询主板序列号:wmic baseboard get serialnumber
//查询BIOS序列号:wmic bios get serialnumber
//查看硬盘:wmic diskdrive get serialnumber
QProcess p;
p.start(cmd);
p.waitForFinished();
QString result = QString::fromLocal8Bit(p.readAllStandardOutput());
QStringList list = cmd.split(" ");
result = result.remove(list.last(), Qt::CaseInsensitive);
result = result.replace("\r", "");
result = result.replace("\n", "");
result = result.simplified();
return result;
}
QString Widget::getCpuId() //获取CPU序列号
{
return getWMIC("wmic cpu get processorid");
}
QString Widget::getDiskNum() //获取硬盘序列号
{
return getWMIC("wmic diskdrive where index=0 get serialnumber");
}
QString Widget::Encode(QString row) //加密,由于加/解密不是本文重点,故简单处理一下
{
QByteArray byteArray = row.toUtf8();
byteArray = byteArray.toBase64();
return byteArray;
}
QString Widget::Decode(QString passwd) //解密
{
QByteArray byteArray = passwd.toUtf8();
byteArray = QByteArray::fromBase64(byteArray);
return byteArray;
}
void Widget::Judge_Valid() //判断程序合法性
{
QString filePath = "System.ini";
QFile file(filePath);
if(!file.exists()) { //如果文件不存在
file.open(QIODevice::ReadWrite | QIODevice::Text); //新建文件
QString info = "RemainTime:"+time; //time是全局变量,QString time = "3";
file.write(Encode(info).toUtf8()); //写入信息
file.close();
goto Here;
}else { //如果文件存在
Here:if(file.open(QFile::ReadWrite | QFile::Text)) { //打开文件
QString info = file.readAll(); //读取信息
if(info.isEmpty()) { //如果文件为空
QString time_temp = "1";
QString info = "RemainTime:"+time_temp;
file.write(Encode(info).toUtf8()); //写入信息
info = file.readAll();
}
info = Decode(info); //解码
if(info.contains(':')) { //信息正确
QStringList list = info.split(':');
if(list.length()>=1) {
if(list[1].toInt() <= 0) { //程序剩余使用次数不足
QMessageBox::about(this,"提示","请注册后再使用!");
exit(0); //程序退出
}else { //程序还有剩余使用次数
file.close();
file.open(QFile::ReadWrite | QFile::Text | QFile::Truncate); //清空文件内容
QString time_remain = QString::number(list[1].toInt()-1); //程序剩余使用次数减1
QString info = "RemainTime:"+time_remain;
file.write(Encode(info).toUtf8()); //更新程序剩余使用次数
QMessageBox::about(this,"提示","程序剩余使用次数:"+time_remain+"次");
}
}
}
}//Here
file.close();
}//如果文件存在
}
四、效果
附:MD5加密注册码
//获取设备信息字符串
const QString get_SerialNumber()
{
QString cpu_id = "";
QProcess p(0);
p.start("wmic CPU get ProcessorID"); //其它信息也类似
p.waitForStarted();
p.waitForFinished();
cpu_id = QString::fromLocal8Bit(p.readAllStandardOutput());
cpu_id = cpu_id.remove("ProcessorId").trimmed();
QString lpRootPathName = "C:\\";
LPTSTR lpVolumeNameBuffer=new TCHAR[12];//磁盘卷标
DWORD nVolumeNameSize=12;// 卷标的字符串长度
DWORD VolumeSerialNumber;//硬盘序列号
DWORD MaximumComponentLength;// 最大的文件长度
LPTSTR lpFileSystemNameBuffer=new TCHAR[10];// 存储所在盘符的分区类型的长指针变量
DWORD nFileSystemNameSize=10;// 分区类型的长指针变量所指向的字符串长度
DWORD FileSystemFlags;// 文件系统的一此标志
GetVolumeInformation((LPTSTR)lpRootPathName.utf16(),
lpVolumeNameBuffer, nVolumeNameSize,
&VolumeSerialNumber, &MaximumComponentLength,
&FileSystemFlags,
lpFileSystemNameBuffer, nFileSystemNameSize);
return (cpu_id.mid(0,4) + "D-"+ cpu_id.mid(4,4) + "R-" +
cpu_id.mid(8,4) + "E-" + cpu_id.mid(12,4) + "A-" +
QString::number(VolumeSerialNumber,10).mid(0,4)+"M");
}
//使用MD5对设备信息字符串进行加密
const QString hash_Encryption(const QString temp)
{
QByteArray byte_array;
byte_array.append(temp);
QByteArray hash_byte_array = QCryptographicHash::hash(byte_array,QCryptographicHash::Md5);
return hash_byte_array.toHex().toUpper();
}
//将加密后的字符串序列化为注册码形式
const QString format_HASHString(const QString hashtemp)
{
QString retemp = "";
for(int i = 0; i < 7; i++)
{
retemp += hashtemp.mid(4*i,4) + "-";
}
retemp += hashtemp.mid(28,4);
return retemp;
}
//去除注册码格式,转化为MD5加密后的字符串
const QString remove_Format(const QString formathash)
{
QString temp = "";
for(int i = 0; i < 8; i++)
{
temp += formathash.mid(5*i,4);
}
return temp;
}
[6] Qt之Base64编解码
编码
QByteArray QByteArray::toBase64() const
QByteArray QByteArray::toBase64(QByteArray::Base64Options options) const
示例
QByteArray text("Hello world");
text.toBase64();
/* 输出: SGVsbG8gd29ybGQ= */
解码
[static] QByteArray QByteArray::fromBase64(const QByteArray &base64)
[static] QByteArray QByteArray::fromBase64(const QByteArray &base64,
QByteArray::Base64Options options)
示例
QByteArray::fromBase64("SGVsbG8gd29ybGQ=");
/* 输出: Hello world */
CTK Plugin Framework插件框架学习1–Qt编译CTK
https://wangjichuan.blog.csdn.net/article/details/128547331?spm=1001.2014.3001.5502