atm-droid 1.0.0 → 1.0.2

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 +7 -2
  2. package/src/api.js +83 -13
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "atm-droid",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "ATM Token Manager CLI - 跨平台 Factory Token 管理工具",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -9,7 +9,12 @@
9
9
  "scripts": {
10
10
  "start": "node bin/atm.js"
11
11
  },
12
- "keywords": ["factory", "token", "manager", "cli"],
12
+ "keywords": [
13
+ "factory",
14
+ "token",
15
+ "manager",
16
+ "cli"
17
+ ],
13
18
  "author": "ATM Team",
14
19
  "license": "MIT",
15
20
  "dependencies": {
package/src/api.js CHANGED
@@ -1,15 +1,64 @@
1
1
  const fetch = require('node-fetch');
2
+ const crypto = require('crypto');
2
3
  const { config, getDeviceId } = require('./config');
3
4
 
4
5
  const getServerUrl = () => config.get('serverUrl');
5
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);
18
+ }
19
+ return key;
20
+ }
21
+
22
+ // 生成签名
23
+ function generateSignature(data, timestamp, deviceId) {
24
+ const message = `${data}|${timestamp}|${deviceId}`;
25
+ const key = getEncryptionKey();
26
+ const hmac = crypto.createHmac('sha256', key);
27
+ hmac.update(message);
28
+ return hmac.digest('hex');
29
+ }
30
+
31
+ // 解密服务器返回的数据
32
+ function decryptPayload(encryptedData, ivHex, tagHex) {
33
+ try {
34
+ const key = getEncryptionKey();
35
+ const iv = Buffer.from(ivHex, 'hex');
36
+ const tag = Buffer.from(tagHex, 'hex');
37
+ const encrypted = Buffer.from(encryptedData, 'hex');
38
+
39
+ const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
40
+ decipher.setAuthTag(tag);
41
+
42
+ let decrypted = decipher.update(encrypted, null, 'utf8');
43
+ decrypted += decipher.final('utf8');
44
+
45
+ return JSON.parse(decrypted);
46
+ } catch (e) {
47
+ console.error('解密失败:', e.message);
48
+ return null;
49
+ }
50
+ }
51
+
6
52
  // 激活码登录
7
53
  async function activate(code) {
8
54
  const deviceId = getDeviceId();
9
- const response = await fetch(`${getServerUrl()}/api/activate`, {
55
+ const timestamp = Math.floor(Date.now() / 1000);
56
+ const signature = generateSignature(code, timestamp, deviceId);
57
+
58
+ const response = await fetch(`${getServerUrl()}/api/v1/auth/activate`, {
10
59
  method: 'POST',
11
60
  headers: { 'Content-Type': 'application/json' },
12
- body: JSON.stringify({ code, device_id: deviceId })
61
+ body: JSON.stringify({ code, device_id: deviceId, timestamp, signature })
13
62
  });
14
63
  return response.json();
15
64
  }
@@ -23,19 +72,27 @@ async function getTokens() {
23
72
  throw new Error('未登录');
24
73
  }
25
74
 
26
- const response = await fetch(`${getServerUrl()}/api/tokens`, {
75
+ const timestamp = Math.floor(Date.now() / 1000);
76
+ const signature = generateSignature(sessionToken, timestamp, deviceId);
77
+
78
+ const response = await fetch(`${getServerUrl()}/api/v1/tokens`, {
27
79
  headers: {
28
80
  'Authorization': `Bearer ${sessionToken}`,
29
- 'X-Device-ID': deviceId
81
+ 'X-Device-ID': deviceId,
82
+ 'X-Timestamp': timestamp.toString(),
83
+ 'X-Signature': signature
30
84
  }
31
85
  });
32
86
 
33
87
  const result = await response.json();
34
88
 
35
89
  // 如果返回加密数据,需要解密
36
- if (result.success && result.data && result.iv) {
37
- // 简化版:假设服务器返回明文(或添加解密逻辑)
38
- return result;
90
+ if (result.success && result.data && result.iv && result.tag) {
91
+ const decrypted = decryptPayload(result.data, result.iv, result.tag);
92
+ if (decrypted) {
93
+ return { success: true, data: decrypted };
94
+ }
95
+ return { success: false, error: '解密失败' };
39
96
  }
40
97
 
41
98
  return result;
@@ -45,13 +102,17 @@ async function getTokens() {
45
102
  async function activateToken(tokenId) {
46
103
  const sessionToken = config.get('sessionToken');
47
104
  const deviceId = getDeviceId();
105
+ const timestamp = Math.floor(Date.now() / 1000);
106
+ const signature = generateSignature(sessionToken, timestamp, deviceId);
48
107
 
49
- const response = await fetch(`${getServerUrl()}/api/tokens/activate`, {
108
+ const response = await fetch(`${getServerUrl()}/api/v1/tokens/activate`, {
50
109
  method: 'POST',
51
110
  headers: {
52
111
  'Content-Type': 'application/json',
53
112
  'Authorization': `Bearer ${sessionToken}`,
54
- 'X-Device-ID': deviceId
113
+ 'X-Device-ID': deviceId,
114
+ 'X-Timestamp': timestamp.toString(),
115
+ 'X-Signature': signature
55
116
  },
56
117
  body: JSON.stringify({ token_id: tokenId })
57
118
  });
@@ -66,12 +127,17 @@ async function heartbeat() {
66
127
 
67
128
  if (!sessionToken) return { valid: false };
68
129
 
69
- const response = await fetch(`${getServerUrl()}/api/heartbeat`, {
130
+ const timestamp = Math.floor(Date.now() / 1000);
131
+ const signature = generateSignature(sessionToken, timestamp, deviceId);
132
+
133
+ const response = await fetch(`${getServerUrl()}/api/v1/auth/heartbeat`, {
70
134
  method: 'POST',
71
135
  headers: {
72
136
  'Content-Type': 'application/json',
73
137
  'Authorization': `Bearer ${sessionToken}`,
74
- 'X-Device-ID': deviceId
138
+ 'X-Device-ID': deviceId,
139
+ 'X-Timestamp': timestamp.toString(),
140
+ 'X-Signature': signature
75
141
  }
76
142
  });
77
143
 
@@ -82,13 +148,17 @@ async function heartbeat() {
82
148
  async function unbind() {
83
149
  const sessionToken = config.get('sessionToken');
84
150
  const deviceId = getDeviceId();
151
+ const timestamp = Math.floor(Date.now() / 1000);
152
+ const signature = generateSignature(sessionToken, timestamp, deviceId);
85
153
 
86
- const response = await fetch(`${getServerUrl()}/api/unbind`, {
154
+ const response = await fetch(`${getServerUrl()}/api/v1/auth/unbind`, {
87
155
  method: 'POST',
88
156
  headers: {
89
157
  'Content-Type': 'application/json',
90
158
  'Authorization': `Bearer ${sessionToken}`,
91
- 'X-Device-ID': deviceId
159
+ 'X-Device-ID': deviceId,
160
+ 'X-Timestamp': timestamp.toString(),
161
+ 'X-Signature': signature
92
162
  }
93
163
  });
94
164