qqmusic-api-enhanced 1.0.6 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +20 -0
  2. package/package.json +9 -1
  3. package/util/des.ts +336 -336
package/README.md CHANGED
@@ -122,6 +122,8 @@ import {
122
122
  hash33, // 经典 hash33 哈希计算
123
123
  getGtk, // 从 skey 计算 g_tk
124
124
  getGuid, // 生成设备与会话 32 位 GUID
125
+ getStableGuid, // 由账号/二维码会话派生稳定设备 GUID
126
+ mergeLoginPayloadCookies, // 合并登录/续期响应中的凭证字段
125
127
  request, // 统一网络调度器 (自动判断 cgi 或 raw http)
126
128
  requestCgi, // 请求 musicu.fcg / musics.fcg
127
129
  requestRaw, // 原始 fetch 包装
@@ -130,6 +132,24 @@ import {
130
132
 
131
133
  ---
132
134
 
135
+ ## 发布
136
+
137
+ 版本号在 `package.json`;发布由 GitHub Actions 自动完成:
138
+
139
+ 1. 修改 `package.json` 的 `version`,提交并推送。
140
+ 2. 打标签并推送:`git tag v1.0.7 && git push origin v1.0.7`。
141
+ 3. `.github/workflows/publish.yml` 会安装依赖、构建、测试,并通过 npm Trusted Publishing(OIDC)执行 `npm publish --provenance`;不需要 `NPM_TOKEN`,也不需要 OTP。
142
+
143
+ 首次配置(npm 控制台,一次性):
144
+
145
+ - 打开 npmjs.com 上 `qqmusic-api-enhanced` 的 Settings → Trusted Publisher。
146
+ - 选择 GitHub Actions,填写仓库 `owner/repo`、workflow 文件名 `publish.yml`、Environment 留空。
147
+ - workflow 文件名必须与 npm 侧逐字一致;如果 npm 侧填了 Environment,要同步把它加到 workflow 的 job 上。
148
+
149
+ 也可以在 Actions 页面手动 `workflow_dispatch` 重跑;tag 触发时会先校验 tag 与 `package.json` 版本一致,不一致直接失败,避免发错版本。
150
+
151
+ ---
152
+
133
153
  ## 协议与免责声明
134
154
 
135
155
  本项目仅供个人学习、技术研究与教育用途。所有接口数据与媒体资源版权归腾讯公司所有。请勿将本项目用于任何商业用途或违反相关法律法规的场景。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qqmusic-api-enhanced",
3
- "version": "1.0.6",
3
+ "version": "1.0.7",
4
4
  "description": "QQ音乐增强版API,支持扫码登录/凭证刷新/直链提取/歌词解密/歌单歌手检索 || QQ Music Enhanced API for Node.js & Bun",
5
5
  "type": "module",
6
6
  "main": "main.js",
@@ -18,6 +18,14 @@
18
18
  ],
19
19
  "author": "BakaGame",
20
20
  "license": "MIT",
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/Cosmosuperbaka/qqmusic-api-enhanced.git"
24
+ },
25
+ "homepage": "https://github.com/Cosmosuperbaka/qqmusic-api-enhanced#readme",
26
+ "bugs": {
27
+ "url": "https://github.com/Cosmosuperbaka/qqmusic-api-enhanced/issues"
28
+ },
21
29
  "files": [
22
30
  "module",
23
31
  "util",
package/util/des.ts CHANGED
@@ -7,340 +7,340 @@ export const DECRYPT = 0;
7
7
 
8
8
  const sbox: number[][] = [[14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7,0,15,7,4,14,2,13,1,10,6,12,11,9,5,3,8,4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0,15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13],[15,1,8,14,6,11,3,4,9,7,2,13,12,0,5,10,3,13,4,7,15,2,8,15,12,0,1,10,6,9,11,5,0,14,7,11,10,4,13,1,5,8,12,6,9,3,2,15,13,8,10,1,3,15,4,2,11,6,7,12,0,5,14,9],[10,0,9,14,6,3,15,5,1,13,12,7,11,4,2,8,13,7,0,9,3,4,6,10,2,8,5,14,12,11,15,1,13,6,4,9,8,15,3,0,11,1,2,12,5,10,14,7,1,10,13,0,6,9,8,7,4,15,14,3,11,5,2,12],[7,13,14,3,0,6,9,10,1,2,8,5,11,12,4,15,13,8,11,5,6,15,0,3,4,7,2,12,1,10,14,9,10,6,9,0,12,11,7,13,15,1,3,14,5,2,8,4,3,15,0,6,10,10,13,8,9,4,5,11,12,7,2,14],[2,12,4,1,7,10,11,6,8,5,3,15,13,0,14,9,14,11,2,12,4,7,13,1,5,0,15,10,3,9,8,6,4,2,1,11,10,13,7,8,15,9,12,5,6,3,0,14,11,8,12,7,1,14,2,13,6,15,0,9,10,4,5,3],[12,1,10,15,9,2,6,8,0,13,3,4,14,7,5,11,10,15,4,2,7,12,9,5,6,1,13,14,0,11,3,8,9,14,15,5,2,8,12,3,7,0,4,10,1,13,11,6,4,3,2,12,9,5,15,10,11,14,1,7,6,0,8,13],[4,11,2,14,15,0,8,13,3,12,9,7,5,10,6,1,13,0,11,7,4,9,1,10,14,3,5,12,2,15,8,6,1,4,11,13,12,3,7,14,10,15,6,8,0,5,9,2,6,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12],[13,2,8,4,6,15,11,1,10,9,3,14,5,0,12,7,1,15,13,8,10,3,7,4,12,5,6,11,0,14,9,2,7,11,4,1,9,12,14,2,0,6,10,13,15,3,5,8,2,1,14,7,4,10,8,13,15,12,9,0,3,5,6,11]];
9
9
 
10
- function sboxBit(a: number): number {
11
- return (a & 32) | ((a & 31) >> 1) | ((a & 1) << 4);
12
- }
13
-
14
- function initialPermutation(inputData: Uint8Array): [number, number] {
15
- const v0 = (inputData[0] | (inputData[1] << 8) | (inputData[2] << 16) | (inputData[3] << 24)) >>> 0;
16
- const v1 = (inputData[4] | (inputData[5] << 8) | (inputData[6] << 16) | (inputData[7] << 24)) >>> 0;
17
-
18
- const s0 = (
19
- (((v1 >> 6) & 1) << 31) |
20
- (((v1 >> 14) & 1) << 30) |
21
- (((v1 >> 22) & 1) << 29) |
22
- (((v1 >> 30) & 1) << 28) |
23
- (((v0 >> 6) & 1) << 27) |
24
- (((v0 >> 14) & 1) << 26) |
25
- (((v0 >> 22) & 1) << 25) |
26
- (((v0 >> 30) & 1) << 24) |
27
- (((v1 >> 4) & 1) << 23) |
28
- (((v1 >> 12) & 1) << 22) |
29
- (((v1 >> 20) & 1) << 21) |
30
- (((v1 >> 28) & 1) << 20) |
31
- (((v0 >> 4) & 1) << 19) |
32
- (((v0 >> 12) & 1) << 18) |
33
- (((v0 >> 20) & 1) << 17) |
34
- (((v0 >> 28) & 1) << 16) |
35
- (((v1 >> 2) & 1) << 15) |
36
- (((v1 >> 10) & 1) << 14) |
37
- (((v1 >> 18) & 1) << 13) |
38
- (((v1 >> 26) & 1) << 12) |
39
- (((v0 >> 2) & 1) << 11) |
40
- (((v0 >> 10) & 1) << 10) |
41
- (((v0 >> 18) & 1) << 9) |
42
- (((v0 >> 26) & 1) << 8) |
43
- (((v1 >> 0) & 1) << 7) |
44
- (((v1 >> 8) & 1) << 6) |
45
- (((v1 >> 16) & 1) << 5) |
46
- (((v1 >> 24) & 1) << 4) |
47
- (((v0 >> 0) & 1) << 3) |
48
- (((v0 >> 8) & 1) << 2) |
49
- (((v0 >> 16) & 1) << 1) |
50
- ((v0 >> 24) & 1)
51
- ) >>> 0;
52
-
53
- const s1 = (
54
- (((v1 >> 7) & 1) << 31) |
55
- (((v1 >> 15) & 1) << 30) |
56
- (((v1 >> 23) & 1) << 29) |
57
- (((v1 >> 31) & 1) << 28) |
58
- (((v0 >> 7) & 1) << 27) |
59
- (((v0 >> 15) & 1) << 26) |
60
- (((v0 >> 23) & 1) << 25) |
61
- (((v0 >> 31) & 1) << 24) |
62
- (((v1 >> 5) & 1) << 23) |
63
- (((v1 >> 13) & 1) << 22) |
64
- (((v1 >> 21) & 1) << 21) |
65
- (((v1 >> 29) & 1) << 20) |
66
- (((v0 >> 5) & 1) << 19) |
67
- (((v0 >> 13) & 1) << 18) |
68
- (((v0 >> 21) & 1) << 17) |
69
- (((v0 >> 29) & 1) << 16) |
70
- (((v1 >> 3) & 1) << 15) |
71
- (((v1 >> 11) & 1) << 14) |
72
- (((v1 >> 19) & 1) << 13) |
73
- (((v1 >> 27) & 1) << 12) |
74
- (((v0 >> 3) & 1) << 11) |
75
- (((v0 >> 11) & 1) << 10) |
76
- (((v0 >> 19) & 1) << 9) |
77
- (((v0 >> 27) & 1) << 8) |
78
- (((v1 >> 1) & 1) << 7) |
79
- (((v1 >> 9) & 1) << 6) |
80
- (((v1 >> 17) & 1) << 5) |
81
- (((v1 >> 25) & 1) << 4) |
82
- (((v0 >> 1) & 1) << 3) |
83
- (((v0 >> 9) & 1) << 2) |
84
- (((v0 >> 17) & 1) << 1) |
85
- ((v0 >> 25) & 1)
86
- ) >>> 0;
87
-
88
- return [s0, s1];
89
- }
90
-
91
- function inversePermutation(s0: number, s1: number): Uint8Array {
92
- const data = new Uint8Array(8);
93
- data[3] = (
94
- (((s1 >> 24) & 1) << 7) |
95
- (((s0 >> 24) & 1) << 6) |
96
- (((s1 >> 16) & 1) << 5) |
97
- (((s0 >> 16) & 1) << 4) |
98
- (((s1 >> 8) & 1) << 3) |
99
- (((s0 >> 8) & 1) << 2) |
100
- (((s1 >> 0) & 1) << 1) |
101
- ((s0 >> 0) & 1)
102
- );
103
- data[2] = (
104
- (((s1 >> 25) & 1) << 7) |
105
- (((s0 >> 25) & 1) << 6) |
106
- (((s1 >> 17) & 1) << 5) |
107
- (((s0 >> 17) & 1) << 4) |
108
- (((s1 >> 9) & 1) << 3) |
109
- (((s0 >> 9) & 1) << 2) |
110
- (((s1 >> 1) & 1) << 1) |
111
- ((s0 >> 1) & 1)
112
- );
113
- data[1] = (
114
- (((s1 >> 26) & 1) << 7) |
115
- (((s0 >> 26) & 1) << 6) |
116
- (((s1 >> 18) & 1) << 5) |
117
- (((s0 >> 18) & 1) << 4) |
118
- (((s1 >> 10) & 1) << 3) |
119
- (((s0 >> 10) & 1) << 2) |
120
- (((s1 >> 2) & 1) << 1) |
121
- ((s0 >> 2) & 1)
122
- );
123
- data[0] = (
124
- (((s1 >> 27) & 1) << 7) |
125
- (((s0 >> 27) & 1) << 6) |
126
- (((s1 >> 19) & 1) << 5) |
127
- (((s0 >> 19) & 1) << 4) |
128
- (((s1 >> 11) & 1) << 3) |
129
- (((s0 >> 11) & 1) << 2) |
130
- (((s1 >> 3) & 1) << 1) |
131
- ((s0 >> 3) & 1)
132
- );
133
- data[7] = (
134
- (((s1 >> 28) & 1) << 7) |
135
- (((s0 >> 28) & 1) << 6) |
136
- (((s1 >> 20) & 1) << 5) |
137
- (((s0 >> 20) & 1) << 4) |
138
- (((s1 >> 12) & 1) << 3) |
139
- (((s0 >> 12) & 1) << 2) |
140
- (((s1 >> 4) & 1) << 1) |
141
- ((s0 >> 4) & 1)
142
- );
143
- data[6] = (
144
- (((s1 >> 29) & 1) << 7) |
145
- (((s0 >> 29) & 1) << 6) |
146
- (((s1 >> 21) & 1) << 5) |
147
- (((s0 >> 21) & 1) << 4) |
148
- (((s1 >> 13) & 1) << 3) |
149
- (((s0 >> 13) & 1) << 2) |
150
- (((s1 >> 5) & 1) << 1) |
151
- ((s0 >> 5) & 1)
152
- );
153
- data[5] = (
154
- (((s1 >> 30) & 1) << 7) |
155
- (((s0 >> 30) & 1) << 6) |
156
- (((s1 >> 22) & 1) << 5) |
157
- (((s0 >> 22) & 1) << 4) |
158
- (((s1 >> 14) & 1) << 3) |
159
- (((s0 >> 14) & 1) << 2) |
160
- (((s1 >> 6) & 1) << 1) |
161
- ((s0 >> 6) & 1)
162
- );
163
- data[4] = (
164
- (((s1 >> 31) & 1) << 7) |
165
- (((s0 >> 31) & 1) << 6) |
166
- (((s1 >> 23) & 1) << 5) |
167
- (((s0 >> 23) & 1) << 4) |
168
- (((s1 >> 15) & 1) << 3) |
169
- (((s0 >> 15) & 1) << 2) |
170
- (((s1 >> 7) & 1) << 1) |
171
- ((s0 >> 7) & 1)
172
- );
173
- return data;
174
- }
175
-
176
- function f(state: number, key: number[]): number {
177
- const t1 = (
178
- (((state & 1) << 31) >>> 0) |
179
- ((state & 0xf8000000) >>> 1) |
180
- ((state & 0x1f800000) >>> 3) |
181
- ((state & 0x01f80000) >>> 5) |
182
- ((state & 0x001f8000) >>> 7)
183
- ) >>> 0;
184
-
185
- const t2 = (
186
- ((state & 0x0001f800) << 15) |
187
- ((state & 0x00001f80) << 13) |
188
- ((state & 0x000001f8) << 11) |
189
- ((state & 0x0000001f) << 9) |
190
- ((state & 0x80000000) >>> 23)
191
- ) >>> 0;
192
-
193
- const k0 = ((t1 >>> 24) & 0xff) ^ key[0];
194
- const k1 = ((t1 >>> 16) & 0xff) ^ key[1];
195
- const k2 = ((t1 >>> 8) & 0xff) ^ key[2];
196
- const k3 = ((t2 >>> 24) & 0xff) ^ key[3];
197
- const k4 = ((t2 >>> 16) & 0xff) ^ key[4];
198
- const k5 = ((t2 >>> 8) & 0xff) ^ key[5];
199
-
200
- let st = (
201
- (sbox[0][sboxBit(k0 >> 2)] << 28) |
202
- (sbox[1][sboxBit(((k0 & 0x03) << 4) | (k1 >> 4))] << 24) |
203
- (sbox[2][sboxBit(((k1 & 0x0f) << 2) | (k2 >> 6))] << 20) |
204
- (sbox[3][sboxBit(k2 & 0x3f)] << 16) |
205
- (sbox[4][sboxBit(k3 >> 2)] << 12) |
206
- (sbox[5][sboxBit(((k3 & 0x03) << 4) | (k4 >> 4))] << 8) |
207
- (sbox[6][sboxBit(((k4 & 0x0f) << 2) | (k5 >> 6))] << 4) |
208
- sbox[7][sboxBit(k5 & 0x3f)]
209
- ) >>> 0;
210
-
211
- return (
212
- (((st >> 16) & 1) << 31) |
213
- (((st >> 25) & 1) << 30) |
214
- (((st >> 12) & 1) << 29) |
215
- (((st >> 11) & 1) << 28) |
216
- (((st >> 3) & 1) << 27) |
217
- (((st >> 20) & 1) << 26) |
218
- (((st >> 4) & 1) << 25) |
219
- (((st >> 15) & 1) << 24) |
220
- (((st >> 31) & 1) << 23) |
221
- (((st >> 17) & 1) << 22) |
222
- (((st >> 9) & 1) << 21) |
223
- (((st >> 6) & 1) << 20) |
224
- (((st >> 27) & 1) << 19) |
225
- (((st >> 14) & 1) << 18) |
226
- (((st >> 1) & 1) << 17) |
227
- (((st >> 22) & 1) << 16) |
228
- (((st >> 30) & 1) << 15) |
229
- (((st >> 24) & 1) << 14) |
230
- (((st >> 8) & 1) << 13) |
231
- (((st >> 18) & 1) << 12) |
232
- (((st >> 0) & 1) << 11) |
233
- (((st >> 5) & 1) << 10) |
234
- (((st >> 29) & 1) << 9) |
235
- (((st >> 23) & 1) << 8) |
236
- (((st >> 13) & 1) << 7) |
237
- (((st >> 19) & 1) << 6) |
238
- (((st >> 2) & 1) << 5) |
239
- (((st >> 26) & 1) << 4) |
240
- (((st >> 10) & 1) << 3) |
241
- (((st >> 21) & 1) << 2) |
242
- (((st >> 28) & 1) << 1) |
243
- ((st >> 7) & 1)
244
- ) >>> 0;
245
- }
246
-
247
- export function desCrypt(inputData: Uint8Array, key: number[][]): Uint8Array {
248
- let [s0, s1] = initialPermutation(inputData);
249
-
250
- for (let idx = 0; idx < 15; idx++) {
251
- const prevS1 = s1;
252
- s1 = (f(s1, key[idx]) ^ s0) >>> 0;
253
- s0 = prevS1;
254
- }
255
- s0 = (f(s1, key[15]) ^ s0) >>> 0;
256
-
257
- return inversePermutation(s0, s1);
258
- }
259
-
260
- const KEY_RND_SHIFT = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1];
261
- const KEY_PERM_C = [
262
- 56, 48, 40, 32, 24, 16, 8, 0,
263
- 57, 49, 41, 33, 25, 17, 9, 1,
264
- 58, 50, 42, 34, 26, 18, 10, 2,
265
- 59, 51, 43, 35
266
- ];
267
- const KEY_PERM_D = [
268
- 62, 54, 46, 38, 30, 22, 14, 6,
269
- 61, 53, 45, 37, 29, 21, 13, 5,
270
- 60, 52, 44, 36, 28, 20, 12, 4,
271
- 27, 19, 11, 3
272
- ];
273
- const KEY_COMPRESSION = [
274
- 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
275
- 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
276
- 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
277
- 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31
278
- ];
279
-
280
- export function keySchedule(key: Uint8Array, mode: number): number[][] {
281
- const schedule: number[][] = Array.from({ length: 16 }, () => [0, 0, 0, 0, 0, 0]);
282
-
283
- const v0 = (key[0] | (key[1] << 8) | (key[2] << 16) | (key[3] << 24)) >>> 0;
284
- const v1 = (key[4] | (key[5] << 8) | (key[6] << 16) | (key[7] << 24)) >>> 0;
285
-
286
- let c = 0;
287
- for (let i = 0; i < KEY_PERM_C.length; i++) {
288
- const b = KEY_PERM_C[i];
289
- const bit = (b < 32 ? ((v0 >>> (31 - b)) & 1) : ((v1 >>> (63 - b)) & 1));
290
- c = (c | (bit << (31 - i))) >>> 0;
291
- }
292
-
293
- let d = 0;
294
- for (let i = 0; i < KEY_PERM_D.length; i++) {
295
- const b = KEY_PERM_D[i];
296
- const bit = (b < 32 ? ((v0 >>> (31 - b)) & 1) : ((v1 >>> (63 - b)) & 1));
297
- d = (d | (bit << (31 - i))) >>> 0;
298
- }
299
-
300
- for (let i = 0; i < 16; i++) {
301
- const shift = KEY_RND_SHIFT[i];
302
- c = (((c << shift) | (c >>> (28 - shift))) & 0xfffffff0) >>> 0;
303
- d = (((d << shift) | (d >>> (28 - shift))) & 0xfffffff0) >>> 0;
304
-
305
- const togen = mode === DECRYPT ? 15 - i : i;
306
-
307
- for (let j = 0; j < 6; j++) {
308
- schedule[togen][j] = 0;
309
- }
310
-
311
- for (let j = 0; j < 24; j++) {
312
- const bit = (c >>> (31 - KEY_COMPRESSION[j])) & 1;
313
- schedule[togen][Math.floor(j / 8)] |= bit << (7 - (j % 8));
314
- }
315
-
316
- for (let j = 24; j < 48; j++) {
317
- const bit = (d >>> (31 - (KEY_COMPRESSION[j] - 27))) & 1;
318
- schedule[togen][Math.floor(j / 8)] |= bit << (7 - (j % 8));
319
- }
320
- }
321
-
322
- return schedule;
323
- }
324
-
325
- export function tripleDesKeySetup(key: Uint8Array, mode: number): number[][][] {
326
- if (mode === ENCRYPT) {
327
- return [
328
- keySchedule(key.subarray(0, 8), ENCRYPT),
329
- keySchedule(key.subarray(8, 16), DECRYPT),
330
- keySchedule(key.subarray(16, 24), ENCRYPT),
331
- ];
332
- }
333
- return [
334
- keySchedule(key.subarray(16, 24), DECRYPT),
335
- keySchedule(key.subarray(8, 16), ENCRYPT),
336
- keySchedule(key.subarray(0, 8), DECRYPT),
337
- ];
338
- }
339
-
340
- export function tripleDesCrypt(data: Uint8Array, key: number[][][]): Uint8Array {
341
- let res = new Uint8Array(data);
342
- for (let i = 0; i < 3; i++) {
343
- res = desCrypt(res, key[i]) as any;
344
- }
345
- return res;
10
+ function sboxBit(a: number): number {
11
+ return (a & 32) | ((a & 31) >> 1) | ((a & 1) << 4);
12
+ }
13
+
14
+ function initialPermutation(inputData: Uint8Array): [number, number] {
15
+ const v0 = (inputData[0] | (inputData[1] << 8) | (inputData[2] << 16) | (inputData[3] << 24)) >>> 0;
16
+ const v1 = (inputData[4] | (inputData[5] << 8) | (inputData[6] << 16) | (inputData[7] << 24)) >>> 0;
17
+
18
+ const s0 = (
19
+ (((v1 >> 6) & 1) << 31) |
20
+ (((v1 >> 14) & 1) << 30) |
21
+ (((v1 >> 22) & 1) << 29) |
22
+ (((v1 >> 30) & 1) << 28) |
23
+ (((v0 >> 6) & 1) << 27) |
24
+ (((v0 >> 14) & 1) << 26) |
25
+ (((v0 >> 22) & 1) << 25) |
26
+ (((v0 >> 30) & 1) << 24) |
27
+ (((v1 >> 4) & 1) << 23) |
28
+ (((v1 >> 12) & 1) << 22) |
29
+ (((v1 >> 20) & 1) << 21) |
30
+ (((v1 >> 28) & 1) << 20) |
31
+ (((v0 >> 4) & 1) << 19) |
32
+ (((v0 >> 12) & 1) << 18) |
33
+ (((v0 >> 20) & 1) << 17) |
34
+ (((v0 >> 28) & 1) << 16) |
35
+ (((v1 >> 2) & 1) << 15) |
36
+ (((v1 >> 10) & 1) << 14) |
37
+ (((v1 >> 18) & 1) << 13) |
38
+ (((v1 >> 26) & 1) << 12) |
39
+ (((v0 >> 2) & 1) << 11) |
40
+ (((v0 >> 10) & 1) << 10) |
41
+ (((v0 >> 18) & 1) << 9) |
42
+ (((v0 >> 26) & 1) << 8) |
43
+ (((v1 >> 0) & 1) << 7) |
44
+ (((v1 >> 8) & 1) << 6) |
45
+ (((v1 >> 16) & 1) << 5) |
46
+ (((v1 >> 24) & 1) << 4) |
47
+ (((v0 >> 0) & 1) << 3) |
48
+ (((v0 >> 8) & 1) << 2) |
49
+ (((v0 >> 16) & 1) << 1) |
50
+ ((v0 >> 24) & 1)
51
+ ) >>> 0;
52
+
53
+ const s1 = (
54
+ (((v1 >> 7) & 1) << 31) |
55
+ (((v1 >> 15) & 1) << 30) |
56
+ (((v1 >> 23) & 1) << 29) |
57
+ (((v1 >> 31) & 1) << 28) |
58
+ (((v0 >> 7) & 1) << 27) |
59
+ (((v0 >> 15) & 1) << 26) |
60
+ (((v0 >> 23) & 1) << 25) |
61
+ (((v0 >> 31) & 1) << 24) |
62
+ (((v1 >> 5) & 1) << 23) |
63
+ (((v1 >> 13) & 1) << 22) |
64
+ (((v1 >> 21) & 1) << 21) |
65
+ (((v1 >> 29) & 1) << 20) |
66
+ (((v0 >> 5) & 1) << 19) |
67
+ (((v0 >> 13) & 1) << 18) |
68
+ (((v0 >> 21) & 1) << 17) |
69
+ (((v0 >> 29) & 1) << 16) |
70
+ (((v1 >> 3) & 1) << 15) |
71
+ (((v1 >> 11) & 1) << 14) |
72
+ (((v1 >> 19) & 1) << 13) |
73
+ (((v1 >> 27) & 1) << 12) |
74
+ (((v0 >> 3) & 1) << 11) |
75
+ (((v0 >> 11) & 1) << 10) |
76
+ (((v0 >> 19) & 1) << 9) |
77
+ (((v0 >> 27) & 1) << 8) |
78
+ (((v1 >> 1) & 1) << 7) |
79
+ (((v1 >> 9) & 1) << 6) |
80
+ (((v1 >> 17) & 1) << 5) |
81
+ (((v1 >> 25) & 1) << 4) |
82
+ (((v0 >> 1) & 1) << 3) |
83
+ (((v0 >> 9) & 1) << 2) |
84
+ (((v0 >> 17) & 1) << 1) |
85
+ ((v0 >> 25) & 1)
86
+ ) >>> 0;
87
+
88
+ return [s0, s1];
89
+ }
90
+
91
+ function inversePermutation(s0: number, s1: number): Uint8Array {
92
+ const data = new Uint8Array(8);
93
+ data[3] = (
94
+ (((s1 >> 24) & 1) << 7) |
95
+ (((s0 >> 24) & 1) << 6) |
96
+ (((s1 >> 16) & 1) << 5) |
97
+ (((s0 >> 16) & 1) << 4) |
98
+ (((s1 >> 8) & 1) << 3) |
99
+ (((s0 >> 8) & 1) << 2) |
100
+ (((s1 >> 0) & 1) << 1) |
101
+ ((s0 >> 0) & 1)
102
+ );
103
+ data[2] = (
104
+ (((s1 >> 25) & 1) << 7) |
105
+ (((s0 >> 25) & 1) << 6) |
106
+ (((s1 >> 17) & 1) << 5) |
107
+ (((s0 >> 17) & 1) << 4) |
108
+ (((s1 >> 9) & 1) << 3) |
109
+ (((s0 >> 9) & 1) << 2) |
110
+ (((s1 >> 1) & 1) << 1) |
111
+ ((s0 >> 1) & 1)
112
+ );
113
+ data[1] = (
114
+ (((s1 >> 26) & 1) << 7) |
115
+ (((s0 >> 26) & 1) << 6) |
116
+ (((s1 >> 18) & 1) << 5) |
117
+ (((s0 >> 18) & 1) << 4) |
118
+ (((s1 >> 10) & 1) << 3) |
119
+ (((s0 >> 10) & 1) << 2) |
120
+ (((s1 >> 2) & 1) << 1) |
121
+ ((s0 >> 2) & 1)
122
+ );
123
+ data[0] = (
124
+ (((s1 >> 27) & 1) << 7) |
125
+ (((s0 >> 27) & 1) << 6) |
126
+ (((s1 >> 19) & 1) << 5) |
127
+ (((s0 >> 19) & 1) << 4) |
128
+ (((s1 >> 11) & 1) << 3) |
129
+ (((s0 >> 11) & 1) << 2) |
130
+ (((s1 >> 3) & 1) << 1) |
131
+ ((s0 >> 3) & 1)
132
+ );
133
+ data[7] = (
134
+ (((s1 >> 28) & 1) << 7) |
135
+ (((s0 >> 28) & 1) << 6) |
136
+ (((s1 >> 20) & 1) << 5) |
137
+ (((s0 >> 20) & 1) << 4) |
138
+ (((s1 >> 12) & 1) << 3) |
139
+ (((s0 >> 12) & 1) << 2) |
140
+ (((s1 >> 4) & 1) << 1) |
141
+ ((s0 >> 4) & 1)
142
+ );
143
+ data[6] = (
144
+ (((s1 >> 29) & 1) << 7) |
145
+ (((s0 >> 29) & 1) << 6) |
146
+ (((s1 >> 21) & 1) << 5) |
147
+ (((s0 >> 21) & 1) << 4) |
148
+ (((s1 >> 13) & 1) << 3) |
149
+ (((s0 >> 13) & 1) << 2) |
150
+ (((s1 >> 5) & 1) << 1) |
151
+ ((s0 >> 5) & 1)
152
+ );
153
+ data[5] = (
154
+ (((s1 >> 30) & 1) << 7) |
155
+ (((s0 >> 30) & 1) << 6) |
156
+ (((s1 >> 22) & 1) << 5) |
157
+ (((s0 >> 22) & 1) << 4) |
158
+ (((s1 >> 14) & 1) << 3) |
159
+ (((s0 >> 14) & 1) << 2) |
160
+ (((s1 >> 6) & 1) << 1) |
161
+ ((s0 >> 6) & 1)
162
+ );
163
+ data[4] = (
164
+ (((s1 >> 31) & 1) << 7) |
165
+ (((s0 >> 31) & 1) << 6) |
166
+ (((s1 >> 23) & 1) << 5) |
167
+ (((s0 >> 23) & 1) << 4) |
168
+ (((s1 >> 15) & 1) << 3) |
169
+ (((s0 >> 15) & 1) << 2) |
170
+ (((s1 >> 7) & 1) << 1) |
171
+ ((s0 >> 7) & 1)
172
+ );
173
+ return data;
174
+ }
175
+
176
+ function f(state: number, key: number[]): number {
177
+ const t1 = (
178
+ (((state & 1) << 31) >>> 0) |
179
+ ((state & 0xf8000000) >>> 1) |
180
+ ((state & 0x1f800000) >>> 3) |
181
+ ((state & 0x01f80000) >>> 5) |
182
+ ((state & 0x001f8000) >>> 7)
183
+ ) >>> 0;
184
+
185
+ const t2 = (
186
+ ((state & 0x0001f800) << 15) |
187
+ ((state & 0x00001f80) << 13) |
188
+ ((state & 0x000001f8) << 11) |
189
+ ((state & 0x0000001f) << 9) |
190
+ ((state & 0x80000000) >>> 23)
191
+ ) >>> 0;
192
+
193
+ const k0 = ((t1 >>> 24) & 0xff) ^ key[0];
194
+ const k1 = ((t1 >>> 16) & 0xff) ^ key[1];
195
+ const k2 = ((t1 >>> 8) & 0xff) ^ key[2];
196
+ const k3 = ((t2 >>> 24) & 0xff) ^ key[3];
197
+ const k4 = ((t2 >>> 16) & 0xff) ^ key[4];
198
+ const k5 = ((t2 >>> 8) & 0xff) ^ key[5];
199
+
200
+ let st = (
201
+ (sbox[0][sboxBit(k0 >> 2)] << 28) |
202
+ (sbox[1][sboxBit(((k0 & 0x03) << 4) | (k1 >> 4))] << 24) |
203
+ (sbox[2][sboxBit(((k1 & 0x0f) << 2) | (k2 >> 6))] << 20) |
204
+ (sbox[3][sboxBit(k2 & 0x3f)] << 16) |
205
+ (sbox[4][sboxBit(k3 >> 2)] << 12) |
206
+ (sbox[5][sboxBit(((k3 & 0x03) << 4) | (k4 >> 4))] << 8) |
207
+ (sbox[6][sboxBit(((k4 & 0x0f) << 2) | (k5 >> 6))] << 4) |
208
+ sbox[7][sboxBit(k5 & 0x3f)]
209
+ ) >>> 0;
210
+
211
+ return (
212
+ (((st >> 16) & 1) << 31) |
213
+ (((st >> 25) & 1) << 30) |
214
+ (((st >> 12) & 1) << 29) |
215
+ (((st >> 11) & 1) << 28) |
216
+ (((st >> 3) & 1) << 27) |
217
+ (((st >> 20) & 1) << 26) |
218
+ (((st >> 4) & 1) << 25) |
219
+ (((st >> 15) & 1) << 24) |
220
+ (((st >> 31) & 1) << 23) |
221
+ (((st >> 17) & 1) << 22) |
222
+ (((st >> 9) & 1) << 21) |
223
+ (((st >> 6) & 1) << 20) |
224
+ (((st >> 27) & 1) << 19) |
225
+ (((st >> 14) & 1) << 18) |
226
+ (((st >> 1) & 1) << 17) |
227
+ (((st >> 22) & 1) << 16) |
228
+ (((st >> 30) & 1) << 15) |
229
+ (((st >> 24) & 1) << 14) |
230
+ (((st >> 8) & 1) << 13) |
231
+ (((st >> 18) & 1) << 12) |
232
+ (((st >> 0) & 1) << 11) |
233
+ (((st >> 5) & 1) << 10) |
234
+ (((st >> 29) & 1) << 9) |
235
+ (((st >> 23) & 1) << 8) |
236
+ (((st >> 13) & 1) << 7) |
237
+ (((st >> 19) & 1) << 6) |
238
+ (((st >> 2) & 1) << 5) |
239
+ (((st >> 26) & 1) << 4) |
240
+ (((st >> 10) & 1) << 3) |
241
+ (((st >> 21) & 1) << 2) |
242
+ (((st >> 28) & 1) << 1) |
243
+ ((st >> 7) & 1)
244
+ ) >>> 0;
245
+ }
246
+
247
+ export function desCrypt(inputData: Uint8Array, key: number[][]): Uint8Array {
248
+ let [s0, s1] = initialPermutation(inputData);
249
+
250
+ for (let idx = 0; idx < 15; idx++) {
251
+ const prevS1 = s1;
252
+ s1 = (f(s1, key[idx]) ^ s0) >>> 0;
253
+ s0 = prevS1;
254
+ }
255
+ s0 = (f(s1, key[15]) ^ s0) >>> 0;
256
+
257
+ return inversePermutation(s0, s1);
258
+ }
259
+
260
+ const KEY_RND_SHIFT = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1];
261
+ const KEY_PERM_C = [
262
+ 56, 48, 40, 32, 24, 16, 8, 0,
263
+ 57, 49, 41, 33, 25, 17, 9, 1,
264
+ 58, 50, 42, 34, 26, 18, 10, 2,
265
+ 59, 51, 43, 35
266
+ ];
267
+ const KEY_PERM_D = [
268
+ 62, 54, 46, 38, 30, 22, 14, 6,
269
+ 61, 53, 45, 37, 29, 21, 13, 5,
270
+ 60, 52, 44, 36, 28, 20, 12, 4,
271
+ 27, 19, 11, 3
272
+ ];
273
+ const KEY_COMPRESSION = [
274
+ 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
275
+ 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
276
+ 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
277
+ 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31
278
+ ];
279
+
280
+ export function keySchedule(key: Uint8Array, mode: number): number[][] {
281
+ const schedule: number[][] = Array.from({ length: 16 }, () => [0, 0, 0, 0, 0, 0]);
282
+
283
+ const v0 = (key[0] | (key[1] << 8) | (key[2] << 16) | (key[3] << 24)) >>> 0;
284
+ const v1 = (key[4] | (key[5] << 8) | (key[6] << 16) | (key[7] << 24)) >>> 0;
285
+
286
+ let c = 0;
287
+ for (let i = 0; i < KEY_PERM_C.length; i++) {
288
+ const b = KEY_PERM_C[i];
289
+ const bit = (b < 32 ? ((v0 >>> (31 - b)) & 1) : ((v1 >>> (63 - b)) & 1));
290
+ c = (c | (bit << (31 - i))) >>> 0;
291
+ }
292
+
293
+ let d = 0;
294
+ for (let i = 0; i < KEY_PERM_D.length; i++) {
295
+ const b = KEY_PERM_D[i];
296
+ const bit = (b < 32 ? ((v0 >>> (31 - b)) & 1) : ((v1 >>> (63 - b)) & 1));
297
+ d = (d | (bit << (31 - i))) >>> 0;
298
+ }
299
+
300
+ for (let i = 0; i < 16; i++) {
301
+ const shift = KEY_RND_SHIFT[i];
302
+ c = (((c << shift) | (c >>> (28 - shift))) & 0xfffffff0) >>> 0;
303
+ d = (((d << shift) | (d >>> (28 - shift))) & 0xfffffff0) >>> 0;
304
+
305
+ const togen = mode === DECRYPT ? 15 - i : i;
306
+
307
+ for (let j = 0; j < 6; j++) {
308
+ schedule[togen][j] = 0;
309
+ }
310
+
311
+ for (let j = 0; j < 24; j++) {
312
+ const bit = (c >>> (31 - KEY_COMPRESSION[j])) & 1;
313
+ schedule[togen][Math.floor(j / 8)] |= bit << (7 - (j % 8));
314
+ }
315
+
316
+ for (let j = 24; j < 48; j++) {
317
+ const bit = (d >>> (31 - (KEY_COMPRESSION[j] - 27))) & 1;
318
+ schedule[togen][Math.floor(j / 8)] |= bit << (7 - (j % 8));
319
+ }
320
+ }
321
+
322
+ return schedule;
323
+ }
324
+
325
+ export function tripleDesKeySetup(key: Uint8Array, mode: number): number[][][] {
326
+ if (mode === ENCRYPT) {
327
+ return [
328
+ keySchedule(key.subarray(0, 8), ENCRYPT),
329
+ keySchedule(key.subarray(8, 16), DECRYPT),
330
+ keySchedule(key.subarray(16, 24), ENCRYPT),
331
+ ];
332
+ }
333
+ return [
334
+ keySchedule(key.subarray(16, 24), DECRYPT),
335
+ keySchedule(key.subarray(8, 16), ENCRYPT),
336
+ keySchedule(key.subarray(0, 8), DECRYPT),
337
+ ];
338
+ }
339
+
340
+ export function tripleDesCrypt(data: Uint8Array, key: number[][][]): Uint8Array {
341
+ let res = new Uint8Array(data);
342
+ for (let i = 0; i < 3; i++) {
343
+ res = desCrypt(res, key[i]) as any;
344
+ }
345
+ return res;
346
346
  }