From a3fbf9662bfc320c239f3460d5d34bcead11d2ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=B2=81=E6=A0=91=E4=BA=BA?= Date: Wed, 18 Sep 2024 23:30:31 +0100 Subject: [PATCH] [xiami] feat: add xiami support --- src/decrypt-worker/Deciphers.ts | 3 ++- src/decrypt-worker/decipher/XiamiMusic.ts | 28 +++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 src/decrypt-worker/decipher/XiamiMusic.ts diff --git a/src/decrypt-worker/Deciphers.ts b/src/decrypt-worker/Deciphers.ts index a98b6ac..5aef2b1 100644 --- a/src/decrypt-worker/Deciphers.ts +++ b/src/decrypt-worker/Deciphers.ts @@ -5,6 +5,7 @@ import { QQMusicV1Decipher, QQMusicV2Decipher } from '~/decrypt-worker/decipher/ import { KuwoMusicDecipher } from '~/decrypt-worker/decipher/KuwoMusic.ts'; 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'; export enum Status { OK = 0, @@ -51,7 +52,7 @@ export const allCryptoFactories: DecipherFactory[] = [ XimalayaPCDecipher.make, // Xiami (*.xm) - // XiamiCrypto.make, + XiamiDecipher.make, /// File with a fixed footer goes second diff --git a/src/decrypt-worker/decipher/XiamiMusic.ts b/src/decrypt-worker/decipher/XiamiMusic.ts new file mode 100644 index 0000000..778d916 --- /dev/null +++ b/src/decrypt-worker/decipher/XiamiMusic.ts @@ -0,0 +1,28 @@ +import { DecipherInstance, DecipherOK, DecipherResult, Status } from '~/decrypt-worker/Deciphers.ts'; +import { Xiami } from '@unlock-music/crypto'; +import { chunkBuffer } from '~/decrypt-worker/util/buffer.ts'; + +export class XiamiDecipher implements DecipherInstance { + cipherName = 'Xiami (XM)'; + + async decrypt(buffer: Uint8Array): Promise { + const xm = Xiami.from_header(buffer.subarray(0, 0x10)); + const { copyPlainLength } = xm; + const audioBuffer = buffer.slice(0x10); + + for (const [block] of chunkBuffer(audioBuffer.subarray(copyPlainLength))) { + xm.decrypt(block); + } + xm.free(); + + return { + cipherName: this.cipherName, + status: Status.OK, + data: audioBuffer, + }; + } + + public static make() { + return new XiamiDecipher(); + } +}