Compare commits

..

No commits in common. "365290905c9f2046afdbd681813e6ec015a98dd7" and "8e2d13f54aa1a38dc49f71d2c2dce4eed54cd69e" have entirely different histories.

5 changed files with 21 additions and 53 deletions

View File

@ -21,7 +21,7 @@
"@chakra-ui/react": "^2.7.0", "@chakra-ui/react": "^2.7.0",
"@emotion/react": "^11.11.0", "@emotion/react": "^11.11.0",
"@emotion/styled": "^11.11.0", "@emotion/styled": "^11.11.0",
"@jixun/libparakeet": "0.1.2", "@jixun/libparakeet": "0.1.1",
"@reduxjs/toolkit": "^1.9.5", "@reduxjs/toolkit": "^1.9.5",
"framer-motion": "^10.12.16", "framer-motion": "^10.12.16",
"immer": "^10.0.2", "immer": "^10.0.2",

View File

@ -21,8 +21,8 @@ dependencies:
specifier: ^11.11.0 specifier: ^11.11.0
version: 11.11.0(@emotion/react@11.11.0)(@types/react@18.2.7)(react@18.2.0) version: 11.11.0(@emotion/react@11.11.0)(@types/react@18.2.7)(react@18.2.0)
'@jixun/libparakeet': '@jixun/libparakeet':
specifier: 0.1.2 specifier: 0.1.1
version: 0.1.2 version: 0.1.1
'@reduxjs/toolkit': '@reduxjs/toolkit':
specifier: ^1.9.5 specifier: ^1.9.5
version: 1.9.5(react-redux@8.0.5)(react@18.2.0) version: 1.9.5(react-redux@8.0.5)(react@18.2.0)
@ -3101,8 +3101,8 @@ packages:
chalk: 4.1.2 chalk: 4.1.2
dev: true dev: true
/@jixun/libparakeet@0.1.2: /@jixun/libparakeet@0.1.1:
resolution: {integrity: sha512-PxhA7EtC3ss3ACxaGckgD41wGAhWllfy80LfL8GMiXkdXMipgcfFfeEcJBBpvTZ/FlDfoFLDJSOz0uculhsgnQ==} resolution: {integrity: sha512-1e6hFsVga3eDkQvUY/wsX/F1R94SzcrO2u7wK/KPaCs9MD0hej+cgraOixp+VDy4uqGSPKU5iNP1a8hCYze2rg==}
dev: false dev: false
/@jridgewell/gen-mapping@0.3.3: /@jridgewell/gen-mapping@0.3.3:
@ -4069,8 +4069,8 @@ packages:
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true hasBin: true
dependencies: dependencies:
caniuse-lite: 1.0.30001498 caniuse-lite: 1.0.30001497
electron-to-chromium: 1.4.427 electron-to-chromium: 1.4.426
node-releases: 2.0.12 node-releases: 2.0.12
update-browserslist-db: 1.0.11(browserslist@4.21.7) update-browserslist-db: 1.0.11(browserslist@4.21.7)
dev: true dev: true
@ -4123,8 +4123,8 @@ packages:
resolution: {integrity: sha512-x1mgZEXK8jHIfAxm+xgdpHpk50IN3z3q3zP261/WS+uvePxW8izXuCu6AHz0lkuYTlATDehiZ/tNyYBdSQsOUQ==} resolution: {integrity: sha512-x1mgZEXK8jHIfAxm+xgdpHpk50IN3z3q3zP261/WS+uvePxW8izXuCu6AHz0lkuYTlATDehiZ/tNyYBdSQsOUQ==}
dev: true dev: true
/caniuse-lite@1.0.30001498: /caniuse-lite@1.0.30001497:
resolution: {integrity: sha512-LFInN2zAwx3ANrGCDZ5AKKJroHqNKyjXitdV5zRIVIaQlXKj3GmxUKagoKsjqUfckpAObPCEWnk5EeMlyMWcgw==} resolution: {integrity: sha512-I4/duVK4wL6rAK/aKZl3HXB4g+lIZvaT4VLAn2rCgJ38jVLb0lv2Xug6QuqmxXFVRJMF74SPPWPJ/1Sdm3vCzw==}
dev: true dev: true
/chai@4.3.7: /chai@4.3.7:
@ -4478,8 +4478,8 @@ packages:
resolution: {integrity: sha512-5VXLW4Qw89vM2WTICHua/y8v7fKGDRVa2VPOtBB9IpLvW316B+xd8yD1wTmLPY2ot/00P/qt87xdolj4aG/Lzg==} resolution: {integrity: sha512-5VXLW4Qw89vM2WTICHua/y8v7fKGDRVa2VPOtBB9IpLvW316B+xd8yD1wTmLPY2ot/00P/qt87xdolj4aG/Lzg==}
dev: true dev: true
/electron-to-chromium@1.4.427: /electron-to-chromium@1.4.426:
resolution: {integrity: sha512-HK3r9l+Jm8dYAm1ctXEWIC+hV60zfcjS9UA5BDlYvnI5S7PU/yytjpvSrTNrSSRRkuu3tDyZhdkwIczh+0DWaw==} resolution: {integrity: sha512-dWuNH+XUT9hdFHASfMpcZGW5kUyJvllumJkXaXiswuCkoaFIFI89aykBPuHEi1YUWQGRCqvIO0BUdmeFJ4W4Ww==}
dev: true dev: true
/emoji-regex@8.0.0: /emoji-regex@8.0.0:

