fix: treat qmcflac/qmcogg as QMCv2 and fallback to QMCv1
(cherry picked from commit 41e588e9864801897fa13eb96a1764baaa5a4ab5)
This commit is contained in:
parent
9edcaadb83
commit
1e927ad962
@ -27,11 +27,14 @@ export const HandlerMap: { [key: string]: Handler } = {
|
|||||||
"mflac": {ext: "flac", version: 2},
|
"mflac": {ext: "flac", version: 2},
|
||||||
"mflac0": {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},
|
"qmc0": {ext: "mp3", version: 1},
|
||||||
"qmc2": {ext: "ogg", version: 1},
|
"qmc2": {ext: "ogg", version: 1},
|
||||||
"qmc3": {ext: "mp3", version: 1},
|
"qmc3": {ext: "mp3", version: 1},
|
||||||
"qmcogg": {ext: "ogg", version: 1},
|
|
||||||
"qmcflac": {ext: "flac", version: 1},
|
|
||||||
"bkcmp3": {ext: "mp3", version: 1},
|
"bkcmp3": {ext: "mp3", version: 1},
|
||||||
"bkcflac": {ext: "flac", version: 1},
|
"bkcflac": {ext: "flac", version: 1},
|
||||||
"tkm": {ext: "m4a", 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<DecryptResult> {
|
export async function Decrypt(file: Blob, raw_filename: string, raw_ext: string): Promise<DecryptResult> {
|
||||||
if (!(raw_ext in HandlerMap)) throw `Qmc cannot handle type: ${raw_ext}`;
|
if (!(raw_ext in HandlerMap)) throw `Qmc cannot handle type: ${raw_ext}`;
|
||||||
const handler = HandlerMap[raw_ext];
|
const handler = HandlerMap[raw_ext];
|
||||||
|
let { version } = handler;
|
||||||
|
|
||||||
const fileBuffer = await GetArrayBuffer(file);
|
const fileBuffer = await GetArrayBuffer(file);
|
||||||
let musicDecoded: Uint8Array;
|
let musicDecoded: Uint8Array|undefined;
|
||||||
if (handler.version === 1) {
|
|
||||||
|
if (version === 2) {
|
||||||
|
const v2Decrypted = await DecryptQMCv2(fileBuffer);
|
||||||
|
// 如果 v2 检测失败,降级到 v1 再尝试一次
|
||||||
|
if (v2Decrypted) {
|
||||||
|
musicDecoded = v2Decrypted;
|
||||||
|
} else {
|
||||||
|
version = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version === 1) {
|
||||||
const seed = QmcMaskGetDefault();
|
const seed = QmcMaskGetDefault();
|
||||||
musicDecoded = seed.Decrypt(new Uint8Array(fileBuffer));
|
musicDecoded = seed.Decrypt(new Uint8Array(fileBuffer));
|
||||||
} else if (handler.version === 2) {
|
} else if (!musicDecoded) {
|
||||||
musicDecoded = await DecryptQMCv2(fileBuffer);
|
throw new Error(`解密失败: ${raw_ext}`);
|
||||||
} else {
|
|
||||||
throw new Error(`不支持的加密版本: ${handler.version} (${raw_ext})`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const ext = SniffAudioExt(musicDecoded, handler.ext);
|
const ext = SniffAudioExt(musicDecoded, handler.ext);
|
||||||
|
@ -28,7 +28,7 @@ function MergeUint8Array(array: Uint8Array[]): Uint8Array {
|
|||||||
* 如果检测并解密成功,返回解密后的 Uint8Array 数据。
|
* 如果检测并解密成功,返回解密后的 Uint8Array 数据。
|
||||||
* @param {ArrayBuffer} mggBlob 读入的文件 Blob
|
* @param {ArrayBuffer} mggBlob 读入的文件 Blob
|
||||||
* @param {string} name 文件名
|
* @param {string} name 文件名
|
||||||
* @return {Promise<Uint8Array|null>}
|
* @return {Promise<Uint8Array|false>}
|
||||||
*/
|
*/
|
||||||
export async function DecryptQMCv2(mggBlob: ArrayBuffer) {
|
export async function DecryptQMCv2(mggBlob: ArrayBuffer) {
|
||||||
// 初始化模组
|
// 初始化模组
|
||||||
@ -53,14 +53,13 @@ export async function DecryptQMCv2(mggBlob: ArrayBuffer) {
|
|||||||
// (pos: i32; len: i32; error: char[??])
|
// (pos: i32; len: i32; error: char[??])
|
||||||
const position = QMCCrypto.getValue(pDetectionResult, "i32");
|
const position = QMCCrypto.getValue(pDetectionResult, "i32");
|
||||||
const len = QMCCrypto.getValue(pDetectionResult + 4, "i32");
|
const len = QMCCrypto.getValue(pDetectionResult + 4, "i32");
|
||||||
const detectionError = QMCCrypto.UTF8ToString(pDetectionResult + 8);
|
|
||||||
|
|
||||||
// 释放内存
|
// 释放内存
|
||||||
QMCCrypto._free(pDetectionBuf);
|
QMCCrypto._free(pDetectionBuf);
|
||||||
QMCCrypto._free(pDetectionResult);
|
QMCCrypto._free(pDetectionResult);
|
||||||
|
|
||||||
if (!detectOK) {
|
if (!detectOK) {
|
||||||
throw new Error("解密失败: \n " + detectionError);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算解密后文件的大小。
|
// 计算解密后文件的大小。
|
||||||
|
Loading…
Reference in New Issue
Block a user