Explorar o código

feat: 增加加密

chengchongzhen hai 1 ano
pai
achega
e8bc3e08f8
Modificáronse 3 ficheiros con 174 adicións e 37 borrados
  1. 73 0
      client_decrypt.py
  2. 66 23
      license_manager.py
  3. 35 14
      server/server.js

+ 73 - 0
client_decrypt.py

@@ -0,0 +1,73 @@
+from Crypto.Cipher import AES
+import json
+import binascii
+
+
+class ResponseDecryptor:
+    def __init__(self, encryption_key):
+        """
+        初始化解密器
+        :param encryption_key: 十六进制格式的密钥字符串
+        """
+        # 将十六进制字符串转换为字节
+        self.key = binascii.unhexlify(encryption_key)
+
+    def decrypt_response(self, encrypted_data):
+        """
+        解密服务器响应的数据
+        :param encrypted_data: 加密的数据字符串 (格式: "iv:encrypted")
+        :return: 解密后的 JSON 数据
+        """
+        try:
+            # 分离 IV 和加密数据
+            iv_hex, encrypted_text = encrypted_data.split(":")
+
+            # 将十六进制转换为字节
+            iv = binascii.unhexlify(iv_hex)
+            encrypted_bytes = binascii.unhexlify(encrypted_text)
+
+            # 创建解密器
+            cipher = AES.new(self.key, AES.MODE_CBC, iv)
+
+            # 解密数据
+            decrypted_bytes = cipher.decrypt(encrypted_bytes)
+
+            # 移除填充
+            padding_length = decrypted_bytes[-1]
+            decrypted_data = decrypted_bytes[:-padding_length]
+
+            # 转换为字符串并解析 JSON
+            decrypted_str = decrypted_data.decode("utf-8")
+            return json.loads(decrypted_str)
+
+        except Exception as e:
+            raise Exception(f"解密失败: {str(e)}")
+
+
+# 使用示例
+def main():
+    # 这里填入与服务器相同的加密密钥(十六进制格式)
+    ENCRYPTION_KEY = "f1e2d3c4b5a6978899aabbccddeeff00112233445566778899aabbccddeeff00"  # 替换为实际的密钥
+
+    # 创建解密器实例
+    decryptor = ResponseDecryptor(ENCRYPTION_KEY)
+
+    # 模拟服务器响应
+    server_response = {
+        "encrypted_data": "iv_hex:encrypted_data_hex"  # 这里是服务器返回的加密数据
+    }
+
+    try:
+        # 解密数据
+        decrypted_data = decryptor.decrypt_response(server_response["encrypted_data"])
+        print("解密后的数据:", decrypted_data)
+
+        # 现在可以访问解密后的数据
+        if decrypted_data.get("success"):
+            print("操作成功!")
+            # 处理其他数据...
+        else:
+            print("操作失败:", decrypted_data.get("message"))
+
+    except Exception as e:
+        print("错误:", str(e))

+ 66 - 23
license_manager.py

@@ -9,6 +9,8 @@ from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
 from cryptography.hazmat.backends import default_backend
 import base64
 import time
+from Crypto.Cipher import AES
+import binascii
 
 
 class LicenseManager:
@@ -24,7 +26,11 @@ class LicenseManager:
         self.license_file = os.path.join(config_dir, "CursorPro", "license.json")
         self.activation_url = "http://119.8.35.41:3003/activate"
         self.verify_url = "http://119.8.35.41:3003/verify"
+        # 开发环境
+        # self.activation_url = "http://127.0.0.1:3000/activate"
+        # self.verify_url = "http://127.0.0.1:3000/verify"
         self.key = b"Kj8nP9x2Qs5mY7vR4wL1hC3fA6tD0iB8"
+        self.encryption_key = b"f1e2d3c4b5a6978899aabbccddeeff00112233445566778899aabbccddeeff00"  # 与服务器端相同的密钥
 
     def encrypt(self, text):
         """使用AES-256-CBC加密"""
@@ -96,20 +102,27 @@ class LicenseManager:
                 )
 
                 if response.status_code == 200:
-                    result = response.json()
-                    if result.get("success"):
-                        license_data = {
-                            "license_key": license_key,
-                            "machine_code": machine_code,
-                            "activation_date": activation_data["activation_date"],
-                            "expiry_date": result.get("expiry_date"),
-                            "is_active": True,
-                        }
-                        self._save_license(license_data)
-                        return True, "激活成功!"
-                    else:
-                        error_msg = result.get("message", "激活失败")
-                        return False, error_msg
+                    try:
+                        encrypted_response = response.json()
+                        result = self.decrypt_response(
+                            encrypted_response["encrypted_data"]
+                        )
+                        if result.get("success"):
+                            license_data = {
+                                "license_key": license_key,
+                                "machine_code": machine_code,
+                                "activation_date": activation_data["activation_date"],
+                                "expiry_date": result.get("expiry_date"),
+                                "is_active": True,
+                            }
+                            self._save_license(license_data)
+                            return True, "激活成功!"
+                        else:
+                            error_msg = result.get("message", "激活失败")
+                            return False, error_msg
+                    except Exception as e:
+                        return False, f"解密响应失败: {str(e)}"
+
                 else:
                     return False, f"服务器响应错误: HTTP {response.status_code}"
 
@@ -117,10 +130,39 @@ class LicenseManager:
                 return False, "无法连接到激活服务器,请检查网络连接"
             except requests.exceptions.Timeout:
                 return False, "服务器响应超时"
