12 KiB
12 KiB
#qt
新建测试工程 Dialog,默认mingw编译方式即可 解压开源方案到工程目录后
需要把openssl文件夹,从include里拿出来,否则 后续 引用异常
bin文件夹里面的,是aes的可执行dll文件,后续如果要使用,也直接复制粘贴即可
创建一下,windows获取硬件属性相关的逻辑,wmic,参考WMIC功能整理即可
再创建一下AESTool,用来引用相关的库
pro文件,工程属性
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
DLL_SRC = $$PWD/bin/*.dll
CONFIG += c++17
LIBS += -L$$PWD/lib -llibcrypto \
-L$$PWD/lib -llibssl
INCLUDEPATH += $$PWD \
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
aestool.cpp \
main.cpp \
dialog.cpp \
wmic.cpp
HEADERS += \
aestool.h \
dialog.h \
wmic.h
FORMS += \
dialog.ui
# 复制依赖库
DLL_DST = $$DESTDIR
DLL_SRC ~= s,/,\\,g
DLL_DST ~= s,/,\\,g
QMAKE_POST_LINK += $$quote($$QMAKE_COPY $$DLL_SRC $$DLL_DST$$escape_expand(\n\t))
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
AESTool对应逻辑参考 头文件
#ifndef AESTOOL_H
#define AESTOOL_H
//#include <QByteArray>
//namespace AESTool {
//QByteArray encrypt(const QByteArray& byteArray, const QByteArray& key);
//QByteArray decrypt(const QByteArray& byteArray, const QByteArray& key);
//}
#include <QByteArray>
#include <openssl/aes.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <QString>
#include <QDebug>
#include <QScopedPointer>
class AESTool
{
public:
struct ScopedPointerCipherCtxDeleter
{
static inline void cleanup(EVP_CIPHER_CTX *pointer)
{
EVP_CIPHER_CTX_free(pointer);
}
};
// 解密函数,失败返回空
static QByteArray decrypt(QByteArray cyphertext, const QString& key, const QString& iv);
// 加密函数,失败返回空
static QByteArray encrypt(QByteArray plaintext, const QString& key, const QString& iv);
// 获取最后一次错误信息
static QString GetLastError();
};
#endif // AESTOOL_H
cpp
#include "aestool.h"
#include <QCryptographicHash>
//#include <openssl/evp.h>
//namespace AESTool {
//QByteArray encrypt(const QByteArray& data, const QByteArray& key)
//{
// EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
// int outLen1 = data.size() + EVP_MAX_BLOCK_LENGTH;
// int outLen2;
// QByteArray buffer(outLen1, 0);
// EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, reinterpret_cast<const unsigned char*>(key.constData()), nullptr);
// EVP_EncryptUpdate(ctx, reinterpret_cast<unsigned char*>(buffer.data()), &outLen1, reinterpret_cast<const unsigned char*>(data.constData()), data.size());
// EVP_EncryptFinal_ex(ctx, reinterpret_cast<unsigned char*>(buffer.data()) + outLen1, &outLen2);
// EVP_CIPHER_CTX_free(ctx);
// return buffer.left(outLen1 + outLen2);
//}
//QByteArray decrypt(const QByteArray& data, const QByteArray& key)
//{
// EVP_CIPHER_CTX *ctx;
// ctx = EVP_CIPHER_CTX_new();
// int outLen1 = data.size();
// int outLen2;
// QByteArray buffer(outLen1, 0);
// EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, reinterpret_cast<const unsigned char*>(key.constData()), nullptr);
// EVP_DecryptUpdate(ctx, reinterpret_cast<unsigned char*>(buffer.data()), &outLen1, reinterpret_cast<const unsigned char*>(data.constData()), data.size());
// EVP_DecryptFinal_ex(ctx, reinterpret_cast<unsigned char*>(buffer.data()) + outLen1, &outLen2);
// EVP_CIPHER_CTX_free(ctx);
// return buffer.left(outLen1 + outLen2);
//}
//}
QByteArray AESTool::decrypt(QByteArray cyphertext, const QString& keyStr, const QString& ivStr)
{
QByteArray key = QCryptographicHash::hash(keyStr.toLocal8Bit(), QCryptographicHash::Sha256);
QByteArray iv = QCryptographicHash::hash(ivStr.toLocal8Bit(), QCryptographicHash::Md5);
ERR_clear_error();
// 检查密钥合法性(只能是16、24、32字节)
Q_ASSERT(key.size() == 32 );
Q_ASSERT(iv.size() == 16);
QByteArray plaintext;
QScopedPointer <EVP_CIPHER_CTX , ScopedPointerCipherCtxDeleter> ctx(EVP_CIPHER_CTX_new());
if (!EVP_DecryptInit_ex(ctx.data(), EVP_aes_256_cbc(), NULL, (unsigned char *)key.data(), (unsigned char *)iv.data()))
{
plaintext.clear();
return plaintext;
}
if (!EVP_CIPHER_CTX_set_padding(ctx.data(), EVP_PADDING_PKCS7))
{
plaintext.clear();
return plaintext;
}
int outlen = 0;
plaintext.resize(cyphertext.size());
if (!EVP_DecryptUpdate(ctx.data(), (unsigned char *)plaintext.data(), &outlen, (unsigned char *)cyphertext.data(), cyphertext.size()))
{
plaintext.clear();
return plaintext;
}
int tmplen = 0;
if (!EVP_DecryptFinal_ex(ctx.data(), (unsigned char *)plaintext.data() + outlen, &tmplen))
{
plaintext.clear();
return plaintext;
}
return plaintext.left(outlen + tmplen);
}
QByteArray AESTool::encrypt(QByteArray plaintext, const QString& keyStr, const QString& ivStr)
{
QByteArray key = QCryptographicHash::hash(keyStr.toLocal8Bit(), QCryptographicHash::Sha256);
QByteArray iv = QCryptographicHash::hash(ivStr.toLocal8Bit(), QCryptographicHash::Md5);
ERR_clear_error();
// 检查密钥合法性(只能是16、24、32字节)
Q_ASSERT(key.size() == 32 );
Q_ASSERT(iv.size() == 16);
QByteArray cyphertext;
QScopedPointer <EVP_CIPHER_CTX , ScopedPointerCipherCtxDeleter> ctx(EVP_CIPHER_CTX_new());
if (!EVP_EncryptInit_ex(ctx.data(), EVP_aes_256_cbc(), NULL, (unsigned char*)key.data(), (unsigned char*)iv.data()))
{
cyphertext.clear();
return cyphertext;
}
if (!EVP_CIPHER_CTX_set_padding(ctx.data(), EVP_PADDING_PKCS7))
{
cyphertext.clear();
return cyphertext;
}
int outlen = 0;
cyphertext.resize(plaintext.size() + 16);
if (!EVP_EncryptUpdate(ctx.data(), (unsigned char *)cyphertext.data(), &outlen, (const unsigned char *)plaintext.data(), plaintext.size()))
{
cyphertext.clear();
return cyphertext;
}
int tmplen = 0;
if (!EVP_EncryptFinal_ex(ctx.data(), (unsigned char *)cyphertext.data() + outlen, &tmplen))
{
cyphertext.clear();
return cyphertext;
}
return cyphertext.left(outlen + tmplen);
}
QString AESTool::GetLastError()
{
unsigned long lastError = ERR_peek_last_error();
if (lastError == 0) {
return "";
}
char errorString[256];
ERR_error_string_n(lastError, errorString, sizeof(errorString));
return errorString;
}
main入口测试参考 有两种形式,其中一种,是用设备指纹的形式生成和读取
#include <QCoreApplication>
#include <QJsonObject>
#include <QJsonDocument>
#include <QFile>
#include <QDebug>
#include <QDir>
#include "aestool.h"
#include "wmic.h"
#define SECRET_KEY "qiuqiu"
#define SECRET_IV "yuexihuachen"
namespace FileIO {
void save(const QJsonObject& object, const QString& save_dir){
QDir dir(save_dir);
dir.mkpath(".");
QString save_path = dir.absoluteFilePath("quiqiulalala.data");
QJsonDocument doc(object);
QByteArray data = doc.toJson(QJsonDocument::Compact);
QByteArray encoded_data = AESTool::encrypt(data, SECRET_KEY, SECRET_IV);
QFile file(save_path);
if(file.open(QIODevice::WriteOnly)){
file.write(encoded_data);
file.close();
}else{
qWarning() << "写入数据失败:" << save_path;
}
}
void read(const QString& load_dir){
QDir dir(load_dir);
QString load_path = dir.absoluteFilePath("quiqiulalala.data");
QFile file(load_path);
if(file.open(QIODevice::ReadOnly)){
QByteArray encoded_data = file.readAll();
QByteArray data = AESTool::decrypt(encoded_data, SECRET_KEY, SECRET_IV);
QJsonDocument doc = QJsonDocument::fromJson(data);
QJsonObject object = doc.object();
QJsonObject debug = object.value("debug").toObject();
QJsonObject release = object.value("release").toObject();
qDebug() << "DEBUG DATA===============================================";
QJsonObject::Iterator it_debug;
for(it_debug=debug.begin();it_debug!=debug.end();++it_debug){
qDebug() << it_debug.key() << ":" << it_debug.value();
}
qDebug() << "RELEASE DATA===============================================";
QJsonObject::Iterator it_release;
for(it_release=debug.begin();it_release!=debug.end();++it_release){
qDebug() << it_release.key() << ":" << it_release.value();
}
}
}
}
namespace Qiuqiu
{
QJsonObject data()
{
int num = 123;
QJsonObject testJson_1;
testJson_1.insert("num",num);
testJson_1.insert("lalal","111");
testJson_1.insert("uuuu",12121);
QJsonObject testJson_2;
testJson_2.insert("num",num);
testJson_2.insert("lalal","111");
testJson_2.insert("uuuu",12121);
QJsonObject object;
object.insert("debug",testJson_1);
object.insert("release",testJson_2);
return object;
}
void save(){FileIO::save(data(), "lalal");}
void read(){FileIO::read("lalal");}
}
namespace FileIOWMIC
{
void save(const QJsonObject& object, const QString& save_dir){
QDir dir(save_dir);
dir.mkpath(".");
QString save_path = dir.absoluteFilePath("quiqiulalalaWMIC.data");
QJsonDocument doc(object);
QByteArray data = doc.toJson(QJsonDocument::Compact);
QByteArray encoded_data = AESTool::encrypt(data, WMIC::fingerprint(), SECRET_IV);
QFile file(save_path);
if(file.open(QIODevice::WriteOnly)){
file.write(encoded_data);
file.close();
}else{
qWarning() << "写入数据失败:" << save_path;
}
}
void read(const QString& load_dir){
QDir dir(load_dir);
QString load_path = dir.absoluteFilePath("quiqiulalalaWMIC.data");
QFile file(load_path);
if(file.open(QIODevice::ReadOnly)){
QByteArray encoded_data = file.readAll();
QByteArray data = AESTool::decrypt(encoded_data, WMIC::fingerprint(), SECRET_IV);
QJsonDocument doc = QJsonDocument::fromJson(data);
QJsonObject object = doc.object();
QJsonObject debug = object.value("debug").toObject();
QJsonObject release = object.value("release").toObject();
qDebug() << "DEBUG DATA===============================================";
QJsonObject::Iterator it_debug;
for(it_debug=debug.begin();it_debug!=debug.end();++it_debug){
qDebug() << it_debug.key() << ":" << it_debug.value();
}
qDebug() << "RELEASE DATA===============================================";
QJsonObject::Iterator it_release;
for(it_release=debug.begin();it_release!=debug.end();++it_release){
qDebug() << it_release.key() << ":" << it_release.value();
}
}
}
}
namespace WMIC
{
QJsonObject data()
{
int num = 123;
QJsonObject testJson_1;
testJson_1.insert("num",num);
testJson_1.insert("lalal","111WMIC");
testJson_1.insert("uuuu",12121);
QJsonObject testJson_2;
testJson_2.insert("num",num);
testJson_2.insert("lalal","111WMIC");
testJson_2.insert("uuuu",12121);
QJsonObject object;
object.insert("debug",testJson_1);
object.insert("release",testJson_2);
return object;
}
void save(){FileIOWMIC::save(data(), "lalal");}
void read(){FileIOWMIC::read("lalal");}
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Qiuqiu::save();
Qiuqiu::read();
WMIC::save();
WMIC::read();
}