#qt 新建测试工程 Dialog,默认mingw编译方式即可 解压开源方案到工程目录后 ![[Pasted image 20240706175742.png]] 需要把openssl文件夹,从include里拿出来,否则 后续 引用异常 ![[Pasted image 20240706181221.png]] bin文件夹里面的,是aes的可执行dll文件,后续如果要使用,也直接复制粘贴即可 ![[Pasted image 20240706181552.png]] 创建一下,windows获取硬件属性相关的逻辑,wmic,参考[[WMIC功能整理]]即可 再创建一下AESTool,用来引用相关的库 pro文件,工程属性 ``` cpp 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对应逻辑参考 头文件 ``` cpp #ifndef AESTOOL_H #define AESTOOL_H //#include //namespace AESTool { //QByteArray encrypt(const QByteArray& byteArray, const QByteArray& key); //QByteArray decrypt(const QByteArray& byteArray, const QByteArray& key); //} #include #include #include #include #include #include #include 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 ``` cpp #include "aestool.h" #include //#include //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(key.constData()), nullptr); // EVP_EncryptUpdate(ctx, reinterpret_cast(buffer.data()), &outLen1, reinterpret_cast(data.constData()), data.size()); // EVP_EncryptFinal_ex(ctx, reinterpret_cast(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(key.constData()), nullptr); // EVP_DecryptUpdate(ctx, reinterpret_cast(buffer.data()), &outLen1, reinterpret_cast(data.constData()), data.size()); // EVP_DecryptFinal_ex(ctx, reinterpret_cast(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 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 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入口测试参考 有两种形式,其中一种,是用设备指纹的形式生成和读取 ``` cpp #include #include #include #include #include #include #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(); } ```