View File

@ -1,7 +1,7 @@
import { CryptoFactory } from './CryptoBase'; import { CryptoFactory } from './CryptoBase';
import { QMC1Crypto } from './qmc/qmc_v1'; import { QMC1Crypto } from './qmc/qmc_v1';
import { QMC2Crypto, QMC2CryptoWithKey } from './qmc/qmc_v2'; import { QMC2Crypto } from './qmc/qmc_v2';
import { XiamiCrypto } from './xiami/xiami'; import { XiamiCrypto } from './xiami/xiami';
import { KGMCrypto } from './kgm/kgm_pc'; import { KGMCrypto } from './kgm/kgm_pc';
import { NCMCrypto } from './ncm/ncm_pc'; import { NCMCrypto } from './ncm/ncm_pc';
@ -14,7 +14,6 @@ export const allCryptoFactories: CryptoFactory[] = [
XiamiCrypto.make, XiamiCrypto.make,
// QMCv2 (*.mflac) // QMCv2 (*.mflac)
QMC2CryptoWithKey.make,
QMC2Crypto.make, QMC2Crypto.make,
// NCM (*.ncm) // NCM (*.ncm)

View File

@ -1,49 +1,16 @@
import { transformBlob } from '~/decrypt-worker/util/transformBlob'; import { transformBlob } from '~/decrypt-worker/util/transformBlob';
import type { CryptoBase } from '../CryptoBase'; import type { CryptoBase } from '../CryptoBase';
import type { DecryptCommandOptions } from '~/decrypt-worker/types.ts';
import { SEED, ENC_V2_KEY_1, ENC_V2_KEY_2 } from './qmc_v2.key.ts'; import { SEED, ENC_V2_KEY_1, ENC_V2_KEY_2 } from './qmc_v2.key.ts';
import { fetchParakeet } from '@jixun/libparakeet';
export class QMC2Crypto implements CryptoBase { export class QMC2Crypto implements CryptoBase {
cryptoName = 'QMC/v2'; cryptoName = 'QMC/v2';
checkByDecryptHeader = false; checkByDecryptHeader = false;
async decrypt(buffer: ArrayBuffer): Promise<Blob> { async decrypt(buffer: ArrayBuffer): Promise<Blob> {
// FIXME: Move the cleanup to transformBlob return transformBlob(buffer, (p) => p.make.QMCv2(p.make.QMCv2FooterParser(SEED, ENC_V2_KEY_1, ENC_V2_KEY_2)));
const mod = await fetchParakeet();
const footerParser = mod.make.QMCv2FooterParser(SEED, ENC_V2_KEY_1, ENC_V2_KEY_2);
return transformBlob(buffer, (p) => p.make.QMCv2(footerParser)).finally(() => {
footerParser.delete();
});
} }
public static make() { public static make() {
return new QMC2Crypto(); return new QMC2Crypto();
} }
} }
export class QMC2CryptoWithKey implements CryptoBase {
cryptoName = 'QMC/v2 (key)';
checkByDecryptHeader = true;
async checkBySignature(_buffer: ArrayBuffer, options: DecryptCommandOptions): Promise<boolean> {
return Boolean(options.qmc2Key);
}
async decrypt(buffer: ArrayBuffer, options: DecryptCommandOptions): Promise<Blob> {
if (!options.qmc2Key) {
throw new Error('key was not provided');
}
// FIXME: Move the cleanup to transformBlob
const mod = await fetchParakeet();
const textEncoder = new TextEncoder();
const key = textEncoder.encode(options.qmc2Key);
const keyCrypto = mod.make.QMCv2KeyCrypto(SEED, ENC_V2_KEY_1, ENC_V2_KEY_2);
return transformBlob(buffer, (p) => p.make.QMCv2EKey(key, keyCrypto));
}
public static make() {
return new QMC2CryptoWithKey();
}
}

View File

@ -25,7 +25,7 @@ import { useDispatch, useSelector } from 'react-redux';
import { qmc2AddKey, qmc2ClearKeys, qmc2DeleteKey, qmc2UpdateKey } from '../settingsSlice'; import { qmc2AddKey, qmc2ClearKeys, qmc2DeleteKey, qmc2UpdateKey } from '../settingsSlice';
import { selectStagingQMCv2Settings } from '../settingsSelector'; import { selectStagingQMCv2Settings } from '../settingsSelector';
import React from 'react'; import React from 'react';
import { MdAdd, MdDelete, MdDeleteForever, MdExpandMore, MdFileUpload, MdVpnKey } from 'react-icons/md'; import { MdAdd, MdAndroid, MdDelete, MdDeleteForever, MdExpandMore, MdFileUpload, MdVpnKey } from 'react-icons/md';
export function PanelQMCv2Key() { export function PanelQMCv2Key() {
const dispatch = useDispatch(); const dispatch = useDispatch();
@ -51,12 +51,14 @@ export function PanelQMCv2Key() {
<Menu> <Menu>
<MenuButton as={IconButton} icon={<MdExpandMore />}></MenuButton> <MenuButton as={IconButton} icon={<MdExpandMore />}></MenuButton>
<MenuList> <MenuList>
{/* 目前的想法是弹出一个 modal给用户一些信息如期待的格式、如何导出或寻找对应的文件 */} <MenuItem onClick={() => alert('TODO!')} icon={<Icon as={MdFileUpload} boxSize={5} />}>
{/* 但是这样的话就不太方便放在这个分支里面做了,下次一定。 */} JSON
<MenuItem hidden onClick={() => alert('TODO!')} icon={<Icon as={MdFileUpload} boxSize={5} />}>
</MenuItem> </MenuItem>
<MenuDivider hidden /> {/* 需要加入 SQL.js 再处理 */}
<MenuItem hidden onClick={() => alert('TODO!')} icon={<Icon as={MdAndroid} boxSize={5} />}>
</MenuItem>
<MenuDivider />
<MenuItem color="red" onClick={clearAll} icon={<Icon as={MdDeleteForever} boxSize={5} />}> <MenuItem color="red" onClick={clearAll} icon={<Icon as={MdDeleteForever} boxSize={5} />}>
</MenuItem> </MenuItem>