atm-droid 1.0.2 → 1.0.3

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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/api.js +63 -16
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "atm-droid",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "ATM Token Manager CLI - 跨平台 Factory Token 管理工具",
5
5
  "main": "src/index.js",
6
6
  "bin": {
package/src/api.js CHANGED
@@ -4,19 +4,35 @@ const { config, getDeviceId } = require('./config');
4
4
 
5
5
  const getServerUrl = () => config.get('serverUrl');
6
6
 
7
- // 生成加密密钥(与服务器一致)
8
- function getEncryptionKey() {
9
- const key = Buffer.alloc(32);
10
- const base = Buffer.from([
11
- 0x4a, 0x7b, 0x2c, 0x9d, 0x1e, 0x5f, 0x8a, 0x3b,
12
- 0x6c, 0x0d, 0x4e, 0x9f, 0x2a, 0x7b, 0x1c, 0x5d,
13
- 0x8e, 0x3f, 0x6a, 0x0b, 0x4c, 0x9d, 0x2e, 0x7f,
14
- 0x1a, 0x5b, 0x8c, 0x3d, 0x6e, 0x0f, 0x4a, 0x9b,
15
- ]);
16
- for (let i = 0; i < 32; i++) {
17
- key[i] = base[i] ^ ((i * 0x17) & 0xff);
7
+ // 解密静态字节(与 Rust 客户端一致)
8
+ function decryptStaticBytes(encrypted, keySeed) {
9
+ const result = [];
10
+ let key = keySeed;
11
+
12
+ for (let i = 0; i < encrypted.length; i++) {
13
+ const byte = encrypted[i];
14
+ let k1 = ((key * 0x1B) + i) & 0xff;
15
+ let k2 = ((k1 << 3) | (k1 >>> 5)) & 0xff; // rotate_left(3)
16
+ k2 = k2 ^ 0xA5;
17
+ const decrypted = byte ^ k2;
18
+ result.push(decrypted);
19
+ key = (((key + decrypted) & 0xff) * 0x3D) & 0xff;
18
20
  }
19
- return key;
21
+
22
+ return Buffer.from(result);
23
+ }
24
+
25
+ // 加密的通信密钥(与 Rust 客户端一致)
26
+ const ENC_COMM_KEY = Buffer.from([
27
+ 0x11, 0x18, 0xFC, 0x4A, 0xF9, 0xB8, 0x1A, 0x9C,
28
+ 0x4F, 0xA4, 0xD1, 0x44, 0x47, 0xE5, 0x03, 0x57,
29
+ 0xA3, 0x2B, 0x8E, 0x38, 0x3B, 0x99, 0x8F, 0x8C,
30
+ 0x2B, 0x91, 0x60, 0xC1, 0x15, 0x07, 0x21, 0x53,
31
+ ]);
32
+
33
+ // 生成加密密钥(与客户端一致)
34
+ function getEncryptionKey() {
35
+ return decryptStaticBytes(ENC_COMM_KEY, 0x8D);
20
36
  }
21
37
 
22
38
  // 生成签名
@@ -28,7 +44,7 @@ function generateSignature(data, timestamp, deviceId) {
28
44
  return hmac.digest('hex');
29
45
  }
30
46
 
31
- // 解密服务器返回的数据
47
+ // 解密服务器返回的数据(返回字符串)
32
48
  function decryptPayload(encryptedData, ivHex, tagHex) {
33
49
  try {
34
50
  const key = getEncryptionKey();
@@ -42,13 +58,26 @@ function decryptPayload(encryptedData, ivHex, tagHex) {
42
58
  let decrypted = decipher.update(encrypted, null, 'utf8');
43
59
  decrypted += decipher.final('utf8');
44
60
 
45
- return JSON.parse(decrypted);
61
+ return decrypted;
46
62
  } catch (e) {
47
63
  console.error('解密失败:', e.message);
48
64
  return null;
49
65
  }
50
66
  }
51
67
 
68
+ // 解密服务器返回的 JSON 数据
69
+ function decryptPayloadJson(encryptedData, ivHex, tagHex) {
70
+ const decrypted = decryptPayload(encryptedData, ivHex, tagHex);
71
+ if (decrypted) {
72
+ try {
73
+ return JSON.parse(decrypted);
74
+ } catch (e) {
75
+ return null;
76
+ }
77
+ }
78
+ return null;
79
+ }
80
+
52
81
  // 激活码登录
53
82
  async function activate(code) {
54
83
  const deviceId = getDeviceId();
@@ -88,7 +117,7 @@ async function getTokens() {
88
117
 
89
118
  // 如果返回加密数据,需要解密
90
119
  if (result.success && result.data && result.iv && result.tag) {
91
- const decrypted = decryptPayload(result.data, result.iv, result.tag);
120
+ const decrypted = decryptPayloadJson(result.data, result.iv, result.tag);
92
121
  if (decrypted) {
93
122
  return { success: true, data: decrypted };
94
123
  }
@@ -117,7 +146,25 @@ async function activateToken(tokenId) {
117
146
  body: JSON.stringify({ token_id: tokenId })
118
147
  });
119
148
 
120
- return response.json();
149
+ const result = await response.json();
150
+
151
+ // 解密 access_token 和 refresh_token
152
+ if (result.success && result.access_token && result.access_iv && result.access_tag) {
153
+ const accessToken = decryptPayload(result.access_token, result.access_iv, result.access_tag);
154
+ const refreshToken = decryptPayload(result.refresh_token, result.refresh_iv, result.refresh_tag);
155
+
156
+ if (accessToken && refreshToken) {
157
+ return {
158
+ success: true,
159
+ email: result.email,
160
+ access_token: accessToken,
161
+ refresh_token: refreshToken
162
+ };
163
+ }
164
+ return { success: false, error: '解密失败' };
165
+ }
166
+
167
+ return result;
121
168
  }
122
169
 
123
170
  // 心跳