mirror of
https://github.com/imsyy/SPlayer.git
synced 2025-11-25 03:14:57 +08:00
574 lines
8.7 KiB
JavaScript
574 lines
8.7 KiB
JavaScript
/*
|
|
Thanks to
|
|
https://github.com/XuShaohua/kwplayer/blob/master/kuwo/DES.py
|
|
https://github.com/Levi233/MusicPlayer/blob/master/app/src/main/java/com/chenhao/musicplayer/utils/crypt/KuwoDES.java
|
|
*/
|
|
|
|
const Long = (n) => {
|
|
const bN = BigInt(n);
|
|
|
|
return {
|
|
low: Number(bN),
|
|
valueOf: () => bN.valueOf(),
|
|
toString: () => bN.toString(),
|
|
not: () => Long(~bN),
|
|
isNegative: () => bN < 0,
|
|
or: (x) => Long(bN | BigInt(x)),
|
|
and: (x) => Long(bN & BigInt(x)),
|
|
xor: (x) => Long(bN ^ BigInt(x)),
|
|
equals: (x) => bN === BigInt(x),
|
|
multiply: (x) => Long(bN * BigInt(x)),
|
|
shiftLeft: (x) => Long(bN << BigInt(x)),
|
|
shiftRight: (x) => Long(bN >> BigInt(x)),
|
|
};
|
|
};
|
|
|
|
const range = (n) => Array.from(new Array(n).keys());
|
|
const power = (base, index) =>
|
|
Array(index)
|
|
.fill(null)
|
|
.reduce((result) => result.multiply(base), Long(1));
|
|
const LongArray = (...array) => array.map((n) => (n === -1 ? Long(-1, -1) : Long(n)));
|
|
|
|
// EXPANSION
|
|
const arrayE = LongArray(
|
|
31,
|
|
0,
|
|
1,
|
|
2,
|
|
3,
|
|
4,
|
|
-1,
|
|
-1,
|
|
3,
|
|
4,
|
|
5,
|
|
6,
|
|
7,
|
|
8,
|
|
-1,
|
|
-1,
|
|
7,
|
|
8,
|
|
9,
|
|
10,
|
|
11,
|
|
12,
|
|
-1,
|
|
-1,
|
|
11,
|
|
12,
|
|
13,
|
|
14,
|
|
15,
|
|
16,
|
|
-1,
|
|
-1,
|
|
15,
|
|
16,
|
|
17,
|
|
18,
|
|
19,
|
|
20,
|
|
-1,
|
|
-1,
|
|
19,
|
|
20,
|
|
21,
|
|
22,
|
|
23,
|
|
24,
|
|
-1,
|
|
-1,
|
|
23,
|
|
24,
|
|
25,
|
|
26,
|
|
27,
|
|
28,
|
|
-1,
|
|
-1,
|
|
27,
|
|
28,
|
|
29,
|
|
30,
|
|
31,
|
|
30,
|
|
-1,
|
|
-1,
|
|
);
|
|
|
|
// INITIAL_PERMUTATION
|
|
const arrayIP = LongArray(
|
|
57,
|
|
49,
|
|
41,
|
|
33,
|
|
25,
|
|
17,
|
|
9,
|
|
1,
|
|
59,
|
|
51,
|
|
43,
|
|
35,
|
|
27,
|
|
19,
|
|
11,
|
|
3,
|
|
61,
|
|
53,
|
|
45,
|
|
37,
|
|
29,
|
|
21,
|
|
13,
|
|
5,
|
|
63,
|
|
55,
|
|
47,
|
|
39,
|
|
31,
|
|
23,
|
|
15,
|
|
7,
|
|
56,
|
|
48,
|
|
40,
|
|
32,
|
|
24,
|
|
16,
|
|
8,
|
|
0,
|
|
58,
|
|
50,
|
|
42,
|
|
34,
|
|
26,
|
|
18,
|
|
10,
|
|
2,
|
|
60,
|
|
52,
|
|
44,
|
|
36,
|
|
28,
|
|
20,
|
|
12,
|
|
4,
|
|
62,
|
|
54,
|
|
46,
|
|
38,
|
|
30,
|
|
22,
|
|
14,
|
|
6,
|
|
);
|
|
|
|
// INVERSE_PERMUTATION
|
|
const arrayIP_1 = LongArray(
|
|
39,
|
|
7,
|
|
47,
|
|
15,
|
|
55,
|
|
23,
|
|
63,
|
|
31,
|
|
38,
|
|
6,
|
|
46,
|
|
14,
|
|
54,
|
|
22,
|
|
62,
|
|
30,
|
|
37,
|
|
5,
|
|
45,
|
|
13,
|
|
53,
|
|
21,
|
|
61,
|
|
29,
|
|
36,
|
|
4,
|
|
44,
|
|
12,
|
|
52,
|
|
20,
|
|
60,
|
|
28,
|
|
35,
|
|
3,
|
|
43,
|
|
11,
|
|
51,
|
|
19,
|
|
59,
|
|
27,
|
|
34,
|
|
2,
|
|
42,
|
|
10,
|
|
50,
|
|
18,
|
|
58,
|
|
26,
|
|
33,
|
|
1,
|
|
41,
|
|
9,
|
|
49,
|
|
17,
|
|
57,
|
|
25,
|
|
32,
|
|
0,
|
|
40,
|
|
8,
|
|
48,
|
|
16,
|
|
56,
|
|
24,
|
|
);
|
|
|
|
// ROTATES
|
|
const arrayLs = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1];
|
|
const arrayLsMask = LongArray(0, 0x100001, 0x300003);
|
|
const arrayMask = range(64).map((n) => power(2, n));
|
|
arrayMask[arrayMask.length - 1] = arrayMask[arrayMask.length - 1].multiply(-1);
|
|
|
|
// PERMUTATION
|
|
const arrayP = LongArray(
|
|
15,
|
|
6,
|
|
19,
|
|
20,
|
|
28,
|
|
11,
|
|
27,
|
|
16,
|
|
0,
|
|
14,
|
|
22,
|
|
25,
|
|
4,
|
|
17,
|
|
30,
|
|
9,
|
|
1,
|
|
7,
|
|
23,
|
|
13,
|
|
31,
|
|
26,
|
|
2,
|
|
8,
|
|
18,
|
|
12,
|
|
29,
|
|
5,
|
|
21,
|
|
10,
|
|
3,
|
|
24,
|
|
);
|
|
|
|
// PERMUTED_CHOICE1
|
|
const arrayPC_1 = LongArray(
|
|
56,
|
|
48,
|
|
40,
|
|
32,
|
|
24,
|
|
16,
|
|
8,
|
|
0,
|
|
57,
|
|
49,
|
|
41,
|
|
33,
|
|
25,
|
|
17,
|
|
9,
|
|
1,
|
|
58,
|
|
50,
|
|
42,
|
|
34,
|
|
26,
|
|
18,
|
|
10,
|
|
2,
|
|
59,
|
|
51,
|
|
43,
|
|
35,
|
|
62,
|
|
54,
|
|
46,
|
|
38,
|
|
30,
|
|
22,
|
|
14,
|
|
6,
|
|
61,
|
|
53,
|
|
45,
|
|
37,
|
|
29,
|
|
21,
|
|
13,
|
|
5,
|
|
60,
|
|
52,
|
|
44,
|
|
36,
|
|
28,
|
|
20,
|
|
12,
|
|
4,
|
|
27,
|
|
19,
|
|
11,
|
|
3,
|
|
);
|
|
|
|
// PERMUTED_CHOICE2
|
|
const arrayPC_2 = LongArray(
|
|
13,
|
|
16,
|
|
10,
|
|
23,
|
|
0,
|
|
4,
|
|
-1,
|
|
-1,
|
|
2,
|
|
27,
|
|
14,
|
|
5,
|
|
20,
|
|
9,
|
|
-1,
|
|
-1,
|
|
22,
|
|
18,
|
|
11,
|
|
3,
|
|
25,
|
|
7,
|
|
-1,
|
|
-1,
|
|
15,
|
|
6,
|
|
26,
|
|
19,
|
|
12,
|
|
1,
|
|
-1,
|
|
-1,
|
|
40,
|
|
51,
|
|
30,
|
|
36,
|
|
46,
|
|
54,
|
|
-1,
|
|
-1,
|
|
29,
|
|
39,
|
|
50,
|
|
44,
|
|
32,
|
|
47,
|
|
-1,
|
|
-1,
|
|
43,
|
|
48,
|
|
38,
|
|
55,
|
|
33,
|
|
52,
|
|
-1,
|
|
-1,
|
|
45,
|
|
41,
|
|
49,
|
|
35,
|
|
28,
|
|
31,
|
|
-1,
|
|
-1,
|
|
);
|
|
|
|
const matrixNSBox = [
|
|
[
|
|
14, 4, 3, 15, 2, 13, 5, 3, 13, 14, 6, 9, 11, 2, 0, 5, 4, 1, 10, 12, 15, 6, 9, 10, 1, 8, 12, 7,
|
|
8, 11, 7, 0, 0, 15, 10, 5, 14, 4, 9, 10, 7, 8, 12, 3, 13, 1, 3, 6, 15, 12, 6, 11, 2, 9, 5, 0, 4,
|
|
2, 11, 14, 1, 7, 8, 13,
|
|
],
|
|
[
|
|
15, 0, 9, 5, 6, 10, 12, 9, 8, 7, 2, 12, 3, 13, 5, 2, 1, 14, 7, 8, 11, 4, 0, 3, 14, 11, 13, 6, 4,
|
|
1, 10, 15, 3, 13, 12, 11, 15, 3, 6, 0, 4, 10, 1, 7, 8, 4, 11, 14, 13, 8, 0, 6, 2, 15, 9, 5, 7,
|
|
1, 10, 12, 14, 2, 5, 9,
|
|
],
|
|
[
|
|
10, 13, 1, 11, 6, 8, 11, 5, 9, 4, 12, 2, 15, 3, 2, 14, 0, 6, 13, 1, 3, 15, 4, 10, 14, 9, 7, 12,
|
|
5, 0, 8, 7, 13, 1, 2, 4, 3, 6, 12, 11, 0, 13, 5, 14, 6, 8, 15, 2, 7, 10, 8, 15, 4, 9, 11, 5, 9,
|
|
0, 14, 3, 10, 7, 1, 12,
|
|
],
|
|
[
|
|
7, 10, 1, 15, 0, 12, 11, 5, 14, 9, 8, 3, 9, 7, 4, 8, 13, 6, 2, 1, 6, 11, 12, 2, 3, 0, 5, 14, 10,
|
|
13, 15, 4, 13, 3, 4, 9, 6, 10, 1, 12, 11, 0, 2, 5, 0, 13, 14, 2, 8, 15, 7, 4, 15, 1, 10, 7, 5,
|
|
6, 12, 11, 3, 8, 9, 14,
|
|
],
|
|
[
|
|
2, 4, 8, 15, 7, 10, 13, 6, 4, 1, 3, 12, 11, 7, 14, 0, 12, 2, 5, 9, 10, 13, 0, 3, 1, 11, 15, 5,
|
|
6, 8, 9, 14, 14, 11, 5, 6, 4, 1, 3, 10, 2, 12, 15, 0, 13, 2, 8, 5, 11, 8, 0, 15, 7, 14, 9, 4,
|
|
12, 7, 10, 9, 1, 13, 6, 3,
|
|
],
|
|
[
|
|
12, 9, 0, 7, 9, 2, 14, 1, 10, 15, 3, 4, 6, 12, 5, 11, 1, 14, 13, 0, 2, 8, 7, 13, 15, 5, 4, 10,
|
|
8, 3, 11, 6, 10, 4, 6, 11, 7, 9, 0, 6, 4, 2, 13, 1, 9, 15, 3, 8, 15, 3, 1, 14, 12, 5, 11, 0, 2,
|
|
12, 14, 7, 5, 10, 8, 13,
|
|
],
|
|
[
|
|
4, 1, 3, 10, 15, 12, 5, 0, 2, 11, 9, 6, 8, 7, 6, 9, 11, 4, 12, 15, 0, 3, 10, 5, 14, 13, 7, 8,
|
|
13, 14, 1, 2, 13, 6, 14, 9, 4, 1, 2, 14, 11, 13, 5, 0, 1, 10, 8, 3, 0, 11, 3, 5, 9, 4, 15, 2, 7,
|
|
8, 12, 15, 10, 7, 6, 12,
|
|
],
|
|
[
|
|
13, 7, 10, 0, 6, 9, 5, 15, 8, 4, 3, 10, 11, 14, 12, 5, 2, 11, 9, 6, 15, 12, 0, 3, 4, 1, 14, 13,
|
|
1, 2, 7, 8, 1, 2, 12, 15, 10, 4, 0, 3, 13, 14, 6, 9, 7, 8, 9, 6, 15, 1, 5, 12, 3, 10, 14, 5, 8,
|
|
7, 11, 0, 4, 13, 2, 11,
|
|
],
|
|
];
|
|
|
|
const bitTransform = (arrInt, n, l) => {
|
|
// int[], int, long : long
|
|
let l2 = Long(0);
|
|
range(n).forEach((i) => {
|
|
if (arrInt[i].isNegative() || l.and(arrayMask[arrInt[i].low]).equals(0)) return;
|
|
l2 = l2.or(arrayMask[i]);
|
|
});
|
|
return l2;
|
|
};
|
|
|
|
const DES64 = (longs, l) => {
|
|
const pR = range(8).map(() => Long(0));
|
|
const pSource = [Long(0), Long(0)];
|
|
let L = Long(0);
|
|
let R = Long(0);
|
|
let out = bitTransform(arrayIP, 64, l);
|
|
pSource[0] = out.and(0xffffffff);
|
|
pSource[1] = out.and(-4294967296).shiftRight(32);
|
|
|
|
range(16).forEach((i) => {
|
|
let SOut = Long(0);
|
|
|
|
R = Long(pSource[1]);
|
|
R = bitTransform(arrayE, 64, R);
|
|
R = R.xor(longs[i]);
|
|
range(8).forEach((j) => {
|
|
pR[j] = R.shiftRight(j * 8).and(255);
|
|
});
|
|
range(8)
|
|
.reverse()
|
|
.forEach((sbi) => {
|
|
SOut = SOut.shiftLeft(4).or(matrixNSBox[sbi][pR[sbi]]);
|
|
});
|
|
R = bitTransform(arrayP, 32, SOut);
|
|
L = Long(pSource[0]);
|
|
pSource[0] = Long(pSource[1]);
|
|
pSource[1] = L.xor(R);
|
|
});
|
|
pSource.reverse();
|
|
out = pSource[1].shiftLeft(32).and(-4294967296).or(pSource[0].and(0xffffffff));
|
|
out = bitTransform(arrayIP_1, 64, out);
|
|
return out;
|
|
};
|
|
|
|
const subKeys = (l, longs, n) => {
|
|
// long, long[], int
|
|
let l2 = bitTransform(arrayPC_1, 56, l);
|
|
range(16).forEach((i) => {
|
|
l2 = l2
|
|
.and(arrayLsMask[arrayLs[i]])
|
|
.shiftLeft(28 - arrayLs[i])
|
|
.or(l2.and(arrayLsMask[arrayLs[i]].not()).shiftRight(arrayLs[i]));
|
|
longs[i] = bitTransform(arrayPC_2, 64, l2);
|
|
});
|
|
if (n === 1) {
|
|
range(8).forEach((j) => {
|
|
[longs[j], longs[15 - j]] = [longs[15 - j], longs[j]];
|
|
});
|
|
}
|
|
};
|
|
|
|
const crypt = (msg, key, mode) => {
|
|
// 处理密钥块
|
|
let l = Long(0);
|
|
range(8).forEach((i) => {
|
|
l = Long(key[i])
|
|
.shiftLeft(i * 8)
|
|
.or(l);
|
|
});
|
|
|
|
const j = Math.floor(msg.length / 8);
|
|
// arrLong1 存放的是转换后的密钥块, 在解密时只需要把这个密钥块反转就行了
|
|
|
|
const arrLong1 = range(16).map(() => Long(0));
|
|
subKeys(l, arrLong1, mode);
|
|
|
|
// arrLong2 存放的是前部分的明文
|
|
const arrLong2 = range(j).map(() => Long(0));
|
|
|
|
range(j).forEach((m) => {
|
|
range(8).forEach((n) => {
|
|
arrLong2[m] = Long(msg[n + m * 8])
|
|
.shiftLeft(n * 8)
|
|
.or(arrLong2[m]);
|
|
});
|
|
});
|
|
|
|
// 用于存放密文
|
|
const arrLong3 = range(Math.floor((1 + 8 * (j + 1)) / 8)).map(() => Long(0));
|
|
|
|
// 计算前部的数据块(除了最后一部分)
|
|
range(j).forEach((i1) => {
|
|
arrLong3[i1] = DES64(arrLong1, arrLong2[i1]);
|
|
});
|
|
|
|
// 保存多出来的字节
|
|
const arrByte1 = msg.slice(j * 8);
|
|
let l2 = Long(0);
|
|
|
|
range(msg.length % 8).forEach((i1) => {
|
|
l2 = Long(arrByte1[i1])
|
|
.shiftLeft(i1 * 8)
|
|
.or(l2);
|
|
});
|
|
|
|
// 计算多出的那一位(最后一位)
|
|
if (arrByte1.length || mode === 0) arrLong3[j] = DES64(arrLong1, l2); // 解密不需要
|
|
|
|
// 将密文转为字节型
|
|
const arrByte2 = range(8 * arrLong3.length).map(() => 0);
|
|
let i4 = 0;
|
|
arrLong3.forEach((l3) => {
|
|
range(8).forEach((i6) => {
|
|
arrByte2[i4] = l3.shiftRight(i6 * 8).and(255).low;
|
|
i4 += 1;
|
|
});
|
|
});
|
|
return Buffer.from(arrByte2);
|
|
};
|
|
|
|
const SECRET_KEY = Buffer.from("ylzsxkwm");
|
|
export const encrypt = (msg) => crypt(msg, SECRET_KEY, 0);
|
|
export const decrypt = (msg) => crypt(msg, SECRET_KEY, 1);
|
|
export const encryptQuery = (query) => encrypt(Buffer.from(query)).toString("base64");
|