|
|
@@ -1,9 +1,34 @@
|
|
|
import CryptoJS from 'crypto-js'
|
|
|
+const key = '49PBou+TREIOzSHj'
|
|
|
const key1 = CryptoJS.enc.Utf8.parse('dmngJmmO+9GMw+tu')
|
|
|
-const key2 = CryptoJS.enc.Utf8.parse('49PBou+TREIOzSHj')
|
|
|
+const key2 = CryptoJS.enc.Utf8.parse(key)
|
|
|
// 固定IV 用于密码、get请求参数加密
|
|
|
const defaultIv = CryptoJS.enc.Utf8.parse('5lDsNRe&UduJ97uS')
|
|
|
|
|
|
+// 密钥派生参数配置
|
|
|
+const PBKDF2_CONFIG = {
|
|
|
+ // 盐值长度(bits)
|
|
|
+ saltSize: 128,
|
|
|
+ // 迭代次数
|
|
|
+ iterations: 10000,
|
|
|
+ // 密钥长度(256bit)
|
|
|
+ keySize: 256 / 32,
|
|
|
+ hashAlgorithm: CryptoJS.algo.SHA256
|
|
|
+}
|
|
|
+
|
|
|
+// 动态密钥派生器
|
|
|
+const deriveDynamicKey = (token, salt) => {
|
|
|
+ if (!token || typeof token !== 'string') {
|
|
|
+ throw new Error('Invalid user token')
|
|
|
+ }
|
|
|
+
|
|
|
+ return CryptoJS.PBKDF2(token, salt, {
|
|
|
+ keySize: PBKDF2_CONFIG.keySize,
|
|
|
+ iterations: PBKDF2_CONFIG.iterations,
|
|
|
+ hasher: PBKDF2_CONFIG.hashAlgorithm
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
// 动态IV生成器
|
|
|
export const generateDynamicIV = () => {
|
|
|
// 1. 获取当前时间戳(8字节,64位)
|
|
|
@@ -31,25 +56,58 @@ export const generateDynamicIV = () => {
|
|
|
return CryptoJS.lib.WordArray.create(ivWords, 16)
|
|
|
}
|
|
|
|
|
|
-// AES加密
|
|
|
-export const encryptByAes = (params, type = 'normal') => {
|
|
|
+const xorEncrypt = (text) => {
|
|
|
let encrypted = ''
|
|
|
- const key = type === 'normal' ? key1 : key2
|
|
|
- const iv = type === 'normal' ? generateDynamicIV() : defaultIv
|
|
|
- if (typeof params === 'string' || typeof params === 'object') {
|
|
|
+ for (let i = 0; i < text.length; i++) {
|
|
|
+ const charCode = text.charCodeAt(i) ^ key.charCodeAt(i % key.length)
|
|
|
+ encrypted += String.fromCharCode(charCode)
|
|
|
+ }
|
|
|
+
|
|
|
+ return btoa(encrypted)
|
|
|
+}
|
|
|
+
|
|
|
+const xorDecrypt = (encryptedBase64) => {
|
|
|
+ // 从Base64解码
|
|
|
+ const decodedStr = atob(encryptedBase64)
|
|
|
+ let decrypted = ''
|
|
|
+
|
|
|
+ // 异或解密
|
|
|
+ for (let i = 0; i < decodedStr.length; i++) {
|
|
|
+ const charCode = decodedStr.charCodeAt(i) ^ key.charCodeAt(i % key.length)
|
|
|
+ decrypted += String.fromCharCode(charCode)
|
|
|
+ }
|
|
|
+
|
|
|
+ return decrypted
|
|
|
+}
|
|
|
+
|
|
|
+// AES加密
|
|
|
+export const encryptByAes = (params, type = 'dynamic', token) => {
|
|
|
+ try {
|
|
|
+ const isDynamic = type === 'dynamic'
|
|
|
+ // 生成随机盐值
|
|
|
+ const salt = CryptoJS.lib.WordArray.random(PBKDF2_CONFIG.saltSize)
|
|
|
+ // 动态派生密钥
|
|
|
+ const derivedKey = isDynamic ? deriveDynamicKey(token, salt) : key2
|
|
|
+ // 生成动态iv
|
|
|
+ const iv = isDynamic ? generateDynamicIV() : defaultIv
|
|
|
const data = typeof params === 'string' ? params : JSON.stringify(params)
|
|
|
const srcs = CryptoJS.enc.Utf8.parse(data)
|
|
|
- encrypted = CryptoJS.AES.encrypt(srcs, key, {
|
|
|
+
|
|
|
+ const encrypted = CryptoJS.AES.encrypt(srcs, derivedKey, {
|
|
|
iv: iv,
|
|
|
mode: CryptoJS.mode.CBC,
|
|
|
padding: CryptoJS.pad.Pkcs7
|
|
|
})
|
|
|
- }
|
|
|
|
|
|
- return type === 'normal' ? {
|
|
|
- ciphertext: encrypted.ciphertext.toString(CryptoJS.enc.Base64),
|
|
|
- iv: iv.toString(CryptoJS.enc.Base64)
|
|
|
- } : encrypted.ciphertext.toString(CryptoJS.enc.Base64)
|
|
|
+ if (isDynamic) {
|
|
|
+ const str = encrypted.ciphertext.toString(CryptoJS.enc.Base64) + '|' + iv.toString(CryptoJS.enc.Base64) + '|' + salt.toString(CryptoJS.enc.Base64) + '|' + token
|
|
|
+ return xorEncrypt(str)
|
|
|
+ }
|
|
|
+ return encrypted.ciphertext.toString(CryptoJS.enc.Base64)
|
|
|
+ } catch (error) {
|
|
|
+ console.error('Encryption error:', error)
|
|
|
+ throw new Error('Encryption failed')
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
const isValidBase64 = (str) => {
|
|
|
@@ -60,32 +118,39 @@ const isValidBase64 = (str) => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-export const decryptByAes = (encryptedText, ivBase64 = null, type = 'normal') => {
|
|
|
- const key = type === 'normal' ? key1 : key2
|
|
|
+export const decryptByAes = (ciphertext) => {
|
|
|
+ try {
|
|
|
+ // 初始化解密参数
|
|
|
+ let cipherToDecrypt = ciphertext
|
|
|
+ let iv = defaultIv
|
|
|
+ let key = key2
|
|
|
|
|
|
- if (!isValidBase64(ivBase64)) {
|
|
|
- console.error('ivBase64不是有效的 Base64 字符串')
|
|
|
- return ''
|
|
|
- }
|
|
|
- // 解析动态IV
|
|
|
- const iv = CryptoJS.enc.Base64.parse(ivBase64)
|
|
|
+ // 尝试XOR解密并解析参数
|
|
|
+ const decryptedStr = xorDecrypt(ciphertext)
|
|
|
+ const parts = decryptedStr.split('|')
|
|
|
+ if (parts.length === 4) {
|
|
|
+ const [ciphertextBase64, ivBase64, saltBase64, token] = parts
|
|
|
|
|
|
- const options = {
|
|
|
- iv: iv,
|
|
|
- mode: CryptoJS.mode.CBC,
|
|
|
- padding: CryptoJS.pad.Pkcs7
|
|
|
- }
|
|
|
+ if (token && !(isValidBase64(ivBase64) && isValidBase64(saltBase64))) {
|
|
|
+ console.error('解密失败: 无效的IV参数或salt参数!')
|
|
|
+ return ''
|
|
|
+ }
|
|
|
+ // 转换编码
|
|
|
+ iv = CryptoJS.enc.Base64.parse(ivBase64)
|
|
|
+ const salt = CryptoJS.enc.Base64.parse(saltBase64)
|
|
|
+ // 动态派生密钥
|
|
|
+ key = deriveDynamicKey(token, salt)
|
|
|
+ cipherToDecrypt = ciphertextBase64
|
|
|
+ }
|
|
|
|
|
|
- try {
|
|
|
- const encryptedData = CryptoJS.enc.Base64.parse(encryptedText)
|
|
|
- const decryptedData = CryptoJS.AES.decrypt(
|
|
|
- { ciphertext: encryptedData },
|
|
|
+ // 解密
|
|
|
+ const decrypted = CryptoJS.AES.decrypt(
|
|
|
+ { ciphertext: CryptoJS.enc.Base64.parse(cipherToDecrypt) },
|
|
|
key,
|
|
|
- options
|
|
|
+ { iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }
|
|
|
)
|
|
|
|
|
|
- // 返回UTF-8解码的明文(去除首尾空格)
|
|
|
- return decryptedData.toString(CryptoJS.enc.Utf8).trim()
|
|
|
+ return decrypted.toString(CryptoJS.enc.Utf8).trim()
|
|
|
} catch (error) {
|
|
|
console.error('AES解密失败:', error)
|
|
|
return ''
|