From 1e927ad962b59c9ab49a6a295d99c91e7c8df112 Mon Sep 17 00:00:00 2001 From: Jixun Wu Date: Wed, 15 Dec 2021 22:07:05 +0000 Subject: [PATCH] fix: treat qmcflac/qmcogg as QMCv2 and fallback to QMCv1 (cherry picked from commit 41e588e9864801897fa13eb96a1764baaa5a4ab5) --- src/decrypt/qmc.ts | 29 +++++++++++++++++++++-------- src/decrypt/qmcv2.ts | 5 ++--- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/decrypt/qmc.ts b/src/decrypt/qmc.ts index 6bc8117..e7fffb9 100644 --- a/src/decrypt/qmc.ts +++ b/src/decrypt/qmc.ts @@ -27,11 +27,14 @@ export const HandlerMap: { [key: string]: Handler } = { "mflac": {ext: "flac", version: 2}, "mflac0": {ext: "flac", version: 2}, + // qmcflac / qmcogg: + // 有可能是 v2 加密但混用同一个后缀名。 + "qmcflac": {ext: "flac", version: 2}, + "qmcogg": {ext: "ogg", version: 2}, + "qmc0": {ext: "mp3", version: 1}, "qmc2": {ext: "ogg", version: 1}, "qmc3": {ext: "mp3", version: 1}, - "qmcogg": {ext: "ogg", version: 1}, - "qmcflac": {ext: "flac", version: 1}, "bkcmp3": {ext: "mp3", version: 1}, "bkcflac": {ext: "flac", version: 1}, "tkm": {ext: "m4a", version: 1}, @@ -45,16 +48,26 @@ export const HandlerMap: { [key: string]: Handler } = { export async function Decrypt(file: Blob, raw_filename: string, raw_ext: string): Promise { if (!(raw_ext in HandlerMap)) throw `Qmc cannot handle type: ${raw_ext}`; const handler = HandlerMap[raw_ext]; + let { version } = handler; const fileBuffer = await GetArrayBuffer(file); - let musicDecoded: Uint8Array; - if (handler.version === 1) { + let musicDecoded: Uint8Array|undefined; + + if (version === 2) { + const v2Decrypted = await DecryptQMCv2(fileBuffer); + // 如果 v2 检测失败,降级到 v1 再尝试一次 + if (v2Decrypted) { + musicDecoded = v2Decrypted; + } else { + version = 1; + } + } + + if (version === 1) { const seed = QmcMaskGetDefault(); musicDecoded = seed.Decrypt(new Uint8Array(fileBuffer)); - } else if (handler.version === 2) { - musicDecoded = await DecryptQMCv2(fileBuffer); - } else { - throw new Error(`不支持的加密版本: ${handler.version} (${raw_ext})`); + } else if (!musicDecoded) { + throw new Error(`解密失败: ${raw_ext}`); } const ext = SniffAudioExt(musicDecoded, handler.ext); diff --git a/src/decrypt/qmcv2.ts b/src/decrypt/qmcv2.ts index 68f11dc..f1f5c81 100644 --- a/src/decrypt/qmcv2.ts +++ b/src/decrypt/qmcv2.ts @@ -28,7 +28,7 @@ function MergeUint8Array(array: Uint8Array[]): Uint8Array { * 如果检测并解密成功,返回解密后的 Uint8Array 数据。 * @param {ArrayBuffer} mggBlob 读入的文件 Blob * @param {string} name 文件名 - * @return {Promise} + * @return {Promise} */ export async function DecryptQMCv2(mggBlob: ArrayBuffer) { // 初始化模组 @@ -53,14 +53,13 @@ export async function DecryptQMCv2(mggBlob: ArrayBuffer) { // (pos: i32; len: i32; error: char[??]) const position = QMCCrypto.getValue(pDetectionResult, "i32"); const len = QMCCrypto.getValue(pDetectionResult + 4, "i32"); - const detectionError = QMCCrypto.UTF8ToString(pDetectionResult + 8); // 释放内存 QMCCrypto._free(pDetectionBuf); QMCCrypto._free(pDetectionResult); if (!detectOK) { - throw new Error("解密失败: \n " + detectionError); + return false; } // 计算解密后文件的大小。