3 Commits

Author SHA1 Message Date
鲁树人
b26e62e8d9 chore: bump version to 0.3.1 2024-09-26 20:43:23 +01:00
鲁树人
9fed1ee610 fix: footer-less qmcv2 file support 2024-09-26 20:41:02 +01:00
鲁树人
5e890bca77 chore: fix husky hooks 2024-09-24 23:20:57 +01:00
4 changed files with 18 additions and 12 deletions

View File

@@ -1,4 +1 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
pnpm exec lint-staged

View File

@@ -1,4 +1 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
pnpm test

View File

@@ -1,7 +1,7 @@
{
"name": "um-react",
"private": true,
"version": "0.3.0",
"version": "0.3.1",
"type": "module",
"scripts": {
"start": "vite",

View File

@@ -38,20 +38,32 @@ export class QQMusicV2Decipher implements DecipherInstance {
this.cipherName = `QQMusic/QMC2(user_key=${+useUserKey})`;
}
async decrypt(buffer: Uint8Array, options: DecryptCommandOptions): Promise<DecipherResult | DecipherOK> {
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<DecipherResult | DecipherOK> {
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);
}