+            except Exception as e:
+                return False, f"激活请求失败: {str(e)}"
 
         except Exception as e:
             return False, f"激活过程出错: {str(e)}"
 
+    def decrypt_response(self, encrypted_data):
+        """解密服务器响应的数据"""
+        try:
+            # 分离 IV 和加密数据
+            iv_hex, encrypted_text = encrypted_data.split(":")
+
+            # 将十六进制转换为字节
+            iv = binascii.unhexlify(iv_hex)
+            encrypted_bytes = binascii.unhexlify(encrypted_text)
+
+            # 创建解密器
+            cipher = AES.new(binascii.unhexlify(self.encryption_key), AES.MODE_CBC, iv)
+
+            # 解密数据
+            decrypted_bytes = cipher.decrypt(encrypted_bytes)
+
+            # 移除填充
+            padding_length = decrypted_bytes[-1]
+            decrypted_data = decrypted_bytes[:-padding_length]
+
+            # 转换为字符串并解析 JSON
+            decrypted_str = decrypted_data.decode("utf-8")
+            return json.loads(decrypted_str)
+
+        except Exception as e:
+            raise Exception(f"解密失败: {str(e)}")
+
     def verify_license(self):
         """验证许可证"""
         try:
@@ -142,18 +184,19 @@ class LicenseManager:
 
             try:
                 response = requests.post(self.verify_url, json=verify_data, timeout=30)
-
                 time.sleep(2)
 
-                try:
-                    result = response.json()
-                except Exception:
-                    return False, "服务器响应格式错误"
-
                 if response.status_code == 200:
-                    if result.get("success"):
-                        return True, "许可证有效"
-                    return False, result.get("message", "许可证无效")
+                    try:
+                        encrypted_response = response.json()
+                        result = self.decrypt_response(
+                            encrypted_response["encrypted_data"]
+                        )
+                        if result.get("success"):
+                            return True, "许可证有效"
+                        return False, result.get("message", "许可证无效")
+                    except Exception as e:
+                        return False, f"解密响应失败: {str(e)}"
 
                 return False, f"服务器响应错误: HTTP {response.status_code}"
 

+ 35 - 14
server/server.js

@@ -52,6 +52,21 @@ function generateLicenseKey() {
     return encrypted;
 }
 
+// 在现有的加密函数下添加新的响应加密函数
+function encryptResponse(data) {
+    // 将对象转换为 JSON 字符串
+    const jsonStr = JSON.stringify(data);
+    const key = Buffer.from(process.env.ENCRYPTION_KEY, 'hex');
+    const iv = getIV();
+    const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
+    let encrypted = cipher.update(jsonStr, 'utf8', 'hex');
+    encrypted += cipher.final('hex');
+    // 将 IV 附加到加密文本中
+    return {
+        encrypted_data: iv.toString('hex') + ':' + encrypted
+    };
+}
+
 // Connect to MongoDB
 mongoose.connect(process.env.MONGODB_URI, {
     useNewUrlParser: true,
@@ -86,22 +101,24 @@ app.post(`/${GENERATE_PATH}`, async (req, res) => {
     try {
         const licenseKey = generateLicenseKey();
         
-        // 保存生成的许可证记录
         await LicenseKey.create({
             licenseKey: licenseKey,
             isUsed: false
         });
 
-        return res.json({
+        // 加密响应数据
+        const responseData = {
             success: true,
             license_key: licenseKey
-        });
+        };
+        
+        return res.json(responseData);
     } catch (error) {
         console.error('生成许可证错误:', error);
-        return res.status(500).json({
+        return res.status(500).json(encryptResponse({
             success: false,
             message: '服务器错误'
-        });
+        }));
     }
 });
 
@@ -164,7 +181,7 @@ app.post('/activate', async (req, res) => {
             expiryDate: expiryDate,
             isActive: true,
             maxUsageCount: process.env.MAX_USAGE_COUNT || 10,
-            currentUsageCount: 0
+            currentUsageCount: 1
         }]);
        
 
@@ -172,17 +189,19 @@ app.post('/activate', async (req, res) => {
         licenseKeyRecord.isUsed = true;
         await licenseKeyRecord.save();
 
-        return res.json({
+        const responseData = {
             success: true,
             message: '激活成功',
             expiry_date: expiryDate
-        });
+        };
+        
+        return res.json(encryptResponse(responseData));
     } catch (error) {
         console.error('激活错误:', error);
-        return res.status(500).json({
+        return res.status(500).json(encryptResponse({
             success: false,
             message: '服务器错误'
-        });
+        }));
     }
 });
 
@@ -255,7 +274,7 @@ app.post('/verify', async (req, res) => {
         license.currentUsageCount += 1;
         await license.save();
 
-        return res.json({
+        const responseData = {
             success: true,
             message: '许可证有效',
             expiry_date: formatChinaTime(license.expiryDate, 'YYYY-MM-DD'),
@@ -263,13 +282,15 @@ app.post('/verify', async (req, res) => {
                 current: license.currentUsageCount,
                 max: license.maxUsageCount
             }
-        });
+        };
+        
+        return res.json(encryptResponse(responseData));
     } catch (error) {
         console.error('验证错误:', error);
-        return res.status(500).json({
+        return res.status(500).json(encryptResponse({
             success: false,
             message: '服务器错误'
-        });
+        }));
     }
 });