Skip to content

Commit

Permalink
refactor: 进一步封装
Browse files Browse the repository at this point in the history
  • Loading branch information
s12mmm3 committed Feb 26, 2024
1 parent 4945f4f commit 3bab964
Show file tree
Hide file tree
Showing 20 changed files with 344 additions and 250 deletions.
24 changes: 11 additions & 13 deletions QCloudMusicApi/util/crypto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,14 @@ extern "C" {
* @param format 输出格式
* @return QString 密文数据,如果加密失败则为空字符串
*/
QByteArray Crypto::aesEncrypt (const QByteArray &plainText, const EVP_CIPHER *mode(), const QByteArray &key, const QByteArray &iv, QString format) {
QByteArray Crypto::aesEncrypt (const QByteArray &plainText, const QString mode, const QByteArray &key, const QByteArray &iv, QString format) {
auto cipher = (mode == "cbc") ? EVP_aes_128_cbc : /*ecb*/ EVP_aes_128_ecb;
EVP_CIPHER_CTX *ctx;
int len;
unsigned char *ciphertext = new unsigned char[plainText.size() * 10];
int ciphertext_len;
if (! (ctx = EVP_CIPHER_CTX_new ())) ERR_print_errors_fp (stderr);
if (1 != EVP_EncryptInit_ex (ctx, mode (), NULL,
if (1 != EVP_EncryptInit_ex (ctx, cipher (), NULL,
(unsigned char *)key.constData(),
(unsigned char *)iv.constData()))
ERR_print_errors_fp (stderr);
Expand Down Expand Up @@ -57,8 +58,9 @@ QByteArray Crypto::aesEncrypt (const QByteArray &plainText, const EVP_CIPHER *mo
* @param iv 偏移量
* @return QString 明文数据,如果解密失败则为空字符串
*/
QByteArray Crypto::aesDecrypt(const QByteArray &cipherText, const EVP_CIPHER *mode(), const QByteArray &key, const QByteArray &iv)
QByteArray Crypto::aesDecrypt(const QByteArray &cipherText, const QString mode, const QByteArray &key, const QByteArray &iv)
{
auto cipher = (mode == "cbc") ? EVP_aes_128_cbc : /*ecb*/ EVP_aes_128_ecb;
EVP_CIPHER_CTX *ctx;

int len;
Expand All @@ -67,7 +69,7 @@ QByteArray Crypto::aesDecrypt(const QByteArray &cipherText, const EVP_CIPHER *mo

if (! (ctx = EVP_CIPHER_CTX_new ())) ERR_print_errors_fp (stderr);

if (1 != EVP_DecryptInit_ex (ctx, mode (), NULL,
if (1 != EVP_DecryptInit_ex (ctx, cipher (), NULL,
(unsigned char *)key.constData(),
(unsigned char *)iv.constData()))
ERR_print_errors_fp (stderr);
Expand Down Expand Up @@ -149,18 +151,14 @@ QVariantMap Crypto::weapi(QJsonDocument object) {
QByteArray secretKey;
secretKey.resize(16);

// 生成随机字节并映射到base62字符的ASCII码
for (int i = 0; i < secretKey.size(); i++) {
// 生成一个随机的quint32值取其最低8位作为字节值
quint8 byte = QRandomGenerator::global()->generate() & 0xFF;
// 对62取余得到base62字符的索引
int index = byte % base62.length();
// 获取base62字符并转换为ASCII码存入结果数组
secretKey[i] = base62.at(index).toLatin1();
}

auto params = aesEncrypt(aesEncrypt(text.toUtf8(), EVP_aes_128_cbc, presetKey.toUtf8().data(), iv.toUtf8().data(), "base64"),
EVP_aes_128_cbc, secretKey.data(), iv.toUtf8().data(), "base64");
auto params = aesEncrypt(aesEncrypt(text.toUtf8(), "cbc", presetKey.toUtf8().data(), iv.toUtf8().data(), "base64"),
"cbc", secretKey.data(), iv.toUtf8().data(), "base64");
std::reverse(secretKey.begin(), secretKey.end());
auto encSecKey = rsaEncrypt(secretKey, publicKey).toHex();

Expand All @@ -173,7 +171,7 @@ QVariantMap Crypto::weapi(QJsonDocument object) {
QVariantMap Crypto::linuxapi(QJsonDocument object) {
const QString text = object.toJson(QJsonDocument::Indented);
return {
{ QStringLiteral("eparams"), aesEncrypt(text.toUtf8(), EVP_aes_128_ecb, linuxapiKey.toUtf8().data(), QStringLiteral("").toUtf8().data(), "hex") }
{ QStringLiteral("eparams"), aesEncrypt(text.toUtf8(), "ecb", linuxapiKey.toUtf8().data(), QStringLiteral("").toUtf8().data(), "hex") }
};
}

Expand All @@ -191,10 +189,10 @@ QVariantMap Crypto::eapi(QString url, QJsonDocument object) {
+ QStringLiteral("-36cd479b6b5-")
+ digest;
return {
{ "params", aesEncrypt(data.toUtf8(), EVP_aes_128_ecb, eapiKey.toUtf8().data(), QStringLiteral("").toUtf8().data(), "hex") }
{ "params", aesEncrypt(data.toUtf8(), "ecb", eapiKey.toUtf8().data(), QStringLiteral("").toUtf8().data(), "hex") }
};
}

QByteArray Crypto::decrypt(QByteArray cipherBuffer) {
return aesDecrypt(cipherBuffer, EVP_aes_128_ecb, eapiKey.toUtf8().data(), "");
return aesDecrypt(cipherBuffer, "ecb", eapiKey.toUtf8().data(), "");
}
10 changes: 2 additions & 8 deletions QCloudMusicApi/util/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,6 @@
#include <QByteArray>
#include <QVariantMap>

extern "C" {
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
}

class QCLOUDMUSICAPI_EXPORT Crypto {
public:
inline const QString static iv = QStringLiteral("0102030405060708");
Expand All @@ -42,9 +36,9 @@ class QCLOUDMUSICAPI_EXPORT Crypto {
);
inline const QString static eapiKey = QStringLiteral("e82ckenh8dichen8");

static QByteArray aesEncrypt (const QByteArray &plainText, const EVP_CIPHER *mode(), const QByteArray &key, const QByteArray &iv, QString format = "base64");
static QByteArray aesEncrypt (const QByteArray &plainText, const QString mode, const QByteArray &key, const QByteArray &iv, QString format = "base64");

static QByteArray aesDecrypt(const QByteArray &cipherText, const EVP_CIPHER *mode(), const QByteArray &key, const QByteArray &iv);
static QByteArray aesDecrypt(const QByteArray &cipherText, const QString mode, const QByteArray &key, const QByteArray &iv);

static QByteArray rsaEncrypt (QString plainText, const QString& strPubKey);

Expand Down
2 changes: 1 addition & 1 deletion QCloudMusicApi/util/request.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ QVariantMap createRequest(QNetworkAccessManager::Operation method,
}
if(options["crypto"].toString() == "eapi") {
answer["body"] = QJsonDocument::fromJson(
Crypto::aesDecrypt(body, EVP_aes_128_ecb, Crypto::eapiKey.toUtf8().data(), "")
Crypto::aesDecrypt(body, "ecb", Crypto::eapiKey.toUtf8().data(), "")
).toVariant().toMap();
if(answer["body"].toMap().isEmpty()) {
answer["body"] = QJsonDocument::fromJson(body).toVariant().toMap();
Expand Down
4 changes: 3 additions & 1 deletion Test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,16 @@ FILE(GLOB HEADERS ./*.h)
FILE(GLOB SOURCES ./*.cpp)
FILE(GLOB UIS ./*.ui)
FILE(GLOB QRCS ./*.qrc)
FILE(GLOB COMMONWIDGET ./commonwidget/*)
set(PROJECT_SOURCES
${HEADERS}
${SOURCES}
${UIS}
${QRCS}
${COMMONWIDGET}
)

include_directories (./)
include_directories (./commonwidget)

if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
qt_add_executable(${PROJECT_NAME}
Expand Down
6 changes: 3 additions & 3 deletions Test/tabaes.cpp → Test/commonwidget/tabaes.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "tabaes.h"
#include "ui_tabaes.h"
#include "../QCloudMusicApi/util/crypto.h"
#include "../../QCloudMusicApi/util/crypto.h"

TabAes::TabAes(QWidget *parent) :
QWidget(parent),
Expand All @@ -17,7 +17,7 @@ TabAes::~TabAes()
void TabAes::on_pushButton_encrypt_clicked()
{
auto arg = ui->textEdit_arg->toPlainText().toUtf8();
auto mode = ui->radioButton_ecb->isChecked() ? EVP_aes_128_ecb : EVP_aes_128_cbc;
auto mode = ui->radioButton_ecb->isChecked() ? "ecb" : "cbc";
auto key = ui->lineEdit_key->text().toUtf8();
auto iv = ui->lineEdit_iv->text().toUtf8();
auto ret = Crypto::aesEncrypt(arg,
Expand All @@ -34,7 +34,7 @@ void TabAes::on_pushButton_decrypt_clicked()
auto arg = ui->radioButton_base64->isChecked()
? QByteArray::fromBase64(ui->textEdit_arg->toPlainText().toUtf8())
: QByteArray::fromHex(ui->textEdit_arg->toPlainText().toLower().toUtf8());
auto mode = ui->radioButton_ecb->isChecked() ? EVP_aes_128_ecb : EVP_aes_128_cbc;
auto mode = ui->radioButton_ecb->isChecked() ? "ecb" : "cbc";
auto key = ui->lineEdit_key->text().toUtf8();
auto iv = ui->lineEdit_iv->text().toUtf8();
auto ret = Crypto::aesDecrypt(arg, mode,
Expand Down
File renamed without changes.
File renamed without changes.
15 changes: 5 additions & 10 deletions Test/tabapitest.cpp → Test/commonwidget/tabapitest.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "tabapitest.h"
#include "ui_tabapitest.h"
#include "../QCloudMusicApi/module.h"
#include "../../QCloudMusicApi/module.h"

#include <QMutex>
#include <QJsonDocument>
Expand Down Expand Up @@ -28,8 +28,9 @@ void TabApiTest::setFunctions(QStringList functions)
ui->textEdit_arg->setText(functions.join("\n"));
}

void TabApiTest::test_send(QTextEdit* textEdit_ret, QStringList functions) {
textEdit_ret->clear();
void TabApiTest::on_pushButton_tabApiTest_send_clicked() {
QStringList functions = ui->textEdit_arg->toPlainText().split("\n");
ui->textEdit_ret->clear();
QVariantMap rets;
QMutex mutex;
auto invoke = [](const QString funName, const QVariantMap arg) {
Expand All @@ -49,12 +50,6 @@ void TabApiTest::test_send(QTextEdit* textEdit_ret, QStringList functions) {
rets[function] = QJsonDocument::fromVariant(ret).toJson(QJsonDocument::Compact);
mutex.unlock();
}).waitForFinished();
textEdit_ret->setText(QJsonDocument::fromVariant(rets).toJson(QJsonDocument::Indented));
}

void TabApiTest::on_pushButton_tabApiTest_send_clicked()
{
test_send(ui->textEdit_ret,
ui->textEdit_arg->toPlainText().split("\n"));
ui->textEdit_ret->setText(QJsonDocument::fromVariant(rets).toJson(QJsonDocument::Indented));
}

3 changes: 0 additions & 3 deletions Test/tabapitest.h → Test/commonwidget/tabapitest.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
#define TABAPITEST_H

#include <QJsonDocument>
#include <QTextEdit>
#include <QWidget>

QT_BEGIN_NAMESPACE
Expand All @@ -23,8 +22,6 @@ class TabApiTest : public QWidget
private slots:
void on_pushButton_tabApiTest_send_clicked();

void test_send(QTextEdit* textEdit_ret, QStringList functions);

private:
Ui::TabApiTest *ui;
QJsonDocument config;
Expand Down
File renamed without changes.
110 changes: 110 additions & 0 deletions Test/commonwidget/tabcommon.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#include <QMetaMethod>
#include <QTextEdit>
#include <QJsonDocument>
#include <QJsonObject>
#include <QFile>
#include <QDebug>
#include <QtConcurrent>

#include "tabcommon.h"
#include "ui_tabcommon.h"


#include "../../QCloudMusicApi/module.h"
#include "../../QCloudMusicApi/util/index.h"

TabCommon::TabCommon(QWidget *parent) :
QWidget(parent),
ui(new Ui::TabCommon)
{
ui->setupUi(this);
//将Api中的方法名称取出
NeteaseCloudMusicApi api;
for(int i = QObject().metaObject()->methodCount(); i < api.metaObject()->methodCount(); i++) {
ui->comboBox->addItem(api.metaObject()->method(i).name());
}

//读取配置
QFile file(":/config.json");
file.open(QIODevice::ReadOnly);
config = QJsonDocument::fromJson(file.readAll());
}

TabCommon::~TabCommon()
{
delete ui;
}

void TabCommon::updateCookie(const QVariantMap ret) {
auto newCookie = Index::stringToMap(ret["cookie"].toString());
if (!newCookie.isEmpty()) {
cookie = Index::mergeMap(cookie, newCookie);
}
auto token = ret["body"].toMap()["token"].toString();
if (!token.isEmpty()) {
cookie["MUSIC_A"] = token;
}
}

QVariantMap TabCommon::invoke(const QString funName, const QVariantMap arg) {
NeteaseCloudMusicApi api;
QVariantMap ret;
QMetaObject::invokeMethod(&api, funName.toUtf8()
, Qt::DirectConnection
, Q_RETURN_ARG(QVariantMap, ret)
, Q_ARG(QVariantMap, arg));
return ret;
}

void TabCommon::on_pushButton_send_clicked()
{
ui->textEdit_ret->clear();

auto JsonFormat = ui->checkBox->isChecked() ? QJsonDocument::Indented : QJsonDocument::Compact;
ui->textEdit_arg->setText(QJsonDocument::fromJson(ui->textEdit_arg->toPlainText().toUtf8()).toJson(JsonFormat));

QVariantMap arg = QJsonDocument::fromJson(ui->textEdit_arg->toPlainText().toUtf8()).toVariant().toMap();

//Api只能处理map类型的cookie
if(arg.contains("cookie")) {
//如果传入新的cookie,替换原有的cookie
if(arg["cookie"].userType() == QMetaType::QVariantMap) {
cookie = arg["cookie"].toMap()/* + " SameSite=None; Secure"*/;
}
else if(arg["cookie"].userType() == QMetaType::QString) {
cookie = Index::stringToMap(arg["cookie"].toString());
}
}
else {
//使用存储的cookie
arg["cookie"] = arg.value("cookie", cookie);
}

QVariantMap ret = this->invoke(ui->comboBox->currentText(), arg);

this->updateCookie(ret);

if(ui->checkBox->isChecked()) {
ui->textEdit_ret->setText(QJsonDocument::fromVariant(ret).toJson(QJsonDocument::Indented));
}
else {
ui->textEdit_ret->setText(QJsonDocument::fromVariant(ret).toJson(QJsonDocument::Compact));
}
}


void TabCommon::on_comboBox_currentTextChanged(const QString &arg1)
{
auto JsonFormat = ui->checkBox->isChecked() ? QJsonDocument::Indented : QJsonDocument::Compact;
ui->textEdit_arg->setText(
QJsonDocument(config[arg1].toObject())
.toJson(JsonFormat)
);
}


void TabCommon::on_checkBox_stateChanged(int arg1)
{
auto JsonFormat = arg1 ? QJsonDocument::Indented : QJsonDocument::Compact;
ui->textEdit_ret->setText(QJsonDocument::fromJson(ui->textEdit_ret->toPlainText().toUtf8()).toJson(JsonFormat));
}
52 changes: 52 additions & 0 deletions Test/commonwidget/tabcommon.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#ifndef TABCOMMON_H
#define TABCOMMON_H

#include <QWidget>
#include <QJsonDocument>
#include <QVariantMap>

QT_BEGIN_NAMESPACE
namespace Ui {
class TabCommon;
}
QT_END_NAMESPACE

class TabCommon : public QWidget
{
Q_OBJECT

public:
explicit TabCommon(QWidget *parent = nullptr);
~TabCommon();

private slots:
void on_pushButton_send_clicked();

void on_comboBox_currentTextChanged(const QString &arg1);

void on_checkBox_stateChanged(int arg1);

private:

/**
* @brief 反射调用API中的方法
* @param funName 函数名称
* @param arg 参数
* @return QVariantMap 返回的数据
*/
QVariantMap invoke(const QString funName, const QVariantMap arg);

/**
* @brief 更新储存的cookie
* @param ret Api返回的数据
* @return void
*/
void updateCookie(const QVariantMap ret);

private:
Ui::TabCommon *ui;
QVariantMap cookie;
QJsonDocument config;
};

#endif // TABCOMMON_H
Loading

0 comments on commit 3bab964

Please sign in to comment.