diff --git a/src/decrypt-worker/crypto/CryptoFactory.ts b/src/decrypt-worker/crypto/CryptoFactory.ts index 00ec3c9..afe390f 100644 --- a/src/decrypt-worker/crypto/CryptoFactory.ts +++ b/src/decrypt-worker/crypto/CryptoFactory.ts @@ -3,6 +3,7 @@ import { CryptoFactory } from './CryptoBase'; import { QMC1Crypto } from './qmc/qmc_v1'; import { QMC2Crypto } from './qmc/qmc_v2'; import { XiamiCrypto } from './xiami/xiami'; +import { XimalayaAndroidCrypto } from './xmly/xmly_android'; export const allCryptoFactories: CryptoFactory[] = [ // Xiami (*.xm) @@ -16,4 +17,8 @@ export const allCryptoFactories: CryptoFactory[] = [ // QMCv1 (*.qmcflac) QMC1Crypto.make, + + // Ximalaya (Android) + XimalayaAndroidCrypto.makeX2M, + XimalayaAndroidCrypto.makeX3M, ]; diff --git a/src/decrypt-worker/crypto/xmly/xmly_android.key.ts b/src/decrypt-worker/crypto/xmly/xmly_android.key.ts new file mode 100644 index 0000000..956de25 --- /dev/null +++ b/src/decrypt-worker/crypto/xmly/xmly_android.key.ts @@ -0,0 +1,17 @@ +export interface XimalayaAndroidKey { + contentKey: string; + init: number; + step: number; +} + +export const XimalayaX2MKey: XimalayaAndroidKey = { + contentKey: 'xmly', + init: 0.615243, + step: 3.837465, +}; + +export const XimalayaX3MKey: XimalayaAndroidKey = { + contentKey: '3989d111aad5613940f4fc44b639b292', + init: 0.726354, + step: 3.948576, +}; diff --git a/src/decrypt-worker/crypto/xmly/xmly_android.ts b/src/decrypt-worker/crypto/xmly/xmly_android.ts new file mode 100644 index 0000000..b6ff4c3 --- /dev/null +++ b/src/decrypt-worker/crypto/xmly/xmly_android.ts @@ -0,0 +1,29 @@ +import { transformBlob } from '~/decrypt-worker/util/transformBlob'; +import type { CryptoBase } from '../CryptoBase.js'; +import { XimalayaAndroidKey, XimalayaX2MKey, XimalayaX3MKey } from './xmly_android.key.js'; + +export class XimalayaAndroidCrypto implements CryptoBase { + cryptoName = 'Ximalaya/Android'; + checkByDecryptHeader = true; + constructor(private key: XimalayaAndroidKey) {} + + async decrypt(buffer: ArrayBuffer): Promise { + const { contentKey, init, step } = this.key; + return transformBlob(buffer, (p) => { + const transformer = p.make.XimalayaAndroid(init, step, contentKey); + if (!transformer) { + throw new Error('could not make xmly transformer, is key invalid?'); + } + + return transformer; + }); + } + + public static makeX2M() { + return new XimalayaAndroidCrypto(XimalayaX2MKey); + } + + public static makeX3M() { + return new XimalayaAndroidCrypto(XimalayaX3MKey); + } +}