version: 20250815
This commit is contained in:
@@ -1,30 +1,103 @@
|
||||
import CryptoJS from 'crypto-js';
|
||||
import CryptoJS from 'crypto-js'; // 假设使用crypto-js库
|
||||
|
||||
const key = CryptoJS.enc.Utf8.parse(import.meta.env.VITE_APP_KEY);
|
||||
const iv = CryptoJS.enc.Utf8.parse(import.meta.env.VITE_APP_IV);
|
||||
// 密钥必须与加密时完全一致(建议从环境变量读取,避免硬编码)
|
||||
const SECRET_KEY = import.meta.env.VITE_APP_KEY || 'your-secret-key-32bytes'; // 32字节密钥(AES-256)
|
||||
const IV = import.meta.env.VITE_APP_IV || '16bytesIvValue!'; // 16字节IV
|
||||
|
||||
const crypto = {
|
||||
encrypt: (str) => {
|
||||
const encrypted = CryptoJS.AES.encrypt(str, key, {
|
||||
// 验证密钥和IV长度(关键修复)
|
||||
if (SECRET_KEY.length !== 32) {
|
||||
console.error(`加密密钥长度错误:需要32字节,实际${SECRET_KEY.length}字节`);
|
||||
}
|
||||
if (IV.length !== 16) {
|
||||
console.error(`IV长度错误:需要16字节,实际${IV.length}字节`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 加密函数
|
||||
* @param {string} data - 要加密的字符串(需确保是有效的UTF-8)
|
||||
* @returns {string} 加密后的Base64字符串
|
||||
*/
|
||||
export const encrypt = (data) => {
|
||||
try {
|
||||
// 确保输入是字符串,且是有效的UTF-8
|
||||
if (typeof data !== 'string') {
|
||||
throw new Error('加密数据必须是字符串');
|
||||
}
|
||||
|
||||
// 验证UTF-8有效性
|
||||
new TextDecoder().decode(new TextEncoder().encode(data));
|
||||
|
||||
const key = CryptoJS.enc.Utf8.parse(SECRET_KEY);
|
||||
const iv = CryptoJS.enc.Utf8.parse(IV);
|
||||
|
||||
const encrypted = CryptoJS.AES.encrypt(
|
||||
data,
|
||||
key,
|
||||
{
|
||||
iv: iv,
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
});
|
||||
// 将加密结果转换为字节数组,然后转换为十六进制字符串
|
||||
const hexString = CryptoJS.enc.Hex.stringify(encrypted.ciphertext);
|
||||
return hexString;
|
||||
},
|
||||
decrypt: (hexString) => {
|
||||
// 将十六进制字符串转换回字节数组
|
||||
const ciphertext = CryptoJS.enc.Hex.parse(hexString);
|
||||
const encryptedParams = CryptoJS.lib.CipherParams.create({ ciphertext });
|
||||
const decrypted = CryptoJS.AES.decrypt(encryptedParams, key, {
|
||||
iv: iv,
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
});
|
||||
return decrypted.toString(CryptoJS.enc.Utf8);
|
||||
}
|
||||
);
|
||||
|
||||
// 返回Base64格式的密文(避免特殊字符问题)
|
||||
return encrypted.ciphertext.toString(CryptoJS.enc.Base64);
|
||||
} catch (error) {
|
||||
console.error('加密失败:', error);
|
||||
throw new Error(`加密错误: ${error.message}`);
|
||||
}
|
||||
};
|
||||
|
||||
export default crypto;
|
||||
/**
|
||||
* 解密函数
|
||||
* @param {string} encryptedData - 加密后的Base64字符串
|
||||
* @returns {string} 解密后的UTF-8字符串
|
||||
*/
|
||||
export const decrypt = (encryptedData) => {
|
||||
try {
|
||||
// 验证输入是否为字符串
|
||||
if (typeof encryptedData !== 'string' || encryptedData.trim() === '') {
|
||||
throw new Error('解密数据必须是非空字符串');
|
||||
}
|
||||
|
||||
// 验证Base64有效性(关键修复)
|
||||
if (!/^[A-Za-z0-9+/=]+$/.test(encryptedData)) {
|
||||
throw new Error('解密数据不是有效的Base64格式');
|
||||
}
|
||||
|
||||
const key = CryptoJS.enc.Utf8.parse(SECRET_KEY);
|
||||
const iv = CryptoJS.enc.Utf8.parse(IV);
|
||||
|
||||
// 先将Base64转换为CipherParams对象
|
||||
const cipherParams = CryptoJS.lib.CipherParams.create({
|
||||
ciphertext: CryptoJS.enc.Base64.parse(encryptedData)
|
||||
});
|
||||
|
||||
const decrypted = CryptoJS.AES.decrypt(
|
||||
cipherParams,
|
||||
key,
|
||||
{
|
||||
iv: iv,
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
}
|
||||
);
|
||||
|
||||
// 转换为UTF-8字符串(处理可能的编码错误)
|
||||
const result = decrypted.toString(CryptoJS.enc.Utf8);
|
||||
|
||||
if (!result) {
|
||||
throw new Error('解密结果为空,可能是密钥不匹配或数据损坏');
|
||||
}
|
||||
|
||||
// 再次验证UTF-8有效性
|
||||
new TextDecoder().decode(new TextEncoder().encode(result));
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error('解密失败:', error);
|
||||
throw new Error(`解密错误: ${error.message}`);
|
||||
}
|
||||
};
|
||||
|
||||
export default { encrypt, decrypt };
|
||||
|
||||
Reference in New Issue
Block a user