104 lines
3.1 KiB
JavaScript
104 lines
3.1 KiB
JavaScript
import CryptoJS from 'crypto-js'; // 假设使用crypto-js库
|
||
|
||
// 密钥必须与加密时完全一致(建议从环境变量读取,避免硬编码)
|
||
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
|
||
|
||
// 验证密钥和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
|
||
}
|
||
);
|
||
|
||
// 返回Base64格式的密文(避免特殊字符问题)
|
||
return encrypted.ciphertext.toString(CryptoJS.enc.Base64);
|
||
} catch (error) {
|
||
console.error('加密失败:', error);
|
||
throw new Error(`加密错误: ${error.message}`);
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 解密函数
|
||
* @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 };
|