mirror of
https://git.um-react.app/um/um-react.git
synced 2025-11-28 03:23:02 +00:00
feat: added support for QMCv2 (#11)
This commit is contained in:
3
src/decrypt-worker/crypto/qmc/qmc_v2.key.ts
Normal file
3
src/decrypt-worker/crypto/qmc/qmc_v2.key.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export const SEED = 106;
|
||||
export const ENC_V2_KEY_1 = '386ZJY!@#*$%^&)(';
|
||||
export const ENC_V2_KEY_2 = '**#!(#$%&^a1cZ,T';
|
||||
17
src/decrypt-worker/crypto/qmc/qmc_v2.ts
Normal file
17
src/decrypt-worker/crypto/qmc/qmc_v2.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { transformBlob } from '~/decrypt-worker/util/transformBlob';
|
||||
import type { CryptoBase } from '../CryptoBase';
|
||||
import { SEED, ENC_V2_KEY_1, ENC_V2_KEY_2 } from './qmc_v2.key.ts';
|
||||
|
||||
export class QMC2Crypto implements CryptoBase {
|
||||
hasSignature(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
async isSupported(): Promise<boolean> {
|
||||
return true;
|
||||
}
|
||||
|
||||
async decrypt(blob: Blob): Promise<Blob> {
|
||||
return transformBlob(blob, (p) => p.make.QMCv2(p.make.QMCv2FooterParser(SEED, ENC_V2_KEY_1, ENC_V2_KEY_2)));
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,11 @@ import { WorkerServerBus } from '~/util/WorkerEventBus';
|
||||
import { DECRYPTION_WORKER_ACTION_NAME } from './constants';
|
||||
|
||||
import type { CryptoFactory } from './crypto/CryptoBase';
|
||||
import { fetchParakeet } from '@jixun/libparakeet';
|
||||
|
||||
import { XiamiCrypto } from './crypto/xiami/xiami';
|
||||
import { QMC1Crypto } from './crypto/qmc/qmc_v1';
|
||||
import { fetchParakeet } from '@jixun/libparakeet';
|
||||
import { QMC2Crypto } from './crypto/qmc/qmc_v2';
|
||||
|
||||
const bus = new WorkerServerBus();
|
||||
onmessage = bus.onmessage;
|
||||
@@ -15,6 +17,9 @@ const decryptorFactories: CryptoFactory[] = [
|
||||
|
||||
// QMCv1 (*.qmcflac)
|
||||
() => new QMC1Crypto(),
|
||||
|
||||
// QMCv2 (*.mflac)
|
||||
() => new QMC2Crypto(),
|
||||
];
|
||||
|
||||
// Use first 4MiB of the file to perform check.
|
||||
@@ -27,17 +32,22 @@ bus.addEventHandler(DECRYPTION_WORKER_ACTION_NAME.DECRYPT, async (blobURI) => {
|
||||
for (const factory of decryptorFactories) {
|
||||
const decryptor = factory();
|
||||
if (await decryptor.isSupported(blob)) {
|
||||
const decryptedBlob = await decryptor.decrypt(blob);
|
||||
try {
|
||||
const decryptedBlob = await decryptor.decrypt(blob);
|
||||
|
||||
// Check if we had a successful decryption
|
||||
const header = await decryptedBlob.slice(0, TEST_FILE_HEADER_LEN).arrayBuffer();
|
||||
const audioExt = parakeet.detectAudioExtension(header);
|
||||
if (!decryptor.hasSignature() && audioExt === 'bin') {
|
||||
// skip this decryptor result
|
||||
// Check if we had a successful decryption
|
||||
const header = await decryptedBlob.slice(0, TEST_FILE_HEADER_LEN).arrayBuffer();
|
||||
const audioExt = parakeet.detectAudioExtension(header);
|
||||
if (!decryptor.hasSignature() && audioExt === 'bin') {
|
||||
// skip this decryptor result
|
||||
continue;
|
||||
}
|
||||
|
||||
return { decrypted: URL.createObjectURL(decryptedBlob), ext: audioExt };
|
||||
} catch (error) {
|
||||
console.error('decrypt failed: ', error);
|
||||
continue;
|
||||
}
|
||||
|
||||
return { decrypted: URL.createObjectURL(decryptedBlob), ext: audioExt };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user