atm-droid 1.0.1 → 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.
- package/package.json +1 -1
- package/src/api.js +49 -7
package/package.json
CHANGED
package/src/api.js
CHANGED
|
@@ -28,6 +28,27 @@ function generateSignature(data, timestamp, deviceId) {
|
|
|
28
28
|
return hmac.digest('hex');
|
|
29
29
|
}
|
|
30
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
|
+
|
|
31
52
|
// 激活码登录
|
|
32
53
|
async function activate(code) {
|
|
33
54
|
const deviceId = getDeviceId();
|
|
@@ -51,19 +72,27 @@ async function getTokens() {
|
|
|
51
72
|
throw new Error('未登录');
|
|
52
73
|
}
|
|
53
74
|
|
|
75
|
+
const timestamp = Math.floor(Date.now() / 1000);
|
|
76
|
+
const signature = generateSignature(sessionToken, timestamp, deviceId);
|
|
77
|
+
|
|
54
78
|
const response = await fetch(`${getServerUrl()}/api/v1/tokens`, {
|
|
55
79
|
headers: {
|
|
56
80
|
'Authorization': `Bearer ${sessionToken}`,
|
|
57
|
-
'X-Device-ID': deviceId
|
|
81
|
+
'X-Device-ID': deviceId,
|
|
82
|
+
'X-Timestamp': timestamp.toString(),
|
|
83
|
+
'X-Signature': signature
|
|
58
84
|
}
|
|
59
85
|
});
|
|
60
86
|
|
|
61
87
|
const result = await response.json();
|
|
62
88
|
|
|
63
89
|
// 如果返回加密数据,需要解密
|
|
64
|
-
if (result.success && result.data && result.iv) {
|
|
65
|
-
|
|
66
|
-
|
|
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: '解密失败' };
|
|
67
96
|
}
|
|
68
97
|
|
|
69
98
|
return result;
|
|
@@ -73,13 +102,17 @@ async function getTokens() {
|
|
|
73
102
|
async function activateToken(tokenId) {
|
|
74
103
|
const sessionToken = config.get('sessionToken');
|
|
75
104
|
const deviceId = getDeviceId();
|
|
105
|
+
const timestamp = Math.floor(Date.now() / 1000);
|
|
106
|
+
const signature = generateSignature(sessionToken, timestamp, deviceId);
|
|
76
107
|
|
|
77
108
|
const response = await fetch(`${getServerUrl()}/api/v1/tokens/activate`, {
|
|
78
109
|
method: 'POST',
|
|
79
110
|
headers: {
|
|
80
111
|
'Content-Type': 'application/json',
|
|
81
112
|
'Authorization': `Bearer ${sessionToken}`,
|
|
82
|
-
'X-Device-ID': deviceId
|
|
113
|
+
'X-Device-ID': deviceId,
|
|
114
|
+
'X-Timestamp': timestamp.toString(),
|
|
115
|
+
'X-Signature': signature
|
|
83
116
|
},
|
|
84
117
|
body: JSON.stringify({ token_id: tokenId })
|
|
85
118
|
});
|
|
@@ -94,12 +127,17 @@ async function heartbeat() {
|
|
|
94
127
|
|
|
95
128
|
if (!sessionToken) return { valid: false };
|
|
96
129
|
|
|
130
|
+
const timestamp = Math.floor(Date.now() / 1000);
|
|
131
|
+
const signature = generateSignature(sessionToken, timestamp, deviceId);
|
|
132
|
+
|
|
97
133
|
const response = await fetch(`${getServerUrl()}/api/v1/auth/heartbeat`, {
|
|
98
134
|
method: 'POST',
|
|
99
135
|
headers: {
|
|
100
136
|
'Content-Type': 'application/json',
|
|
101
137
|
'Authorization': `Bearer ${sessionToken}`,
|
|
102
|
-
'X-Device-ID': deviceId
|
|
138
|
+
'X-Device-ID': deviceId,
|
|
139
|
+
'X-Timestamp': timestamp.toString(),
|
|
140
|
+
'X-Signature': signature
|
|
103
141
|
}
|
|
104
142
|
});
|
|
105
143
|
|
|
@@ -110,13 +148,17 @@ async function heartbeat() {
|
|
|
110
148
|
async function unbind() {
|
|
111
149
|
const sessionToken = config.get('sessionToken');
|
|
112
150
|
const deviceId = getDeviceId();
|
|
151
|
+
const timestamp = Math.floor(Date.now() / 1000);
|
|
152
|
+
const signature = generateSignature(sessionToken, timestamp, deviceId);
|
|
113
153
|
|
|
114
154
|
const response = await fetch(`${getServerUrl()}/api/v1/auth/unbind`, {
|
|
115
155
|
method: 'POST',
|
|
116
156
|
headers: {
|
|
117
157
|
'Content-Type': 'application/json',
|
|
118
158
|
'Authorization': `Bearer ${sessionToken}`,
|
|
119
|
-
'X-Device-ID': deviceId
|
|
159
|
+
'X-Device-ID': deviceId,
|
|
160
|
+
'X-Timestamp': timestamp.toString(),
|
|
161
|
+
'X-Signature': signature
|
|
120
162
|
}
|
|
121
163
|
});
|
|
122
164
|
|