File size: 2,885 Bytes
3c8ff75
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// authService.js
const { encrypt, decrypt } = require('../utils/cryptoUtils');

// 简单的内存存储用于保存会话密钥
// 在生产环境中,应该使用数据库或其他持久化存储
const sessionKeys = new Map();

/**
 * 生成会话密钥
 * @param {string} clientId - 客户端标识
 * @returns {string} 会话密钥
 */
function generateSessionKey(clientId) {
  // 生成一个随机的会话密钥
  const sessionKey = require('crypto').randomBytes(32).toString('hex');
  
  // 保存会话密钥
  sessionKeys.set(clientId, sessionKey);
  
  return sessionKey;
}

/**
 * 验证客户端
 * @param {string} clientId - 客户端标识
 * @param {string} clientSecret - 客户端密钥
 * @returns {boolean} 验证是否成功
 */
function authenticateClient(clientId, clientSecret) {
  // 在实际应用中,应该从数据库或其他安全存储中获取客户端密钥
  // 这里为了简化,使用硬编码的密钥
  const validClientId = 'test-client';
  const validClientSecret = 'test-secret';
  
  return clientId === validClientId && clientSecret === validClientSecret;
}

/**
 * 获取客户端的会话密钥
 * @param {string} clientId - 客户端标识
 * @returns {string|null} 会话密钥或 null
 */
function getSessionKey(clientId) {
  return sessionKeys.get(clientId) || null;
}

/**
 * 删除客户端的会话密钥
 * @param {string} clientId - 客户端标识
 */
function removeSessionKey(clientId) {
  sessionKeys.delete(clientId);
}

/**
 * 加密数据包
 * @param {Buffer} data - 要加密的数据
 * @param {string} clientId - 客户端标识
 * @returns {Buffer} 加密后的数据
 */
function encryptPacket(data, clientId) {
  const sessionKey = getSessionKey(clientId);
  
  if (!sessionKey) {
    throw new Error('未找到会话密钥');
  }
  
  // 加密数据
  const encrypted = encrypt(data, sessionKey);
  
  // 将加密参数和数据组合成一个缓冲区
  // 格式: salt(16) + iv(12) + authTag(16) + encryptedData(n)
  const result = Buffer.concat([
    encrypted.salt,
    encrypted.iv,
    encrypted.authTag,
    encrypted.data
  ]);
  
  return result;
}

/**
 * 解密数据包
 * @param {Buffer} encryptedData - 加密的数据
 * @param {string} clientId - 客户端标识
 * @returns {Buffer} 解密后的数据
 */
function decryptPacket(encryptedData, clientId) {
  const sessionKey = getSessionKey(clientId);
  
  if (!sessionKey) {
    throw new Error('未找到会话密钥');
  }
  
  // 解析加密参数
  const salt = encryptedData.slice(0, 16);
  const iv = encryptedData.slice(16, 28);
  const authTag = encryptedData.slice(28, 44);
  const data = encryptedData.slice(44);
  
  // 解密数据
  return decrypt(data, salt, iv, authTag, sessionKey);
}

module.exports = {
  generateSessionKey,
  authenticateClient,
  getSessionKey,
  removeSessionKey,
  encryptPacket,
  decryptPacket
};