From 9fed1ee610a6b79cfbcd22829f9be28bf2036c6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=B2=81=E6=A0=91=E4=BA=BA?= Date: Thu, 26 Sep 2024 20:41:02 +0100 Subject: [PATCH] fix: footer-less qmcv2 file support --- src/decrypt-worker/decipher/QQMusic.ts | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/decrypt-worker/decipher/QQMusic.ts b/src/decrypt-worker/decipher/QQMusic.ts index 5e53455..111cb99 100644 --- a/src/decrypt-worker/decipher/QQMusic.ts +++ b/src/decrypt-worker/decipher/QQMusic.ts @@ -38,20 +38,32 @@ export class QQMusicV2Decipher implements DecipherInstance { this.cipherName = `QQMusic/QMC2(user_key=${+useUserKey})`; } - async decrypt(buffer: Uint8Array, options: DecryptCommandOptions): Promise { + parseFooter(buffer: Uint8Array): { size: number; ekey?: undefined | string } { const footer = QMCFooter.parse(buffer.subarray(buffer.byteLength - 1024)); - if (!footer) { + + if (footer) { + const { size, ekey } = footer; + footer.free(); + return { size, ekey }; + } + + // No footer, and we don't accept user key: + if (!this.useUserKey) { throw new UnsupportedSourceFile('Not QMC2 File'); } - const audioBuffer = buffer.slice(0, buffer.byteLength - footer.size); + return { size: 0 }; + } + + async decrypt(buffer: Uint8Array, options: DecryptCommandOptions): Promise { + const footer = this.parseFooter(buffer.subarray(buffer.byteLength - 1024)); const ekey = this.useUserKey ? options.qmc2Key : footer.ekey; - footer.free(); if (!ekey) { - throw new Error('EKey missing'); + throw new Error('EKey required'); } const qmc2 = new QMC2(ekey); + const audioBuffer = buffer.slice(0, buffer.byteLength - footer.size); for (const [block, offset] of chunkBuffer(audioBuffer)) { qmc2.decrypt(block, offset); }