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