test(joox): Added basic sanity test for joox encryption.

(cherry picked from commit 48b8194363264a0276006deaa3c956970a543627)
master
Jixun Wu 8 months ago committed by MengYX
parent c098b73617
commit a73212f026
No known key found for this signature in database
GPG Key ID: E63F9C7303E8F604
  1. 3
      jest.config.js
  2. 14
      package-lock.json
  3. 2
      package.json
  4. 2
      src/__test__/setup_jest.js
  5. BIN
      src/decrypt/__test__/fixture/joox_1.bin
  6. 52
      src/decrypt/__test__/joox.test.ts
  7. 1
      src/utils/__mocks__/qm_meta.ts
  8. 4
      src/utils/__mocks__/storage.ts

@ -1,4 +1,7 @@
module.exports = {
setupFilesAfterEnv: [
'./src/__test__/setup_jest.js'
],
moduleNameMapper: {
'@/(.*)': '<rootDir>/src/$1'
}

14
package-lock.json generated

@ -12,7 +12,7 @@
"dependencies": {
"@babel/preset-typescript": "^7.16.5",
"@jixun/qmc2-crypto": "^0.0.5-R4",
"@unlock-music/joox-crypto": "^0.0.1-R4",
"@unlock-music/joox-crypto": "^0.0.1-R5",
"base64-js": "^1.5.1",
"browser-id3-writer": "^4.4.0",
"core-js": "^3.16.0",
@ -3487,9 +3487,9 @@
"dev": true
},
"node_modules/@unlock-music/joox-crypto": {
"version": "0.0.1-R4",
"resolved": "https://registry.npmjs.org/@unlock-music/joox-crypto/-/joox-crypto-0.0.1-R4.tgz",
"integrity": "sha512-5UScjXtH9J3mAy9sRBjNn5kkEuT7dHvH3YQYKRyOfF3EKxLkWsJP0Fuw/tZtylLPL5beI3qDBzyHf5mVrpdH4A==",
"version": "0.0.1-R5",
"resolved": "https://registry.npmjs.org/@unlock-music/joox-crypto/-/joox-crypto-0.0.1-R5.tgz",
"integrity": "sha512-+FhGT4bjzfb1Q7dAwHps/XqbqXrRA6Qg7pkDPzyXfeRmQocAySQ/dekojxkaFBf7ZX5ToIAopwxkKZ5NFt5bFw==",
"dependencies": {
"crypto-js": "^4.1.1"
},
@ -23635,9 +23635,9 @@
"dev": true
},
"@unlock-music/joox-crypto": {
"version": "0.0.1-R4",
"resolved": "https://registry.npmjs.org/@unlock-music/joox-crypto/-/joox-crypto-0.0.1-R4.tgz",
"integrity": "sha512-5UScjXtH9J3mAy9sRBjNn5kkEuT7dHvH3YQYKRyOfF3EKxLkWsJP0Fuw/tZtylLPL5beI3qDBzyHf5mVrpdH4A==",
"version": "0.0.1-R5",
"resolved": "https://registry.npmjs.org/@unlock-music/joox-crypto/-/joox-crypto-0.0.1-R5.tgz",
"integrity": "sha512-+FhGT4bjzfb1Q7dAwHps/XqbqXrRA6Qg7pkDPzyXfeRmQocAySQ/dekojxkaFBf7ZX5ToIAopwxkKZ5NFt5bFw==",
"requires": {
"crypto-js": "^4.1.1"
}

@ -22,7 +22,7 @@
"dependencies": {
"@babel/preset-typescript": "^7.16.5",
"@jixun/qmc2-crypto": "^0.0.5-R4",
"@unlock-music/joox-crypto": "^0.0.1-R4",
"@unlock-music/joox-crypto": "^0.0.1-R5",
"base64-js": "^1.5.1",
"browser-id3-writer": "^4.4.0",
"core-js": "^3.16.0",

@ -0,0 +1,2 @@
// Polyfill for node.
global.Blob = global.Blob || require("node:buffer").Blob;

@ -0,0 +1,52 @@
import fs from 'fs';
import { storage } from '@/utils/storage';
import { Decrypt as decryptJoox } from '../joox';
import { extractQQMusicMeta as extractQQMusicMetaOrig } from '@/utils/qm_meta';
jest.mock('@/utils/storage');
jest.mock('@/utils/qm_meta');
const loadJooxUUID = storage.loadJooxUUID as jest.MockedFunction<typeof storage.loadJooxUUID>;
const extractQQMusicMeta = extractQQMusicMetaOrig as jest.MockedFunction<typeof extractQQMusicMetaOrig>;
const TEST_UUID_ZEROS = ''.padStart(32, '0');
const encryptedFile1 = fs.readFileSync(__dirname + '/fixture/joox_1.bin');
describe('decrypt/joox', () => {
it('should be able to decrypt sample file (v4)', async () => {
loadJooxUUID.mockResolvedValue(TEST_UUID_ZEROS);
extractQQMusicMeta.mockImplementationOnce(async (blob: Blob) => {
return {
title: 'unused',
album: 'unused',
blob: blob,
artist: 'unused',
imgUrl: 'https://github.com/unlock-music',
};
});
const result = await decryptJoox(new Blob([encryptedFile1]), 'test.bin', 'bin');
const resultBuf = await result.blob.arrayBuffer();
expect(resultBuf).toEqual(Buffer.from('Hello World', 'utf-8').buffer);
});
it('should reject E!99 files', async () => {
loadJooxUUID.mockResolvedValue(TEST_UUID_ZEROS);
const input = new Blob([Buffer.from('E!99....')]);
await expect(decryptJoox(input, 'test.bin', 'bin')).rejects.toThrow('不支持的 joox 加密格式');
});
it('should reject empty uuid', async () => {
loadJooxUUID.mockResolvedValue('');
const input = new Blob([encryptedFile1]);
await expect(decryptJoox(input, 'test.bin', 'bin')).rejects.toThrow('UUID');
});
it('should reject invalid uuid', async () => {
loadJooxUUID.mockResolvedValue('hello!');
const input = new Blob([encryptedFile1]);
await expect(decryptJoox(input, 'test.bin', 'bin')).rejects.toThrow('UUID');
});
});

@ -0,0 +1 @@
export const extractQQMusicMeta = jest.fn();

@ -0,0 +1,4 @@
export const storage = {
loadJooxUUID: jest.fn(),
saveJooxUUID: jest.fn(),
};
Loading…
Cancel
Save