From a1d7e81859f554f3a53680cc35f0f49bf1f77098 Mon Sep 17 00:00:00 2001
From: wwf <1971391498@qq.com>
Date: 星期四, 14 五月 2026 14:37:02 +0800
Subject: [PATCH] 导入项目

---
 src/utils/encrypt.ts |  231 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 231 insertions(+), 0 deletions(-)

diff --git a/src/utils/encrypt.ts b/src/utils/encrypt.ts
new file mode 100644
index 0000000..aee289e
--- /dev/null
+++ b/src/utils/encrypt.ts
@@ -0,0 +1,231 @@
+import CryptoJS from 'crypto-js'
+import { JSEncrypt } from 'jsencrypt'
+
+/**
+ * API 鍔犺В瀵嗗伐鍏风被
+ * 鏀寔 AES 鍜� RSA 鍔犲瘑绠楁硶
+ */
+
+// 浠庣幆澧冨彉閲忚幏鍙栭厤缃�
+const API_ENCRYPT_ENABLE = import.meta.env.VITE_APP_API_ENCRYPT_ENABLE === 'true'
+const API_ENCRYPT_HEADER = import.meta.env.VITE_APP_API_ENCRYPT_HEADER || 'X-Api-Encrypt'
+const API_ENCRYPT_ALGORITHM = import.meta.env.VITE_APP_API_ENCRYPT_ALGORITHM || 'AES'
+const API_ENCRYPT_REQUEST_KEY = import.meta.env.VITE_APP_API_ENCRYPT_REQUEST_KEY || '' // AES瀵嗛挜 鎴� RSA鍏挜
+const API_ENCRYPT_RESPONSE_KEY = import.meta.env.VITE_APP_API_ENCRYPT_RESPONSE_KEY || '' // AES瀵嗛挜 鎴� RSA绉侀挜
+
+/**
+ * AES 鍔犲瘑宸ュ叿绫�
+ */
+export class AES {
+  /**
+   * AES 鍔犲瘑
+   * @param data 瑕佸姞瀵嗙殑鏁版嵁
+   * @param key 鍔犲瘑瀵嗛挜
+   * @returns 鍔犲瘑鍚庣殑瀛楃涓�
+   */
+  static encrypt(data: string, key: string): string {
+    try {
+      if (!key) {
+        throw new Error('AES 鍔犲瘑瀵嗛挜涓嶈兘涓虹┖')
+      }
+      if (key.length !== 32) {
+        throw new Error(`AES 鍔犲瘑瀵嗛挜闀垮害蹇呴』涓� 32 浣嶏紝褰撳墠闀垮害: ${key.length}`)
+      }
+
+      const keyUtf8 = CryptoJS.enc.Utf8.parse(key)
+      const encrypted = CryptoJS.AES.encrypt(data, keyUtf8, {
+        mode: CryptoJS.mode.ECB,
+        padding: CryptoJS.pad.Pkcs7
+      })
+      return encrypted.toString()
+    } catch (error) {
+      console.error('AES 鍔犲瘑澶辫触:', error)
+      throw error
+    }
+  }
+
+  /**
+   * AES 瑙e瘑
+   * @param encryptedData 鍔犲瘑鐨勬暟鎹�
+   * @param key 瑙e瘑瀵嗛挜
+   * @returns 瑙e瘑鍚庣殑瀛楃涓�
+   */
+  static decrypt(encryptedData: string, key: string): string {
+    try {
+      if (!key) {
+        throw new Error('AES 瑙e瘑瀵嗛挜涓嶈兘涓虹┖')
+      }
+      if (key.length !== 32) {
+        throw new Error(`AES 瑙e瘑瀵嗛挜闀垮害蹇呴』涓� 32 浣嶏紝褰撳墠闀垮害: ${key.length}`)
+      }
+      if (!encryptedData) {
+        throw new Error('AES 瑙e瘑鏁版嵁涓嶈兘涓虹┖')
+      }
+
+      const keyUtf8 = CryptoJS.enc.Utf8.parse(key)
+      const decrypted = CryptoJS.AES.decrypt(encryptedData, keyUtf8, {
+        mode: CryptoJS.mode.ECB,
+        padding: CryptoJS.pad.Pkcs7
+      })
+      const result = decrypted.toString(CryptoJS.enc.Utf8)
+      if (!result) {
+        throw new Error('AES 瑙e瘑缁撴灉涓虹┖锛屽彲鑳芥槸瀵嗛挜閿欒鎴栨暟鎹崯鍧�')
+      }
+      return result
+    } catch (error) {
+      console.error('AES 瑙e瘑澶辫触:', error)
+      throw error
+    }
+  }
+}
+
+/**
+ * RSA 鍔犲瘑宸ュ叿绫�
+ */
+export class RSA {
+  /**
+   * RSA 鍔犲瘑
+   * @param data 瑕佸姞瀵嗙殑鏁版嵁
+   * @param publicKey 鍏挜锛堝繀闇�锛�
+   * @returns 鍔犲瘑鍚庣殑瀛楃涓�
+   */
+  static encrypt(data: string, publicKey: string): string | false {
+    try {
+      if (!publicKey) {
+        throw new Error('RSA 鍏挜涓嶈兘涓虹┖')
+      }
+
+      const encryptor = new JSEncrypt()
+      encryptor.setPublicKey(publicKey)
+      const result = encryptor.encrypt(data)
+      if (result === false) {
+        throw new Error('RSA 鍔犲瘑澶辫触锛屽彲鑳芥槸鍏挜鏍煎紡閿欒鎴栨暟鎹繃闀�')
+      }
+      return result
+    } catch (error) {
+      console.error('RSA 鍔犲瘑澶辫触:', error)
+      throw error
+    }
+  }
+
+  /**
+   * RSA 瑙e瘑
+   * @param encryptedData 鍔犲瘑鐨勬暟鎹�
+   * @param privateKey 绉侀挜锛堝繀闇�锛�
+   * @returns 瑙e瘑鍚庣殑瀛楃涓�
+   */
+  static decrypt(encryptedData: string, privateKey: string): string | false {
+    try {
+      if (!privateKey) {
+        throw new Error('RSA 绉侀挜涓嶈兘涓虹┖')
+      }
+      if (!encryptedData) {
+        throw new Error('RSA 瑙e瘑鏁版嵁涓嶈兘涓虹┖')
+      }
+
+      const encryptor = new JSEncrypt()
+      encryptor.setPrivateKey(privateKey)
+      const result = encryptor.decrypt(encryptedData)
+      if (result === false) {
+        throw new Error('RSA 瑙e瘑澶辫触锛屽彲鑳芥槸绉侀挜閿欒鎴栨暟鎹崯鍧�')
+      }
+      return result
+    } catch (error) {
+      console.error('RSA 瑙e瘑澶辫触:', error)
+      throw error
+    }
+  }
+}
+
+/**
+ * API 鍔犺В瀵嗕富绫�
+ */
+export class ApiEncrypt {
+  /**
+   * 鑾峰彇鍔犲瘑澶村悕绉�
+   */
+  static getEncryptHeader(): string {
+    return API_ENCRYPT_HEADER
+  }
+
+  /**
+   * 鍔犲瘑璇锋眰鏁版嵁
+   * @param data 瑕佸姞瀵嗙殑鏁版嵁
+   * @returns 鍔犲瘑鍚庣殑鏁版嵁
+   */
+  static encryptRequest(data: any): string {
+    if (!API_ENCRYPT_ENABLE) {
+      return data
+    }
+
+    try {
+      const jsonData = typeof data === 'string' ? data : JSON.stringify(data)
+
+      if (API_ENCRYPT_ALGORITHM.toUpperCase() === 'AES') {
+        if (!API_ENCRYPT_REQUEST_KEY) {
+          throw new Error('AES 璇锋眰鍔犲瘑瀵嗛挜鏈厤缃�')
+        }
+        return AES.encrypt(jsonData, API_ENCRYPT_REQUEST_KEY)
+      } else if (API_ENCRYPT_ALGORITHM.toUpperCase() === 'RSA') {
+        if (!API_ENCRYPT_REQUEST_KEY) {
+          throw new Error('RSA 鍏挜鏈厤缃�')
+        }
+        const result = RSA.encrypt(jsonData, API_ENCRYPT_REQUEST_KEY)
+        if (result === false) {
+          throw new Error('RSA 鍔犲瘑澶辫触')
+        }
+        return result
+      } else {
+        throw new Error(`涓嶆敮鎸佺殑鍔犲瘑绠楁硶: ${API_ENCRYPT_ALGORITHM}`)
+      }
+    } catch (error) {
+      console.error('璇锋眰鏁版嵁鍔犲瘑澶辫触:', error)
+      throw error
+    }
+  }
+
+  /**
+   * 瑙e瘑鍝嶅簲鏁版嵁
+   * @param encryptedData 鍔犲瘑鐨勫搷搴旀暟鎹�
+   * @returns 瑙e瘑鍚庣殑鏁版嵁
+   */
+  static decryptResponse(encryptedData: string): any {
+    if (!API_ENCRYPT_ENABLE) {
+      return encryptedData
+    }
+
+    try {
+      let decryptedData: string | false = ''
+      if (API_ENCRYPT_ALGORITHM.toUpperCase() === 'AES') {
+        if (!API_ENCRYPT_RESPONSE_KEY) {
+          throw new Error('AES 鍝嶅簲瑙e瘑瀵嗛挜鏈厤缃�')
+        }
+        decryptedData = AES.decrypt(encryptedData, API_ENCRYPT_RESPONSE_KEY)
+      } else if (API_ENCRYPT_ALGORITHM.toUpperCase() === 'RSA') {
+        if (!API_ENCRYPT_RESPONSE_KEY) {
+          throw new Error('RSA 绉侀挜鏈厤缃�')
+        }
+        decryptedData = RSA.decrypt(encryptedData, API_ENCRYPT_RESPONSE_KEY)
+        if (decryptedData === false) {
+          throw new Error('RSA 瑙e瘑澶辫触')
+        }
+      } else {
+        throw new Error(`涓嶆敮鎸佺殑瑙e瘑绠楁硶: ${API_ENCRYPT_ALGORITHM}`)
+      }
+
+      if (!decryptedData) {
+        throw new Error('瑙e瘑缁撴灉涓虹┖')
+      }
+
+      // 灏濊瘯瑙f瀽涓� JSON锛屽鏋滃け璐ュ垯杩斿洖鍘熷瓧绗︿覆
+      try {
+        return JSON.parse(decryptedData)
+      } catch {
+        return decryptedData
+      }
+    } catch (error) {
+      console.error('鍝嶅簲鏁版嵁瑙e瘑澶辫触:', error)
+      throw error
+    }
+  }
+}

--
Gitblit v1.8.0