obsidian/笔记文件/2.笔记/openssl功能整理.md
2025-03-26 00:02:56 +08:00

12 KiB
Raw Permalink Blame History

#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文件工程属性

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();
}