diff --git a/.drone.yml b/.drone.yml index 72763ef..dd4d4ef 100644 --- a/.drone.yml +++ b/.drone.yml @@ -4,11 +4,6 @@ type: docker name: default steps: - - name: build-wasm - image: emscripten/emsdk:3.0.0 - commands: - - ./scripts/build-wasm.sh - - name: build image: node:16.18-bullseye commands: diff --git a/package-lock.json b/package-lock.json index 80e2a66..26ab988 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,18 +1,19 @@ { "name": "unlock-music", - "version": "v1.10.3", + "version": "1.10.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "unlock-music", - "version": "v1.10.3", + "version": "1.10.4", "hasInstallScript": true, "license": "MIT", "dependencies": { "@babel/preset-typescript": "^7.16.5", - "@jixun/kugou-crypto": "^1.0.3", "@unlock-music/joox-crypto": "^0.0.1-R5", + "@xhacker/kgmwasm": "^1.0.0", + "@xhacker/qmcwasm": "^1.0.0", "base64-js": "^1.5.1", "browser-id3-writer": "^4.4.0", "core-js": "^3.16.0", @@ -2986,22 +2987,6 @@ "regenerator-runtime": "^0.13.3" } }, - "node_modules/@jixun/kugou-crypto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@jixun/kugou-crypto/-/kugou-crypto-1.0.3.tgz", - "integrity": "sha512-ZiwSkpIAH8IkFcTfMjdQMpP/xco3iXEdYDEQo4wquYpSAln5RmSed3iBctnpoE6s3X1cxmBGhpCYW6v6vZfs+g==", - "dependencies": { - "commander": "^9.2.0" - } - }, - "node_modules/@jixun/kugou-crypto/node_modules/commander": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.2.0.tgz", - "integrity": "sha512-e2i4wANQiSXgnrBlIatyHtP1odfUp0BbV5Y5nEGbxtIrStkEOAAzCUirvLBNXHLr7kwLvJl6V+4V3XV9x7Wd9w==", - "engines": { - "node": "^12.20.0 || >=14" - } - }, "node_modules/@mrmlnc/readdir-enhanced": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", @@ -4197,6 +4182,16 @@ "@xtuc/long": "4.2.2" } }, + "node_modules/@xhacker/kgmwasm": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@xhacker/kgmwasm/-/kgmwasm-1.0.0.tgz", + "integrity": "sha512-LnBuEVRJQVyJGJTb0cPZxZDu7Qi4PqDhJLRaRJfG6pSUeZuIoglzHiysyd4XfNHobNnLxG8v1IiNPS/uWwoG0A==" + }, + "node_modules/@xhacker/qmcwasm": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@xhacker/qmcwasm/-/qmcwasm-1.0.0.tgz", + "integrity": "sha512-oE6isNLmCDqIvxJV9KyDVlIzMISQzTj8o1ePWtQ+DhfXLI0hel/DwOIQ3icCikWnfwA/5SDs2hYw5BvrxdJ63g==" + }, "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -23195,21 +23190,6 @@ "regenerator-runtime": "^0.13.3" } }, - "@jixun/kugou-crypto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@jixun/kugou-crypto/-/kugou-crypto-1.0.3.tgz", - "integrity": "sha512-ZiwSkpIAH8IkFcTfMjdQMpP/xco3iXEdYDEQo4wquYpSAln5RmSed3iBctnpoE6s3X1cxmBGhpCYW6v6vZfs+g==", - "requires": { - "commander": "^9.2.0" - }, - "dependencies": { - "commander": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.2.0.tgz", - "integrity": "sha512-e2i4wANQiSXgnrBlIatyHtP1odfUp0BbV5Y5nEGbxtIrStkEOAAzCUirvLBNXHLr7kwLvJl6V+4V3XV9x7Wd9w==" - } - } - }, "@mrmlnc/readdir-enhanced": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", @@ -24256,6 +24236,16 @@ "@xtuc/long": "4.2.2" } }, + "@xhacker/kgmwasm": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@xhacker/kgmwasm/-/kgmwasm-1.0.0.tgz", + "integrity": "sha512-LnBuEVRJQVyJGJTb0cPZxZDu7Qi4PqDhJLRaRJfG6pSUeZuIoglzHiysyd4XfNHobNnLxG8v1IiNPS/uWwoG0A==" + }, + "@xhacker/qmcwasm": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@xhacker/qmcwasm/-/qmcwasm-1.0.0.tgz", + "integrity": "sha512-oE6isNLmCDqIvxJV9KyDVlIzMISQzTj8o1ePWtQ+DhfXLI0hel/DwOIQ3icCikWnfwA/5SDs2hYw5BvrxdJ63g==" + }, "@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", diff --git a/package.json b/package.json index 8373728..fc70d97 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "unlock-music", - "version": "1.10.3", + "version": "1.10.4", "ext_build": 0, "updateInfo": "完善音乐标签编辑功能,支持编辑更多标签", "license": "MIT", @@ -21,8 +21,9 @@ }, "dependencies": { "@babel/preset-typescript": "^7.16.5", - "@jixun/kugou-crypto": "^1.0.3", "@unlock-music/joox-crypto": "^0.0.1-R5", + "@xhacker/kgmwasm": "^1.0.0", + "@xhacker/qmcwasm": "^1.0.0", "base64-js": "^1.5.1", "browser-id3-writer": "^4.4.0", "core-js": "^3.16.0", @@ -56,4 +57,4 @@ "vue-cli-plugin-element": "^1.0.1", "vue-template-compiler": "^2.6.14" } -} \ No newline at end of file +} diff --git a/scripts/build-wasm.sh b/scripts/build-wasm.sh deleted file mode 100755 index f0d7922..0000000 --- a/scripts/build-wasm.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash - -set -ex - -cd "$(git rev-parse --show-toplevel)" - -pushd ./src/QmcWasm -bash build-wasm -popd - -pushd ./src/KgmWasm -bash build-wasm -popd diff --git a/src/KgmWasm/CMakeLists.txt b/src/KgmWasm/CMakeLists.txt deleted file mode 100644 index 1014b3b..0000000 --- a/src/KgmWasm/CMakeLists.txt +++ /dev/null @@ -1,65 +0,0 @@ -# CMakeList.txt : CMake project for KgmWasm, include source and define -# project specific logic here. -# -cmake_minimum_required (VERSION 3.8) - -project ("KgmWasm") - -set(CMAKE_CXX_STANDARD 14) - -include_directories( - $ -) - -# Add source to this project's executable. -set(RUNTIME_METHODS_LIST - getValue - writeArrayToMemory - UTF8ToString -) -list(JOIN RUNTIME_METHODS_LIST "," RUNTIME_METHODS) - -set(EMSCRIPTEN_FLAGS - "--bind" - "-s NO_DYNAMIC_EXECUTION=1" - "-s MODULARIZE=1" - "-s EXPORT_NAME=KgmCryptoModule" - "-s EXPORTED_RUNTIME_METHODS=${RUNTIME_METHODS}" -) -set(EMSCRIPTEN_LEGACY_FLAGS - ${EMSCRIPTEN_FLAGS} - "-s WASM=0" - "--memory-init-file 0" -) -set(EMSCRIPTEN_WASM_BUNDLE_FLAGS - ${EMSCRIPTEN_FLAGS} - "-s SINGLE_FILE=1" -) - -list(JOIN EMSCRIPTEN_FLAGS " " EMSCRIPTEN_FLAGS_STR) -list(JOIN EMSCRIPTEN_LEGACY_FLAGS " " EMSCRIPTEN_LEGACY_FLAGS_STR) -list(JOIN EMSCRIPTEN_WASM_BUNDLE_FLAGS " " EMSCRIPTEN_WASM_BUNDLE_FLAGS_STR) - -# Define projects config -set(WASM_SOURCES - "KgmWasm.cpp" -) - -add_executable(KgmWasm ${WASM_SOURCES}) -set_target_properties( - KgmWasm - PROPERTIES LINK_FLAGS ${EMSCRIPTEN_FLAGS_STR} -) - -add_executable(KgmWasmBundle ${WASM_SOURCES}) -set_target_properties( - KgmWasmBundle - PROPERTIES LINK_FLAGS ${EMSCRIPTEN_WASM_BUNDLE_FLAGS_STR} -) - -add_executable(KgmLegacy ${WASM_SOURCES}) -set_target_properties( - KgmLegacy - PROPERTIES LINK_FLAGS ${EMSCRIPTEN_LEGACY_FLAGS_STR} -) - diff --git a/src/KgmWasm/KgmWasm.cpp b/src/KgmWasm/KgmWasm.cpp deleted file mode 100644 index 7901fed..0000000 --- a/src/KgmWasm/KgmWasm.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// KgmWasm.cpp : Defines the entry point for the application. -// - -#include "KgmWasm.h" - -#include "kgm.hpp" - -#include -#include - -size_t preDec(uintptr_t blob, size_t blobSize, std::string ext) -{ - return PreDec((uint8_t*)blob, blobSize, ext == "vpr"); -} - -void decBlob(uintptr_t blob, size_t blobSize, size_t offset) -{ - Decrypt((uint8_t*)blob, blobSize, offset); - return; -} diff --git a/src/KgmWasm/KgmWasm.h b/src/KgmWasm/KgmWasm.h deleted file mode 100644 index 0b1d7eb..0000000 --- a/src/KgmWasm/KgmWasm.h +++ /dev/null @@ -1,18 +0,0 @@ -// KgmWasm.h : Include file for standard system include files, -// or project specific include files. - -#pragma once - -#include -#include - -namespace em = emscripten; - -size_t preDec(uintptr_t blob, size_t blobSize, std::string ext); -void decBlob(uintptr_t blob, size_t blobSize, size_t offset); - -EMSCRIPTEN_BINDINGS(QmcCrypto) -{ - em::function("preDec", &preDec, em::allow_raw_pointers()); - em::function("decBlob", &decBlob, em::allow_raw_pointers()); -} diff --git a/src/KgmWasm/README.md b/src/KgmWasm/README.md deleted file mode 100644 index 0ad5092..0000000 --- a/src/KgmWasm/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# KgmWasm - -## 构建 - -在 Linux 环境下执行 `bash build-wasm` 即可构建。 - -## Build - -Linux environment required. Build wasm binary by execute `bash build-wasm`. diff --git a/src/KgmWasm/build-wasm b/src/KgmWasm/build-wasm deleted file mode 100755 index 599b97c..0000000 --- a/src/KgmWasm/build-wasm +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env bash - -set -e - -pushd "$(realpath "$(dirname "$0")")" - -CURR_DIR="${PWD}" - -BUILD_TYPE="$1" -if [ -z "$BUILD_TYPE" ]; then - BUILD_TYPE=Release -fi - -# CI: already had emsdk installed. -if ! command -v emcc; then - if [ ! -d ../../build/emsdk ]; then - git clone https://github.com/emscripten-core/emsdk.git ../../build/emsdk - fi - - pushd ../../build/emsdk - ./emsdk install 3.0.0 - ./emsdk activate 3.0.0 - source ./emsdk_env.sh - popd # ../../build/emsdk -fi - -mkdir -p build/wasm -pushd build/wasm -emcmake cmake -DCMAKE_BUILD_TYPE="$BUILD_TYPE" ../.. -make -j -TARGET_FILES=" - KgmLegacy.js - KgmWasm.js - KgmWasm.wasm - KgmWasmBundle.js -" - -cp $TARGET_FILES "${CURR_DIR}/" -popd # build/wasm - -popd diff --git a/src/KgmWasm/kgm.hpp b/src/KgmWasm/kgm.hpp deleted file mode 100644 index b3493e5..0000000 --- a/src/KgmWasm/kgm.hpp +++ /dev/null @@ -1,112 +0,0 @@ -#include - -std::vector VprHeader = { - 0x05, 0x28, 0xBC, 0x96, 0xE9, 0xE4, 0x5A, 0x43, - 0x91, 0xAA, 0xBD, 0xD0, 0x7A, 0xF5, 0x36, 0x31 }; -std::vector KgmHeader = { - 0x7C, 0xD5, 0x32, 0xEB, 0x86, 0x02, 0x7F, 0x4B, - 0xA8, 0xAF, 0xA6, 0x8E, 0x0F, 0xFF, 0x99, 0x14 }; -std::vector VprMaskDiff = { - 0x25, 0xDF, 0xE8, 0xA6, 0x75, 0x1E, 0x75, 0x0E, - 0x2F, 0x80, 0xF3, 0x2D, 0xB8, 0xB6, 0xE3, 0x11, 0x00 }; - -std::vector MaskV2; - -std::vector table1 = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x21, 0x01, 0x61, 0x01, 0x21, 0x01, 0xe1, 0x01, 0x21, 0x01, 0x61, 0x01, 0x21, 0x01, - 0xd2, 0x23, 0x02, 0x02, 0x42, 0x42, 0x02, 0x02, 0xc2, 0xc2, 0x02, 0x02, 0x42, 0x42, 0x02, 0x02, - 0xd3, 0xd3, 0x02, 0x03, 0x63, 0x43, 0x63, 0x03, 0xe3, 0xc3, 0xe3, 0x03, 0x63, 0x43, 0x63, 0x03, - 0x94, 0xb4, 0x94, 0x65, 0x04, 0x04, 0x04, 0x04, 0x84, 0x84, 0x84, 0x84, 0x04, 0x04, 0x04, 0x04, - 0x95, 0x95, 0x95, 0x95, 0x04, 0x05, 0x25, 0x05, 0xe5, 0x85, 0xa5, 0x85, 0xe5, 0x05, 0x25, 0x05, - 0xd6, 0xb6, 0x96, 0xb6, 0xd6, 0x27, 0x06, 0x06, 0xc6, 0xc6, 0x86, 0x86, 0xc6, 0xc6, 0x06, 0x06, - 0xd7, 0xd7, 0x97, 0x97, 0xd7, 0xd7, 0x06, 0x07, 0xe7, 0xc7, 0xe7, 0x87, 0xe7, 0xc7, 0xe7, 0x07, - 0x18, 0x38, 0x18, 0x78, 0x18, 0x38, 0x18, 0xe9, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x08, 0x09, 0x29, 0x09, 0x69, 0x09, 0x29, 0x09, - 0xda, 0x3a, 0x1a, 0x3a, 0x5a, 0x3a, 0x1a, 0x3a, 0xda, 0x2b, 0x0a, 0x0a, 0x4a, 0x4a, 0x0a, 0x0a, - 0xdb, 0xdb, 0x1b, 0x1b, 0x5b, 0x5b, 0x1b, 0x1b, 0xdb, 0xdb, 0x0a, 0x0b, 0x6b, 0x4b, 0x6b, 0x0b, - 0x9c, 0xbc, 0x9c, 0x7c, 0x1c, 0x3c, 0x1c, 0x7c, 0x9c, 0xbc, 0x9c, 0x6d, 0x0c, 0x0c, 0x0c, 0x0c, - 0x9d, 0x9d, 0x9d, 0x9d, 0x1d, 0x1d, 0x1d, 0x1d, 0x9d, 0x9d, 0x9d, 0x9d, 0x0c, 0x0d, 0x2d, 0x0d, - 0xde, 0xbe, 0x9e, 0xbe, 0xde, 0x3e, 0x1e, 0x3e, 0xde, 0xbe, 0x9e, 0xbe, 0xde, 0x2f, 0x0e, 0x0e, - 0xdf, 0xdf, 0x9f, 0x9f, 0xdf, 0xdf, 0x1f, 0x1f, 0xdf, 0xdf, 0x9f, 0x9f, 0xdf, 0xdf, 0x0e, 0x0f, - 0x00, 0x20, 0x00, 0x60, 0x00, 0x20, 0x00, 0xe0, 0x00, 0x20, 0x00, 0x60, 0x00, 0x20, 0x00, 0xf1 -}; - -std::vector table2 = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x23, 0x01, 0x67, 0x01, 0x23, 0x01, 0xef, 0x01, 0x23, 0x01, 0x67, 0x01, 0x23, 0x01, - 0xdf, 0x21, 0x02, 0x02, 0x46, 0x46, 0x02, 0x02, 0xce, 0xce, 0x02, 0x02, 0x46, 0x46, 0x02, 0x02, - 0xde, 0xde, 0x02, 0x03, 0x65, 0x47, 0x65, 0x03, 0xed, 0xcf, 0xed, 0x03, 0x65, 0x47, 0x65, 0x03, - 0x9d, 0xbf, 0x9d, 0x63, 0x04, 0x04, 0x04, 0x04, 0x8c, 0x8c, 0x8c, 0x8c, 0x04, 0x04, 0x04, 0x04, - 0x9c, 0x9c, 0x9c, 0x9c, 0x04, 0x05, 0x27, 0x05, 0xeb, 0x8d, 0xaf, 0x8d, 0xeb, 0x05, 0x27, 0x05, - 0xdb, 0xbd, 0x9f, 0xbd, 0xdb, 0x25, 0x06, 0x06, 0xca, 0xca, 0x8e, 0x8e, 0xca, 0xca, 0x06, 0x06, - 0xda, 0xda, 0x9e, 0x9e, 0xda, 0xda, 0x06, 0x07, 0xe9, 0xcb, 0xe9, 0x8f, 0xe9, 0xcb, 0xe9, 0x07, - 0x19, 0x3b, 0x19, 0x7f, 0x19, 0x3b, 0x19, 0xe7, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x08, 0x09, 0x2b, 0x09, 0x6f, 0x09, 0x2b, 0x09, - 0xd7, 0x39, 0x1b, 0x39, 0x5f, 0x39, 0x1b, 0x39, 0xd7, 0x29, 0x0a, 0x0a, 0x4e, 0x4e, 0x0a, 0x0a, - 0xd6, 0xd6, 0x1a, 0x1a, 0x5e, 0x5e, 0x1a, 0x1a, 0xd6, 0xd6, 0x0a, 0x0b, 0x6d, 0x4f, 0x6d, 0x0b, - 0x95, 0xb7, 0x95, 0x7b, 0x1d, 0x3f, 0x1d, 0x7b, 0x95, 0xb7, 0x95, 0x6b, 0x0c, 0x0c, 0x0c, 0x0c, - 0x94, 0x94, 0x94, 0x94, 0x1c, 0x1c, 0x1c, 0x1c, 0x94, 0x94, 0x94, 0x94, 0x0c, 0x0d, 0x2f, 0x0d, - 0xd3, 0xb5, 0x97, 0xb5, 0xd3, 0x3d, 0x1f, 0x3d, 0xd3, 0xb5, 0x97, 0xb5, 0xd3, 0x2d, 0x0e, 0x0e, - 0xd2, 0xd2, 0x96, 0x96, 0xd2, 0xd2, 0x1e, 0x1e, 0xd2, 0xd2, 0x96, 0x96, 0xd2, 0xd2, 0x0e, 0x0f, - 0x00, 0x22, 0x00, 0x66, 0x00, 0x22, 0x00, 0xee, 0x00, 0x22, 0x00, 0x66, 0x00, 0x22, 0x00, 0xfe -}; - -std::vector MaskV2PreDef = { - 0xB8, 0xD5, 0x3D, 0xB2, 0xE9, 0xAF, 0x78, 0x8C, 0x83, 0x33, 0x71, 0x51, 0x76, 0xA0, 0xCD, 0x37, - 0x2F, 0x3E, 0x35, 0x8D, 0xA9, 0xBE, 0x98, 0xB7, 0xE7, 0x8C, 0x22, 0xCE, 0x5A, 0x61, 0xDF, 0x68, - 0x69, 0x89, 0xFE, 0xA5, 0xB6, 0xDE, 0xA9, 0x77, 0xFC, 0xC8, 0xBD, 0xBD, 0xE5, 0x6D, 0x3E, 0x5A, - 0x36, 0xEF, 0x69, 0x4E, 0xBE, 0xE1, 0xE9, 0x66, 0x1C, 0xF3, 0xD9, 0x02, 0xB6, 0xF2, 0x12, 0x9B, - 0x44, 0xD0, 0x6F, 0xB9, 0x35, 0x89, 0xB6, 0x46, 0x6D, 0x73, 0x82, 0x06, 0x69, 0xC1, 0xED, 0xD7, - 0x85, 0xC2, 0x30, 0xDF, 0xA2, 0x62, 0xBE, 0x79, 0x2D, 0x62, 0x62, 0x3D, 0x0D, 0x7E, 0xBE, 0x48, - 0x89, 0x23, 0x02, 0xA0, 0xE4, 0xD5, 0x75, 0x51, 0x32, 0x02, 0x53, 0xFD, 0x16, 0x3A, 0x21, 0x3B, - 0x16, 0x0F, 0xC3, 0xB2, 0xBB, 0xB3, 0xE2, 0xBA, 0x3A, 0x3D, 0x13, 0xEC, 0xF6, 0x01, 0x45, 0x84, - 0xA5, 0x70, 0x0F, 0x93, 0x49, 0x0C, 0x64, 0xCD, 0x31, 0xD5, 0xCC, 0x4C, 0x07, 0x01, 0x9E, 0x00, - 0x1A, 0x23, 0x90, 0xBF, 0x88, 0x1E, 0x3B, 0xAB, 0xA6, 0x3E, 0xC4, 0x73, 0x47, 0x10, 0x7E, 0x3B, - 0x5E, 0xBC, 0xE3, 0x00, 0x84, 0xFF, 0x09, 0xD4, 0xE0, 0x89, 0x0F, 0x5B, 0x58, 0x70, 0x4F, 0xFB, - 0x65, 0xD8, 0x5C, 0x53, 0x1B, 0xD3, 0xC8, 0xC6, 0xBF, 0xEF, 0x98, 0xB0, 0x50, 0x4F, 0x0F, 0xEA, - 0xE5, 0x83, 0x58, 0x8C, 0x28, 0x2C, 0x84, 0x67, 0xCD, 0xD0, 0x9E, 0x47, 0xDB, 0x27, 0x50, 0xCA, - 0xF4, 0x63, 0x63, 0xE8, 0x97, 0x7F, 0x1B, 0x4B, 0x0C, 0xC2, 0xC1, 0x21, 0x4C, 0xCC, 0x58, 0xF5, - 0x94, 0x52, 0xA3, 0xF3, 0xD3, 0xE0, 0x68, 0xF4, 0x00, 0x23, 0xF3, 0x5E, 0x0A, 0x7B, 0x93, 0xDD, - 0xAB, 0x12, 0xB2, 0x13, 0xE8, 0x84, 0xD7, 0xA7, 0x9F, 0x0F, 0x32, 0x4C, 0x55, 0x1D, 0x04, 0x36, - 0x52, 0xDC, 0x03, 0xF3, 0xF9, 0x4E, 0x42, 0xE9, 0x3D, 0x61, 0xEF, 0x7C, 0xB6, 0xB3, 0x93, 0x50, -}; - -uint8_t getMask(size_t pos) { - size_t offset = pos >> 4; - uint8_t value = 0; - while (offset >= 0x11) { - value ^= table1[offset % 272]; - offset >>= 4; - value ^= table2[offset % 272]; - offset >>= 4; - } - - return MaskV2PreDef[pos % 272] ^ value; -} - -std::vector key(17); -bool isVpr = false; - -size_t PreDec(uint8_t* fileData, size_t size, bool iV) { - uint32_t headerLen = *(uint32_t*)(fileData + 0x10); - memcpy(key.data(), (fileData + 0x1C), 0x10); - key[16] = 0; - isVpr = iV; - return headerLen; -} - -void Decrypt(uint8_t* fileData, size_t size, size_t offset) { - for (size_t i = 0; i < size; ++i) { - uint8_t med8 = key[(i + offset) % 17] ^ fileData[i]; - med8 ^= (med8 & 0xf) << 4; - - uint8_t msk8 = getMask(i + offset); - msk8 ^= (msk8 & 0xf) << 4; - fileData[i] = med8 ^ msk8; - - if (isVpr) { - fileData[i] ^= VprMaskDiff[(i + offset) % 17]; - } - } -} diff --git a/src/QmcWasm/CMakeLists.txt b/src/QmcWasm/CMakeLists.txt deleted file mode 100644 index 066268a..0000000 --- a/src/QmcWasm/CMakeLists.txt +++ /dev/null @@ -1,65 +0,0 @@ -# CMakeList.txt : CMake project for QmcWasm, include source and define -# project specific logic here. -# -cmake_minimum_required (VERSION 3.8) - -project ("QmcWasm") - -set(CMAKE_CXX_STANDARD 14) - -include_directories( - $ -) - -# Add source to this project's executable. -set(RUNTIME_METHODS_LIST - getValue - writeArrayToMemory - UTF8ToString -) -list(JOIN RUNTIME_METHODS_LIST "," RUNTIME_METHODS) - -set(EMSCRIPTEN_FLAGS - "--bind" - "-s NO_DYNAMIC_EXECUTION=1" - "-s MODULARIZE=1" - "-s EXPORT_NAME=QmcCryptoModule" - "-s EXPORTED_RUNTIME_METHODS=${RUNTIME_METHODS}" -) -set(EMSCRIPTEN_LEGACY_FLAGS - ${EMSCRIPTEN_FLAGS} - "-s WASM=0" - "--memory-init-file 0" -) -set(EMSCRIPTEN_WASM_BUNDLE_FLAGS - ${EMSCRIPTEN_FLAGS} - "-s SINGLE_FILE=1" -) - -list(JOIN EMSCRIPTEN_FLAGS " " EMSCRIPTEN_FLAGS_STR) -list(JOIN EMSCRIPTEN_LEGACY_FLAGS " " EMSCRIPTEN_LEGACY_FLAGS_STR) -list(JOIN EMSCRIPTEN_WASM_BUNDLE_FLAGS " " EMSCRIPTEN_WASM_BUNDLE_FLAGS_STR) - -# Define projects config -set(WASM_SOURCES - "QmcWasm.cpp" -) - -add_executable(QmcWasm ${WASM_SOURCES}) -set_target_properties( - QmcWasm - PROPERTIES LINK_FLAGS ${EMSCRIPTEN_FLAGS_STR} -) - -add_executable(QmcWasmBundle ${WASM_SOURCES}) -set_target_properties( - QmcWasmBundle - PROPERTIES LINK_FLAGS ${EMSCRIPTEN_WASM_BUNDLE_FLAGS_STR} -) - -add_executable(QmcLegacy ${WASM_SOURCES}) -set_target_properties( - QmcLegacy - PROPERTIES LINK_FLAGS ${EMSCRIPTEN_LEGACY_FLAGS_STR} -) - diff --git a/src/QmcWasm/QmcWasm.cpp b/src/QmcWasm/QmcWasm.cpp deleted file mode 100644 index f4fc8c0..0000000 --- a/src/QmcWasm/QmcWasm.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// QmcWasm.cpp : Defines the entry point for the application. -// - -#include "QmcWasm.h" - -#include "qmc.hpp" - -#include -#include - -std::string err = ""; -std::string sid = ""; -QmcDecode e; - -int preDec(uintptr_t blob, size_t blobSize, std::string ext) -{ - if (!e.SetBlob((uint8_t*)blob, blobSize)) - { - err = "cannot allocate memory"; - return -1; - } - int tailSize = e.PreDecode(ext); - if (e.error != "") - { - err = e.error; - return -1; - } - sid = e.songId; - return tailSize; -} - -size_t decBlob(uintptr_t blob, size_t blobSize, size_t offset) -{ - if (!e.SetBlob((uint8_t*)blob, blobSize)) - { - err = "cannot allocate memory"; - return 0; - } - std::vector decData = e.Decode(offset); - if (e.error != "") - { - err = e.error; - return 0; - } - memcpy((uint8_t*)blob, decData.data(), decData.size()); - return decData.size(); -} - -std::string getErr() -{ - return err; -} - -std::string getSongId() -{ - return sid; -} diff --git a/src/QmcWasm/QmcWasm.h b/src/QmcWasm/QmcWasm.h deleted file mode 100644 index 6fd63bf..0000000 --- a/src/QmcWasm/QmcWasm.h +++ /dev/null @@ -1,23 +0,0 @@ -// QmcWasm.h : Include file for standard system include files, -// or project specific include files. - -#pragma once - -#include -#include - -namespace em = emscripten; - -int preDec(uintptr_t blob, size_t blobSize, std::string ext); -size_t decBlob(uintptr_t blob, size_t blobSize, size_t offset); -std::string getErr(); -std::string getSongId(); - -EMSCRIPTEN_BINDINGS(QmcCrypto) -{ - em::function("getErr", &getErr); - em::function("getSongId", &getSongId); - - em::function("preDec", &preDec, em::allow_raw_pointers()); - em::function("decBlob", &decBlob, em::allow_raw_pointers()); -} diff --git a/src/QmcWasm/README.md b/src/QmcWasm/README.md deleted file mode 100644 index 035fe65..0000000 --- a/src/QmcWasm/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# QmcWasm - -## 构建 - -在 Linux 环境下执行 `bash build-wasm` 即可构建。 - -## Build - -Linux environment required. Build wasm binary by execute `bash build-wasm`. diff --git a/src/QmcWasm/TencentTea.hpp b/src/QmcWasm/TencentTea.hpp deleted file mode 100644 index 4f635a7..0000000 --- a/src/QmcWasm/TencentTea.hpp +++ /dev/null @@ -1,289 +0,0 @@ -#ifndef QQMUSIC_CPP_TENCENTTEA_HPP -#define QQMUSIC_CPP_TENCENTTEA_HPP - -#include -#include -#include -#include -#include -#include - -const uint32_t DELTA = 0x9e3779b9; - -#define ROUNDS 32 -#define SALT_LEN 2 -#define ZERO_LEN 7 - -void TeaDecryptECB(uint8_t* src, uint8_t* dst, std::vector key, size_t rounds = ROUNDS) { - if (key.size() != 16 || (rounds & 1) != 0) - { - return; - } - uint32_t y, z, sum; - uint32_t k[4]; - int i; - - //now encrypted buf is TCP/IP-endian; - //TCP/IP network byte order (which is big-endian). - y = ntohl(*((uint32_t*)src)); - z = ntohl(*((uint32_t*)(src + 4))); - //std::cout << ntohl(0x0a3aea41); - - for (i = 0; i < 4; i++) { - //key is TCP/IP-endian; - k[i] = ntohl(*((uint32_t*)(key.data() + i * 4))); - } - - sum = (DELTA * rounds); - for (i = 0; i < rounds; i++) { - z -= ((y << 4) + k[2]) ^ (y + sum) ^ ((y >> 5) + k[3]); - y -= ((z << 4) + k[0]) ^ (z + sum) ^ ((z >> 5) + k[1]); - sum -= DELTA; - } - - *((uint32_t*)dst) = ntohl(y); - *((uint32_t*)(dst + 4)) = ntohl(z); - - //now plain-text is TCP/IP-endian; -} - -void TeaEncryptECB(uint8_t* src, uint8_t* dst, std::vector key, size_t rounds = ROUNDS) { - if (key.size() != 16 || (rounds & 1) != 0) - { - return; - } - uint32_t y, z, sum; - uint32_t k[4]; - int i; - - //now encrypted buf is TCP/IP-endian; - //TCP/IP network byte order (which is big-endian). - y = ntohl(*((uint32_t*)src)); - z = ntohl(*((uint32_t*)(src + 4))); - //std::cout << ntohl(0x0a3aea41); - - for (i = 0; i < 4; i++) { - //key is TCP/IP-endian; - k[i] = ntohl(*((uint32_t*)(key.data() + i * 4))); - } - - sum = 0; - for (i = 0; i < rounds; i++) { - sum += DELTA; - y += ((z << 4) + k[0]) ^ (z + sum) ^ ((z >> 5) + k[1]); - z += ((y << 4) + k[2]) ^ (y + sum) ^ ((y >> 5) + k[3]); - } - - *((uint32_t*)dst) = ntohl(y); - *((uint32_t*)(dst + 4)) = ntohl(z); - - //now plain-text is TCP/IP-endian; -} - -/*pKeyΪ16byte*/ -/* - :nInBufLenΪܵIJ(Body); - :Ϊܺij(8byteı); -*/ -/*TEA㷨,CBCģʽ*/ -/*ĸʽ:PadLen(1byte)+Padding(var,0-7byte)+Salt(2byte)+Body(var byte)+Zero(7byte)*/ -int encryptTencentTeaLen(int nInBufLen) -{ - - int nPadSaltBodyZeroLen/*PadLen(1byte)+Salt+Body+Zeroij*/; - int nPadlen; - - /*BodyȼPadLen,С賤ȱΪ8byte*/ - nPadSaltBodyZeroLen = nInBufLen/*Body*/ + 1 + SALT_LEN + ZERO_LEN/*PadLen(1byte)+Salt(2byte)+Zero(7byte)*/; - if ((nPadlen = nPadSaltBodyZeroLen % 8)) /*len=nSaltBodyZeroLen%8*/ - { - /*ģ80貹0,17,26,...,71*/ - nPadlen = 8 - nPadlen; - } - - return nPadlen; -} - -/*pKeyΪ16byte*/ -/* - :pInBufΪܵIJ(Body),nInBufLenΪpInBuf; - :pOutBufΪĸʽ,pOutBufLenΪpOutBufij8byteı; -*/ -/*TEA㷨,CBCģʽ*/ -/*ĸʽ:PadLen(1byte)+Padding(var,0-7byte)+Salt(2byte)+Body(var byte)+Zero(7byte)*/ -bool encryptTencentTea(std::vector inBuf, std::vector key, std::vector &outBuf) -{ - srand(time(0)); - int nPadlen = encryptTencentTeaLen(inBuf.size()); - size_t ivCrypt; - std::vector srcBuf; - srcBuf.resize(8); - std::vector ivPlain; - ivPlain.resize(8); - int tmpIdx, i, j; - - /*ܵһ(8byte),ȡǰ10byte*/ - srcBuf[0] = (((char)rand()) & 0x0f8)/*λPadLen,*/ | (char)nPadlen; - tmpIdx = 1; /*tmpIdxָsrcBufһλ*/ - - while (nPadlen--) srcBuf[tmpIdx++] = (char)rand(); /*Padding*/ - - /*come here, tmpIdx must <= 8*/ - - for (i = 0; i < 8; i++) ivPlain[i] = 0; - ivCrypt = 0;//ivPlain /*make zero iv*/ - - auto outBufPos = 0; /*init outBufPos*/ - -#define cryptBlock {\ - /*tmpIdx==8*/\ - outBuf.resize(outBuf.size() + 8);\ - for (j = 0; j < 8; j++) /*ǰǰ8byte(iv_cryptָ)*/\ - srcBuf[j] ^= outBuf[j + ivCrypt];\ - /*pOutBufferpInBufferΪ8byte, pKeyΪ16byte*/\ - /**/\ - TeaEncryptECB(srcBuf.data(), outBuf.data()+outBufPos, key, 16);\ - for (j = 0; j < 8; j++) /*ܺǰ8byte(iv_plainָ)*/\ - outBuf[j + outBufPos] ^= ivPlain[j];\ - /*浱ǰiv_plain*/\ - for (j = 0; j < 8; j++) ivPlain[j] = srcBuf[j];\ - /*iv_crypt*/\ - tmpIdx = 0;\ - ivCrypt = outBufPos;\ - outBufPos += 8;\ - } - - - for (i = 1; i <= SALT_LEN;) /*Salt(2byte)*/ - { - if (tmpIdx < 8) - { - srcBuf[tmpIdx++] = (char)rand(); - i++; /*i inc in here*/ - } - if (tmpIdx == 8) - { - cryptBlock - } - } - - /*tmpIdxָsrcBufһλ*/ - - auto inBufPos = 0; - while (inBufPos < inBuf.size()) - { - if (tmpIdx < 8) - { - srcBuf[tmpIdx++] = inBuf[inBufPos]; - inBufPos++; - } - if (tmpIdx == 8) - { - cryptBlock - } - } - - /*tmpIdxָsrcBufһλ*/ - - for (i = 1; i <= ZERO_LEN;) - { - if (tmpIdx < 8) - { - srcBuf[tmpIdx++] = 0; - i++; //i inc in here - } - if (tmpIdx == 8) - { - cryptBlock - } - } - return true; -#undef cryptBlock -} - -bool decryptTencentTea(std::vector inBuf, std::vector key, std::vector &out) { - if (inBuf.size() % 8 != 0) { - return false; - //inBuf size not a multiple of the block size - } - if (inBuf.size() < 16) { - return false; - //inBuf size too small - } - - std::vector tmpBuf; - tmpBuf.resize(8); - - TeaDecryptECB(inBuf.data(), tmpBuf.data(), key, 16); - - auto nPadLen = tmpBuf[0] & 0x7; //ֻҪλ - /*ĸʽ:PadLen(1byte)+Padding(var,0-7byte)+Salt(2byte)+Body(var byte)+Zero(7byte)*/ - auto outLen = inBuf.size() - 1 /*PadLen*/ - nPadLen - SALT_LEN - ZERO_LEN; - std::vector outBuf; - outBuf.resize(outLen); - - std::vector ivPrev; - ivPrev.resize(8); - std::vector ivCur; - ivCur.resize(8); - for (size_t i = 0; i < 8; i++) - { - ivCur[i] = inBuf[i]; // init iv - } - auto inBufPos = 8; - - // Padding Len Padding - auto tmpIdx = 1 + nPadLen; - - // CBC IV -#define cryptBlock {\ - ivPrev = ivCur;\ - for (size_t k = inBufPos; k < inBufPos + 8; k++)\ - {\ - ivCur[k - inBufPos] = inBuf[k];\ - }\ - for (size_t j = 0; j < 8; j++) {\ - tmpBuf[j] ^= ivCur[j];\ - }\ - TeaDecryptECB(tmpBuf.data(), tmpBuf.data(), key, 16);\ - inBufPos += 8;\ - tmpIdx = 0;\ - } - - // Salt - for (size_t i = 1; i <= SALT_LEN; ) { - if (tmpIdx < 8) { - tmpIdx++; - i++; - } - else { - cryptBlock - } - } - - // ԭ - auto outBufPos = 0; - while (outBufPos < outLen) { - if (tmpIdx < 8) { - outBuf[outBufPos] = tmpBuf[tmpIdx] ^ ivPrev[tmpIdx]; - outBufPos++; - tmpIdx++; - } - else { - cryptBlock - } - } - - // УZero - for (size_t i = 1; i <= ZERO_LEN; i++) { - if (tmpBuf[i] != ivPrev[i]) { - return false; - //zero check failed - } - } - out = outBuf; - return true; -#undef cryptBlock -} - -#endif //QQMUSIC_CPP_TENCENTTEA_HPP diff --git a/src/QmcWasm/base64.hpp b/src/QmcWasm/base64.hpp deleted file mode 100644 index b3b6aca..0000000 --- a/src/QmcWasm/base64.hpp +++ /dev/null @@ -1,207 +0,0 @@ -// -// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -// Official repository: https://github.com/boostorg/beast -// - -/* - Portions from http://www.adp-gmbh.ch/cpp/common/base64.html - Copyright notice: - - base64.cpp and base64.h - - Copyright (C) 2004-2008 Rene Nyffenegger - - This source code is provided 'as-is', without any express or implied - warranty. In no event will the author be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this source code must not be misrepresented; you must not - claim that you wrote the original source code. If you use this source code - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original source code. - - 3. This notice may not be removed or altered from any source distribution. - - Rene Nyffenegger rene.nyffenegger@adp-gmbh.ch -*/ - -#ifndef BASE64_HPP -#define BASE64_HPP - -#include -#include -#include - -namespace base64 { - - /// Returns max chars needed to encode a base64 string - std::size_t constexpr - encoded_size(std::size_t n) - { - return 4 * ((n + 2) / 3); - } - - /// Returns max bytes needed to decode a base64 string - inline - std::size_t constexpr - decoded_size(std::size_t n) - { - return n / 4 * 3; // requires n&3==0, smaller - } - - char const* - get_alphabet() - { - static char constexpr tab[] = { - "ABCDEFGHIJKLMNOP" - "QRSTUVWXYZabcdef" - "ghijklmnopqrstuv" - "wxyz0123456789+/" - }; - return &tab[0]; - } - - signed char const* - get_inverse() - { - static signed char constexpr tab[] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0-15 - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 16-31 - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, // 32-47 - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, // 48-63 - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 64-79 - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, // 80-95 - -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 96-111 - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, // 112-127 - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 128-143 - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 144-159 - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 160-175 - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 176-191 - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 192-207 - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 208-223 - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 224-239 - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 // 240-255 - }; - return &tab[0]; - } - - /** Encode a series of octets as a padded, base64 string. - - The resulting string will not be null terminated. - - @par Requires - - The memory pointed to by `out` points to valid memory - of at least `encoded_size(len)` bytes. - - @return The number of characters written to `out`. This - will exclude any null termination. - */ - std::size_t - encode(void* dest, void const* src, std::size_t len) - { - char* out = static_cast(dest); - char const* in = static_cast(src); - auto const tab = base64::get_alphabet(); - - for (auto n = len / 3; n--;) - { - *out++ = tab[(in[0] & 0xfc) >> 2]; - *out++ = tab[((in[0] & 0x03) << 4) + ((in[1] & 0xf0) >> 4)]; - *out++ = tab[((in[2] & 0xc0) >> 6) + ((in[1] & 0x0f) << 2)]; - *out++ = tab[in[2] & 0x3f]; - in += 3; - } - - switch (len % 3) - { - case 2: - *out++ = tab[(in[0] & 0xfc) >> 2]; - *out++ = tab[((in[0] & 0x03) << 4) + ((in[1] & 0xf0) >> 4)]; - *out++ = tab[(in[1] & 0x0f) << 2]; - *out++ = '='; - break; - - case 1: - *out++ = tab[(in[0] & 0xfc) >> 2]; - *out++ = tab[((in[0] & 0x03) << 4)]; - *out++ = '='; - *out++ = '='; - break; - - case 0: - break; - } - - return out - static_cast(dest); - } - - /** Decode a padded base64 string into a series of octets. - - @par Requires - - The memory pointed to by `out` points to valid memory - of at least `decoded_size(len)` bytes. - - @return The number of octets written to `out`, and - the number of characters read from the input string, - expressed as a pair. - */ - std::pair - decode(void* dest, char const* src, std::size_t len) - { - char* out = static_cast(dest); - auto in = reinterpret_cast(src); - unsigned char c3[3], c4[4]; - int i = 0; - int j = 0; - - auto const inverse = base64::get_inverse(); - - while (len-- && *in != '=') - { - auto const v = inverse[*in]; - if (v == -1) - break; - ++in; - c4[i] = v; - if (++i == 4) - { - c3[0] = (c4[0] << 2) + ((c4[1] & 0x30) >> 4); - c3[1] = ((c4[1] & 0xf) << 4) + ((c4[2] & 0x3c) >> 2); - c3[2] = ((c4[2] & 0x3) << 6) + c4[3]; - - for (i = 0; i < 3; i++) - *out++ = c3[i]; - i = 0; - } - } - - if (i) - { - c3[0] = (c4[0] << 2) + ((c4[1] & 0x30) >> 4); - c3[1] = ((c4[1] & 0xf) << 4) + ((c4[2] & 0x3c) >> 2); - c3[2] = ((c4[2] & 0x3) << 6) + c4[3]; - - for (j = 0; j < i - 1; j++) - *out++ = c3[j]; - } - - return { out - static_cast(dest), - in - reinterpret_cast(src) }; - } - -} // base64 - -#endif diff --git a/src/QmcWasm/build-wasm b/src/QmcWasm/build-wasm deleted file mode 100755 index 4cd1640..0000000 --- a/src/QmcWasm/build-wasm +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env bash - -set -e - -pushd "$(realpath "$(dirname "$0")")" - -CURR_DIR="${PWD}" - -BUILD_TYPE="$1" -if [ -z "$BUILD_TYPE" ]; then - BUILD_TYPE=Release -fi - -# CI: already had emsdk installed. -if ! command -v emcc; then - if [ ! -d ../../build/emsdk ]; then - git clone https://github.com/emscripten-core/emsdk.git ../../build/emsdk - fi - - pushd ../../build/emsdk - ./emsdk install 3.0.0 - ./emsdk activate 3.0.0 - source ./emsdk_env.sh - popd # ../../build/emsdk -fi - -mkdir -p build/wasm -pushd build/wasm -emcmake cmake -DCMAKE_BUILD_TYPE="$BUILD_TYPE" ../.. -make -j -TARGET_FILES=" - QmcLegacy.js - QmcWasm.js - QmcWasm.wasm - QmcWasmBundle.js -" - -cp $TARGET_FILES "${CURR_DIR}/" -popd # build/wasm - -popd diff --git a/src/QmcWasm/qmc.hpp b/src/QmcWasm/qmc.hpp deleted file mode 100644 index 3f26ecf..0000000 --- a/src/QmcWasm/qmc.hpp +++ /dev/null @@ -1,230 +0,0 @@ -#include -#include -#include -#include -#include "qmc_key.hpp" -#include "qmc_cipher.hpp" - -class QmcDecode { -private: - std::vector blobData; - - std::vector rawKeyBuf; - std::string cipherType = ""; - - size_t dataOffset = 0; - size_t keySize = 0; - int mediaVer = 0; - - std::string checkType(std::string fn) { - if (fn.find(".qmc") < fn.size() || fn.find(".m") < fn.size()) - { - std::string buf_tag = ""; - for (int i = 4; i > 0; --i) - { - buf_tag += *((char*)blobData.data() + blobData.size() - i); - } - if (buf_tag == "QTag") - { - keySize = ntohl(*(uint32_t*)(blobData.data() + blobData.size() - 8)); - return "QTag"; - } - else if (buf_tag == "STag") - { - return "STag"; - } - else - { - keySize = (*(uint32_t*)(blobData.data() + blobData.size() - 4)); - if (keySize < 0x400) - { - return "Map/RC4"; - } - else - { - keySize = 0; - return "Static"; - } - } - } - else if (fn.find(".cache") < fn.size()) - { - return "cache"; - } - else if (fn.find(".tm") < fn.size()) - { - return "ios"; - } - else - { - return "invalid"; - } - } - - bool parseRawKeyQTag() { - std::string ketStr = ""; - std::string::size_type index = 0; - ketStr.append((char*)rawKeyBuf.data(), rawKeyBuf.size()); - index = ketStr.find(",", 0); - if (index != std::string::npos) - { - rawKeyBuf.resize(index); - } - else - { - return false; - } - ketStr = ketStr.substr(index + 1); - index = ketStr.find(",", 0); - if (index != std::string::npos) - { - this->songId = ketStr.substr(0, index); - } - else - { - return false; - } - ketStr = ketStr.substr(index + 1); - index = ketStr.find(",", 0); - if (index == std::string::npos) - { - this->mediaVer = std::stoi(ketStr); - } - else - { - return false; - } - return true; - } - - bool readRawKey(size_t tailSize) { - // get raw key data length - rawKeyBuf.resize(keySize); - if (rawKeyBuf.size() != keySize) { - return false; - } - for (size_t i = 0; i < keySize; i++) - { - rawKeyBuf[i] = blobData[i + blobData.size() - (tailSize + keySize)]; - } - return true; - } - - void DecodeStatic(); - - void DecodeMapRC4(); - - void DecodeCache(); - - void DecodeTm(); - -public: - bool SetBlob(uint8_t* blob, size_t blobSize) { - blobData.resize(blobSize); - if (blobData.size() != blobSize) { - return false; - } - memcpy(blobData.data(), blob, blobSize); - return true; - } - - int PreDecode(std::string ext) { - cipherType = checkType(ext); - size_t tailSize = 0; - if (cipherType == "invalid" || cipherType == "STag") { - error = "file is invalid or not supported (Please downgrade your app)."; - return -1; - } - if (cipherType == "QTag") { - tailSize = 8; - } - else if (cipherType == "Map/RC4") { - tailSize = 4; - } - if (keySize > 0) { - if (!readRawKey(tailSize)) { - error = "cannot read embedded key from file"; - return -1; - } - if (tailSize == 8) { - cipherType = "Map/RC4"; - if (!parseRawKeyQTag()) { - error = "cannot parse embedded key"; - return -1; - } - } - std::vector tmp; - if (!QmcDecryptKey(rawKeyBuf, tmp)) { - error = "cannot decrypt embedded key"; - return -1; - } - rawKeyBuf = tmp; - } - return keySize + tailSize; - } - - std::vector Decode(size_t offset); - - std::string songId = ""; - std::string error = ""; -}; - -void QmcDecode::DecodeStatic() -{ - QmcStaticCipher sc; - sc.proc(blobData, dataOffset); -} - -void QmcDecode::DecodeMapRC4() { - if (rawKeyBuf.size() > 300) - { - QmcRC4Cipher c(rawKeyBuf, 2); - c.proc(blobData, dataOffset); - } - else - { - QmcMapCipher c(rawKeyBuf, 2); - c.proc(blobData, dataOffset); - } -} - -void QmcDecode::DecodeCache() -{ - for (size_t i = 0; i < blobData.size(); i++) { - blobData[i] ^= 0xf4; - blobData[i] = ((blobData[i] & 0b00111111) << 2) | (blobData[i] >> 6); // rol 2 - } -} - -void QmcDecode::DecodeTm() -{ - uint8_t const TM_HEADER[] = { 0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70 }; - for (size_t cur = dataOffset, i = 0; cur < 8 && i < blobData.size(); ++cur, ++i) { - blobData[i] = TM_HEADER[dataOffset]; - } -} - -std::vector QmcDecode::Decode(size_t offset) -{ - dataOffset = offset; - if (cipherType == "Map/RC4") - { - DecodeMapRC4(); - } - else if (cipherType == "Static") - { - DecodeStatic(); - } - else if (cipherType == "cache") - { - DecodeCache(); - } - else if (cipherType == "ios") - { - DecodeTm(); - } - else { - error = "File is invalid or encryption type is not supported."; - } - return blobData; -} diff --git a/src/QmcWasm/qmc_cipher.hpp b/src/QmcWasm/qmc_cipher.hpp deleted file mode 100644 index 8dc2b18..0000000 --- a/src/QmcWasm/qmc_cipher.hpp +++ /dev/null @@ -1,290 +0,0 @@ -#include -#include -class QmcStaticCipher { -private: - uint8_t staticCipherBox[256] = { - 0x77, 0x48, 0x32, 0x73, 0xDE, 0xF2, 0xC0, 0xC8, //0x00 - 0x95, 0xEC, 0x30, 0xB2, 0x51, 0xC3, 0xE1, 0xA0, //0x08 - 0x9E, 0xE6, 0x9D, 0xCF, 0xFA, 0x7F, 0x14, 0xD1, //0x10 - 0xCE, 0xB8, 0xDC, 0xC3, 0x4A, 0x67, 0x93, 0xD6, //0x18 - 0x28, 0xC2, 0x91, 0x70, 0xCA, 0x8D, 0xA2, 0xA4, //0x20 - 0xF0, 0x08, 0x61, 0x90, 0x7E, 0x6F, 0xA2, 0xE0, //0x28 - 0xEB, 0xAE, 0x3E, 0xB6, 0x67, 0xC7, 0x92, 0xF4, //0x30 - 0x91, 0xB5, 0xF6, 0x6C, 0x5E, 0x84, 0x40, 0xF7, //0x38 - 0xF3, 0x1B, 0x02, 0x7F, 0xD5, 0xAB, 0x41, 0x89, //0x40 - 0x28, 0xF4, 0x25, 0xCC, 0x52, 0x11, 0xAD, 0x43, //0x48 - 0x68, 0xA6, 0x41, 0x8B, 0x84, 0xB5, 0xFF, 0x2C, //0x50 - 0x92, 0x4A, 0x26, 0xD8, 0x47, 0x6A, 0x7C, 0x95, //0x58 - 0x61, 0xCC, 0xE6, 0xCB, 0xBB, 0x3F, 0x47, 0x58, //0x60 - 0x89, 0x75, 0xC3, 0x75, 0xA1, 0xD9, 0xAF, 0xCC, //0x68 - 0x08, 0x73, 0x17, 0xDC, 0xAA, 0x9A, 0xA2, 0x16, //0x70 - 0x41, 0xD8, 0xA2, 0x06, 0xC6, 0x8B, 0xFC, 0x66, //0x78 - 0x34, 0x9F, 0xCF, 0x18, 0x23, 0xA0, 0x0A, 0x74, //0x80 - 0xE7, 0x2B, 0x27, 0x70, 0x92, 0xE9, 0xAF, 0x37, //0x88 - 0xE6, 0x8C, 0xA7, 0xBC, 0x62, 0x65, 0x9C, 0xC2, //0x90 - 0x08, 0xC9, 0x88, 0xB3, 0xF3, 0x43, 0xAC, 0x74, //0x98 - 0x2C, 0x0F, 0xD4, 0xAF, 0xA1, 0xC3, 0x01, 0x64, //0xA0 - 0x95, 0x4E, 0x48, 0x9F, 0xF4, 0x35, 0x78, 0x95, //0xA8 - 0x7A, 0x39, 0xD6, 0x6A, 0xA0, 0x6D, 0x40, 0xE8, //0xB0 - 0x4F, 0xA8, 0xEF, 0x11, 0x1D, 0xF3, 0x1B, 0x3F, //0xB8 - 0x3F, 0x07, 0xDD, 0x6F, 0x5B, 0x19, 0x30, 0x19, //0xC0 - 0xFB, 0xEF, 0x0E, 0x37, 0xF0, 0x0E, 0xCD, 0x16, //0xC8 - 0x49, 0xFE, 0x53, 0x47, 0x13, 0x1A, 0xBD, 0xA4, //0xD0 - 0xF1, 0x40, 0x19, 0x60, 0x0E, 0xED, 0x68, 0x09, //0xD8 - 0x06, 0x5F, 0x4D, 0xCF, 0x3D, 0x1A, 0xFE, 0x20, //0xE0 - 0x77, 0xE4, 0xD9, 0xDA, 0xF9, 0xA4, 0x2B, 0x76, //0xE8 - 0x1C, 0x71, 0xDB, 0x00, 0xBC, 0xFD, 0x0C, 0x6C, //0xF0 - 0xA5, 0x47, 0xF7, 0xF6, 0x00, 0x79, 0x4A, 0x11 //0xF8 - }; - - uint8_t getMask(size_t offset) { - if (offset > 0x7fff) offset %= 0x7fff; - return staticCipherBox[(offset * offset + 27) & 0xff]; - } - -public: - void proc(std::vector& buf, size_t offset) { - for (size_t i = 0; i < buf.size(); i++) { - buf[i] ^= getMask(offset + i); - } - } -}; - -class QmcMapCipher { -private: - std::vector key; - - uint8_t rotate(uint8_t value, size_t bits) { - auto rotate = (bits + 4) % 8; - auto left = value << rotate; - auto right = value >> rotate; - return (left | right) & 0xff; - } - - uint8_t getMask(size_t offset) { - if (offset > 0x7fff) offset %= 0x7fff; - - const auto idx = (offset * offset + 71214) % key.size(); - return rotate(key[idx], idx & 0x7); - } - -public: - QmcMapCipher(std::vector &argKey, short operation) { - if (operation == 2) - { - if (argKey.size() == 0) { - return; - } - } - else if (operation == 1) - { - const char WordList[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - srand(time(0)); - uint32_t number = 0; - while (number > 300 || number == 0) - { - number = rand(); - } - argKey.resize(number); - for (int i = 0; i < argKey.size(); i++) { - number = rand(); - argKey[i] = WordList[number % 62]; - } - } - else - { - return; - } - - key = argKey; - } - - void proc(std::vector& buf, size_t offset) { - for (size_t i = 0; i < buf.size(); i++) { - buf[i] ^= getMask(offset + i); - } - } -}; - -class QmcRC4Cipher { -public: - void proc(std::vector& buf, size_t offset) { - // Macro: common code after each process -#define postProcess(len) \ - { \ - toProcess -= len; \ - processed += len; \ - offset += len; \ - /* no more data */ \ - if (toProcess == 0) { \ - return; \ - } \ - } - - size_t toProcess = buf.size(); - size_t processed = 0; - std::vector tmpbuf; - - // ǰ 128 ֽʹòͬĽܷ - if (offset < FIRST_SEGMENT_SIZE) { - size_t len_segment = std::min(FIRST_SEGMENT_SIZE - offset, buf.size()); - tmpbuf.resize(len_segment); - for (size_t i = 0; i < len_segment; i++) - { - tmpbuf[i] = buf[processed + i]; - } - procFirstSegment(tmpbuf, offset); - for (size_t i = 0; i < len_segment; i++) - { - buf[processed + i] = tmpbuf[i]; - } - postProcess(len_segment); - } - - - // - if (offset % SEGMENT_SIZE != 0) { - size_t len_segment = std::min(SEGMENT_SIZE - (offset % SEGMENT_SIZE), toProcess); - tmpbuf.resize(len_segment); - for (size_t i = 0; i < len_segment; i++) - { - tmpbuf[i] = buf[processed + i]; - } - procASegment(tmpbuf, offset); - for (size_t i = 0; i < len_segment; i++) - { - buf[processed + i] = tmpbuf[i]; - } - postProcess(len_segment); - } - - // ÿһн - while (toProcess > SEGMENT_SIZE) { - tmpbuf.resize(SEGMENT_SIZE); - for (size_t i = 0; i < SEGMENT_SIZE; i++) - { - tmpbuf[i] = buf[processed + i]; - } - procASegment(tmpbuf, offset); - for (size_t i = 0; i < SEGMENT_SIZE; i++) - { - buf[processed + i] = tmpbuf[i]; - } - postProcess(SEGMENT_SIZE); - } - - if (toProcess > 0) { - tmpbuf.resize(toProcess); - for (size_t i = 0; i < toProcess; i++) - { - tmpbuf[i] = buf[processed + i]; - } - procASegment(tmpbuf, offset); - for (size_t i = 0; i < toProcess; i++) - { - buf[processed + i] = tmpbuf[i]; - } - } - -#undef postProcess - } - - QmcRC4Cipher(std::vector& argKey, short operation) { - if (operation == 2) - { - if (argKey.size() == 0) { - return; - } - } - else if (operation == 1) - { - const char WordList[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - srand(time(0)); - uint32_t number = 0; - while (number <= 300 || number >= 512) - { - number = rand(); - } - argKey.resize(number); - for (int i = 0; i < argKey.size(); i++) { - number = rand(); - argKey[i] = WordList[number % 62]; - } - } - else - { - return; - } - - key = argKey; - - // init seed box - S.resize(key.size()); - for (size_t i = 0; i < key.size(); ++i) { - S[i] = i & 0xff; - } - size_t j = 0; - for (size_t i = 0; i < key.size(); ++i) { - j = (S[i] + j + key[i % key.size()]) % key.size(); - std::swap(S[i], S[j]); - } - - // init hash base - hash = 1; - for (size_t i = 0; i < key.size(); i++) { - uint8_t value = key[i]; - - // ignore if key char is '\x00' - if (!value) continue; - - auto next_hash = hash * value; - if (next_hash == 0 || next_hash <= hash) break; - - hash = next_hash; - } - } - -private: - const size_t FIRST_SEGMENT_SIZE = 0x80; - const size_t SEGMENT_SIZE = 5120; - - std::vector S; - std::vector key; - uint32_t hash = 1; - - void procFirstSegment(std::vector& buf, size_t offset) { - for (size_t i = 0; i < buf.size(); i++) { - buf[i] ^= key[getSegmentKey(offset + i)]; - } - } - - void procASegment(std::vector& buf, size_t offset) { - // Initialise a new seed box - std::vector nS; - nS = S; - - // Calculate the number of bytes to skip. - // The initial "key" derived from segment id, plus the current offset. - int64_t skipLen = (offset % SEGMENT_SIZE) + getSegmentKey(int(offset / SEGMENT_SIZE)); - - // decrypt the block - size_t j = 0; - size_t k = 0; - int i = -skipLen; - for (; i < (int)buf.size(); i++) { - j = (j + 1) % key.size(); - k = (nS[j] + k) % key.size(); - std::swap(nS[k], nS[j]); - - if (i >= 0) { - buf[i] ^= nS[(nS[j] + nS[k]) % key.size()]; - } - } - } - - uint64_t getSegmentKey(int id) { - auto seed = key[id % key.size()]; - uint64_t idx = ((double)hash / ((id + 1) * seed)) * 100.0; - return idx % key.size(); - } -}; diff --git a/src/QmcWasm/qmc_key.hpp b/src/QmcWasm/qmc_key.hpp deleted file mode 100644 index f3178cd..0000000 --- a/src/QmcWasm/qmc_key.hpp +++ /dev/null @@ -1,217 +0,0 @@ -#include"TencentTea.hpp" -#include "base64.hpp" - -void simpleMakeKey(uint8_t salt, int length, std::vector &key_buf) { - for (size_t i = 0; i < length; ++i) { - double tmp = tan((float)salt + (double)i * 0.1); - key_buf[i] = 0xFF & (uint8_t)(fabs(tmp) * 100.0); - } -} - -std::vector v2KeyPrefix = { 0x51, 0x51, 0x4D, 0x75, 0x73, 0x69, 0x63, 0x20, 0x45, 0x6E, 0x63, 0x56, 0x32, 0x2C, 0x4B, 0x65, 0x79, 0x3A }; - -bool decryptV2Key(std::vector key, std::vector& outVec) -{ - if (v2KeyPrefix.size() > key.size()) - { - return true; - } - for (size_t i = 0; i < v2KeyPrefix.size(); i++) - { - if (key[i] != v2KeyPrefix[i]) - { - return true; - } - } - - std::vector mixKey1 = { 0x33, 0x38, 0x36, 0x5A, 0x4A, 0x59, 0x21, 0x40, 0x23, 0x2A, 0x24, 0x25, 0x5E, 0x26, 0x29, 0x28 }; - std::vector mixKey2 = { 0x2A, 0x2A, 0x23, 0x21, 0x28, 0x23, 0x24, 0x25, 0x26, 0x5E, 0x61, 0x31, 0x63, 0x5A, 0x2C, 0x54 }; - - std::vector out; - std::vector tmpKey; - tmpKey.resize(key.size() - 18); - for (size_t i = 0; i < tmpKey.size(); i++) - { - tmpKey[i] = key[18 + i]; - } - if (!decryptTencentTea(tmpKey, mixKey1, out)) - { - outVec.resize(0); - //EncV2 key decode failed. - return false; - } - - tmpKey.resize(out.size()); - for (size_t i = 0; i < tmpKey.size(); i++) - { - tmpKey[i] = out[i]; - } - out.resize(0); - if (!decryptTencentTea(tmpKey, mixKey2, out)) - { - outVec.resize(0); - //EncV2 key decode failed. - return false; - } - - outVec.resize(base64::decoded_size(out.size())); - auto n = base64::decode(outVec.data(), (const char*)(out.data()), out.size()).first; - - if (n < 16) - { - outVec.resize(0); - //EncV2 key size is too small. - return false; - } - outVec.resize(n); - - return true; -} - -bool encryptV2Key(std::vector key, std::vector& outVec) -{ - if (key.size() < 16) - { - outVec.resize(0); - //EncV2 key size is too small. - return false; - } - - std::vector in; - in.resize(base64::encoded_size(key.size())); - auto n = base64::encode(in.data(), (const char*)(key.data()), key.size()); - in.resize(n); - - std::vector mixKey1 = { 0x33, 0x38, 0x36, 0x5A, 0x4A, 0x59, 0x21, 0x40, 0x23, 0x2A, 0x24, 0x25, 0x5E, 0x26, 0x29, 0x28 }; - std::vector mixKey2 = { 0x2A, 0x2A, 0x23, 0x21, 0x28, 0x23, 0x24, 0x25, 0x26, 0x5E, 0x61, 0x31, 0x63, 0x5A, 0x2C, 0x54 }; - - std::vector tmpKey; - if (!encryptTencentTea(in, mixKey2, tmpKey)) - { - outVec.resize(0); - //EncV2 key decode failed. - return false; - } - in.resize(tmpKey.size()); - for (size_t i = 0; i < tmpKey.size(); i++) - { - in[i] = tmpKey[i]; - } - tmpKey.resize(0); - - if (!encryptTencentTea(in, mixKey1, tmpKey)) - { - outVec.resize(0); - //EncV2 key decode failed. - return false; - } - outVec.resize(tmpKey.size() + 18); - for (size_t i = 0; i < tmpKey.size(); i++) - { - outVec[18 + i] = tmpKey[i]; - } - - for (size_t i = 0; i < v2KeyPrefix.size(); i++) - { - outVec[i] = v2KeyPrefix[i]; - } - - return true; -} - -bool QmcDecryptKey(std::vector raw, std::vector &outVec) { - std::vector rawDec; - rawDec.resize(base64::decoded_size(raw.size())); - auto n = base64::decode(rawDec.data(), (const char*)(raw.data()), raw.size()).first; - if (n < 16) { - return false; - //key length is too short - } - rawDec.resize(n); - - std::vector tmpIn = rawDec; - if (!decryptV2Key(tmpIn, rawDec)) - { - //decrypt EncV2 failed. - return false; - } - - std::vector simpleKey; - simpleKey.resize(8); - simpleMakeKey(106, 8, simpleKey); - std::vector teaKey; - teaKey.resize(16); - for (size_t i = 0; i < 8; i++) { - teaKey[i << 1] = simpleKey[i]; - teaKey[(i << 1) + 1] = rawDec[i]; - } - std::vector out; - std::vector tmpRaw; - tmpRaw.resize(rawDec.size() - 8); - for (size_t i = 0; i < tmpRaw.size(); i++) - { - tmpRaw[i] = rawDec[8 + i]; - } - if (decryptTencentTea(tmpRaw, teaKey, out)) - { - rawDec.resize(8 + out.size()); - for (size_t i = 0; i < out.size(); i++) - { - rawDec[8 + i] = out[i]; - } - outVec = rawDec; - return true; - } - else - { - return false; - } -} - -bool QmcEncryptKey(std::vector raw, std::vector& outVec, bool useEncV2 = true) { - std::vector simpleKey; - simpleKey.resize(8); - simpleMakeKey(106, 8, simpleKey); - std::vector teaKey; - teaKey.resize(16); - for (size_t i = 0; i < 8; i++) { - teaKey[i << 1] = simpleKey[i]; - teaKey[(i << 1) + 1] = raw[i]; - } - std::vector out; - out.resize(raw.size() - 8); - for (size_t i = 0; i < out.size(); i++) - { - out[i] = raw[8 + i]; - } - std::vector tmpRaw; - if (encryptTencentTea(out, teaKey, tmpRaw)) - { - raw.resize(tmpRaw.size() + 8); - for (size_t i = 0; i < tmpRaw.size(); i++) - { - raw[i + 8] = tmpRaw[i]; - } - - if (useEncV2) - { - std::vector tmpIn = raw; - if (!encryptV2Key(tmpIn, raw)) - { - //encrypt EncV2 failed. - return false; - } - } - - std::vector rawEnc; - rawEnc.resize(base64::encoded_size(raw.size())); - auto n = base64::encode(rawEnc.data(), (const char*)(raw.data()), raw.size()); - rawEnc.resize(n); - outVec = rawEnc; - return true; - } - else - { - return false; - } -} diff --git a/src/decrypt/kgm_wasm.ts b/src/decrypt/kgm_wasm.ts index da45a38..039c3be 100644 --- a/src/decrypt/kgm_wasm.ts +++ b/src/decrypt/kgm_wasm.ts @@ -1,4 +1,5 @@ -import KgmCryptoModule from '@/KgmWasm/KgmWasmBundle'; +import { KgmCrypto } from '@xhacker/kgmwasm/KgmWasmBundle'; +import KgmCryptoModule from '@xhacker/kgmwasm/KgmWasmBundle'; import { MergeUint8Array } from '@/utils/MergeUint8Array'; // 每次处理 2M 的数据 @@ -20,26 +21,26 @@ export async function DecryptKgmWasm(kgmBlob: ArrayBuffer, ext: string): Promise const result: KGMDecryptionResult = { success: false, data: new Uint8Array(), error: '' }; // 初始化模组 - let KgmCrypto: any; + let KgmCryptoObj: KgmCrypto; try { - KgmCrypto = await KgmCryptoModule(); + KgmCryptoObj = await KgmCryptoModule(); } catch (err: any) { result.error = err?.message || 'wasm 加载失败'; return result; } - if (!KgmCrypto) { + if (!KgmCryptoObj) { result.error = 'wasm 加载失败'; return result; } // 申请内存块,并文件末端数据到 WASM 的内存堆 let kgmBuf = new Uint8Array(kgmBlob); - const pQmcBuf = KgmCrypto._malloc(DECRYPTION_BUF_SIZE); - KgmCrypto.writeArrayToMemory(kgmBuf.slice(0, DECRYPTION_BUF_SIZE), pQmcBuf); + const pQmcBuf = KgmCryptoObj._malloc(DECRYPTION_BUF_SIZE); + KgmCryptoObj.writeArrayToMemory(kgmBuf.slice(0, DECRYPTION_BUF_SIZE), pQmcBuf); // 进行解密初始化 - const headerSize = KgmCrypto.preDec(pQmcBuf, DECRYPTION_BUF_SIZE, ext); + const headerSize = KgmCryptoObj.preDec(pQmcBuf, DECRYPTION_BUF_SIZE, ext); console.log(headerSize); kgmBuf = kgmBuf.slice(headerSize); @@ -51,14 +52,14 @@ export async function DecryptKgmWasm(kgmBlob: ArrayBuffer, ext: string): Promise // 解密一些片段 const blockData = new Uint8Array(kgmBuf.slice(offset, offset + blockSize)); - KgmCrypto.writeArrayToMemory(blockData, pQmcBuf); - KgmCrypto.decBlob(pQmcBuf, blockSize, offset); - decryptedParts.push(KgmCrypto.HEAPU8.slice(pQmcBuf, pQmcBuf + blockSize)); + KgmCryptoObj.writeArrayToMemory(blockData, pQmcBuf); + KgmCryptoObj.decBlob(pQmcBuf, blockSize, offset); + decryptedParts.push(KgmCryptoObj.HEAPU8.slice(pQmcBuf, pQmcBuf + blockSize)); offset += blockSize; bytesToDecrypt -= blockSize; } - KgmCrypto._free(pQmcBuf); + KgmCryptoObj._free(pQmcBuf); result.data = MergeUint8Array(decryptedParts); result.success = true; diff --git a/src/decrypt/qmc_wasm.ts b/src/decrypt/qmc_wasm.ts index c2e06db..f747bf4 100644 --- a/src/decrypt/qmc_wasm.ts +++ b/src/decrypt/qmc_wasm.ts @@ -1,4 +1,5 @@ -import QmcCryptoModule from '@/QmcWasm/QmcWasmBundle'; +import { QmcCrypto } from '@xhacker/qmcwasm/QmcWasmBundle'; +import QmcCryptoModule from '@xhacker/qmcwasm/QmcWasmBundle'; import { MergeUint8Array } from '@/utils/MergeUint8Array'; // 每次处理 2M 的数据 @@ -21,32 +22,32 @@ export async function DecryptQmcWasm(qmcBlob: ArrayBuffer, ext: string): Promise const result: QMCDecryptionResult = { success: false, data: new Uint8Array(), songId: 0, error: '' }; // 初始化模组 - let QmcCrypto: any; + let QmcCryptoObj: QmcCrypto; try { - QmcCrypto = await QmcCryptoModule(); + QmcCryptoObj = await QmcCryptoModule(); } catch (err: any) { result.error = err?.message || 'wasm 加载失败'; return result; } - if (!QmcCrypto) { + if (!QmcCryptoObj) { result.error = 'wasm 加载失败'; return result; } // 申请内存块,并文件末端数据到 WASM 的内存堆 const qmcBuf = new Uint8Array(qmcBlob); - const pQmcBuf = QmcCrypto._malloc(DECRYPTION_BUF_SIZE); - QmcCrypto.writeArrayToMemory(qmcBuf.slice(-DECRYPTION_BUF_SIZE), pQmcBuf); + const pQmcBuf = QmcCryptoObj._malloc(DECRYPTION_BUF_SIZE); + QmcCryptoObj.writeArrayToMemory(qmcBuf.slice(-DECRYPTION_BUF_SIZE), pQmcBuf); // 进行解密初始化 ext = '.' + ext; - const tailSize = QmcCrypto.preDec(pQmcBuf, DECRYPTION_BUF_SIZE, ext); + const tailSize = QmcCryptoObj.preDec(pQmcBuf, DECRYPTION_BUF_SIZE, ext); if (tailSize == -1) { - result.error = QmcCrypto.getError(); + result.error = QmcCryptoObj.getErr(); return result; } else { - result.songId = QmcCrypto.getSongId(); + result.songId = QmcCryptoObj.getSongId(); result.songId = result.songId == "0" ? 0 : result.songId; } @@ -58,13 +59,13 @@ export async function DecryptQmcWasm(qmcBlob: ArrayBuffer, ext: string): Promise // 解密一些片段 const blockData = new Uint8Array(qmcBuf.slice(offset, offset + blockSize)); - QmcCrypto.writeArrayToMemory(blockData, pQmcBuf); - decryptedParts.push(QmcCrypto.HEAPU8.slice(pQmcBuf, pQmcBuf + QmcCrypto.decBlob(pQmcBuf, blockSize, offset))); + QmcCryptoObj.writeArrayToMemory(blockData, pQmcBuf); + decryptedParts.push(QmcCryptoObj.HEAPU8.slice(pQmcBuf, pQmcBuf + QmcCryptoObj.decBlob(pQmcBuf, blockSize, offset))); offset += blockSize; bytesToDecrypt -= blockSize; } - QmcCrypto._free(pQmcBuf); + QmcCryptoObj._free(pQmcBuf); result.data = MergeUint8Array(decryptedParts); result.success = true;