From 4396f8876266d0f78b781f1863d8187776d22687 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=B2=81=E6=A0=91=E4=BA=BA?= Date: Fri, 20 Sep 2024 23:23:19 +0100 Subject: [PATCH] feat: add Migu3D Keyless decipher --- package.json | 2 +- pnpm-lock.yaml | 9 +++++++-- src/decrypt-worker/Deciphers.ts | 3 ++- src/decrypt-worker/decipher/Migu3d.ts | 27 +++++++++++++++++++++++++++ 4 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 src/decrypt-worker/decipher/Migu3d.ts diff --git a/package.json b/package.json index f51f2b8..2a6ecb5 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", "@reduxjs/toolkit": "^2.0.1", - "@unlock-music/crypto": "0.0.0-alpha.15", + "@unlock-music/crypto": "0.0.0-alpha.16", "framer-motion": "^10.16.16", "nanoid": "^5.0.4", "radash": "^11.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8eb7f5a..21007bd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -39,8 +39,8 @@ importers: specifier: ^2.0.1 version: 2.0.1(react-redux@9.0.4(@types/react@18.2.45)(react@18.2.0)(redux@5.0.0))(react@18.2.0) '@unlock-music/crypto': - specifier: 0.0.0-alpha.15 - version: link:../lib_um_crypto_rust/um_wasm_loader + specifier: 0.0.0-alpha.16 + version: 0.0.0-alpha.16 framer-motion: specifier: ^10.16.16 version: 10.16.16(react-dom@18.2.0(react@18.2.0))(react@18.2.0) @@ -1921,6 +1921,9 @@ packages: '@ungap/structured-clone@1.2.0': resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + '@unlock-music/crypto@0.0.0-alpha.16': + resolution: {integrity: sha512-QDhDWTsZOOkSQ64d3+pBwPCfesit6MiO63SzV7TQB8rQ/lPb78MMz6C4ECIjP9ijCBXds4PT4CBXp8vJDifAEg==, tarball: https://git.unlock-music.dev/api/packages/um/npm/%40unlock-music%2Fcrypto/-/0.0.0-alpha.16/crypto-0.0.0-alpha.16.tgz} + '@vitejs/plugin-react@4.2.1': resolution: {integrity: sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==} engines: {node: ^14.18.0 || >=16.0.0} @@ -6107,6 +6110,8 @@ snapshots: '@ungap/structured-clone@1.2.0': {} + '@unlock-music/crypto@0.0.0-alpha.16': {} + '@vitejs/plugin-react@4.2.1(vite@5.0.10(@types/node@20.10.5)(sass@1.69.5)(terser@5.27.0))': dependencies: '@babel/core': 7.23.6 diff --git a/src/decrypt-worker/Deciphers.ts b/src/decrypt-worker/Deciphers.ts index d11da39..423b9b0 100644 --- a/src/decrypt-worker/Deciphers.ts +++ b/src/decrypt-worker/Deciphers.ts @@ -7,6 +7,7 @@ import { KugouMusicDecipher } from '~/decrypt-worker/decipher/KugouMusic.ts'; import { XimalayaAndroidDecipher, XimalayaPCDecipher } from '~/decrypt-worker/decipher/Ximalaya.ts'; import { XiamiDecipher } from '~/decrypt-worker/decipher/XiamiMusic.ts'; import { QignTingFMDecipher } from '~/decrypt-worker/decipher/QingTingFM.ts'; +import { Migu3DKeylessDecipher } from '~/decrypt-worker/decipher/Migu3d.ts'; export enum Status { OK = 0, @@ -67,7 +68,7 @@ export const allCryptoFactories: DecipherFactory[] = [ /// File without an obvious header or footer goes last. // Migu3D/Keyless (*.wav; *.m4a) - // MiguCrypto.make, + Migu3DKeylessDecipher.make, // Crypto that does not implement "checkBySignature" or need to decrypt the entire file and then check audio type, // should be moved to the bottom of the list for performance reasons. diff --git a/src/decrypt-worker/decipher/Migu3d.ts b/src/decrypt-worker/decipher/Migu3d.ts new file mode 100644 index 0000000..4a793f0 --- /dev/null +++ b/src/decrypt-worker/decipher/Migu3d.ts @@ -0,0 +1,27 @@ +import { DecipherInstance, DecipherOK, DecipherResult, Status } from '~/decrypt-worker/Deciphers.ts'; +import { chunkBuffer } from '~/decrypt-worker/util/buffer.ts'; +import { Migu3D } from '@unlock-music/crypto'; + +export class Migu3DKeylessDecipher implements DecipherInstance { + cipherName = 'Migu3D (Keyless)'; + + async decrypt(buffer: Uint8Array): Promise { + const mg3d = Migu3D.fromHeader(buffer.subarray(0, 0x100)); + const audioBuffer = new Uint8Array(buffer); + + for (const [block, i] of chunkBuffer(audioBuffer)) { + mg3d.decrypt(block, i); + } + mg3d.free(); + + return { + cipherName: this.cipherName, + status: Status.OK, + data: audioBuffer, + }; + } + + public static make() { + return new Migu3DKeylessDecipher(); + } +}