Files
ReisaAdmin/reijm-read/src/utils/encryptionUtil.js
2025-09-30 12:54:29 +08:00

122 lines
4.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import CryptoJS from 'crypto-js';
import pako from 'pako';
const key2 = CryptoJS.enc.Utf8.parse(',Lscj312.;[]sc`1dsajcjc;;wislacx'); // 32字节的密钥
const iv2 = CryptoJS.enc.Utf8.parse(',>ew:[7890;,wd[2'); // 16字节的IV
// 新增PKCS5Padding移除函数更健壮
function removePadding(data) {
if (data.length === 0) return data;
const paddingLength = data[data.length - 1];
if (data.length < paddingLength) {
console.warn("Padding length greater than data length");
return data;
}
return data.slice(0, data.length - paddingLength);
}
// 辅助函数打印ArrayBuffer内容调试用
function arrayBufferToString(buffer) {
return [...new Uint8Array(buffer)].map(b => b.toString(16).padStart(2, '0')).join(' ');
}
export default {
methods: {
encryptAndCompress(data) {
try {
// 压缩数据
const dataArray = new TextEncoder().encode(data);
const compressed = pako.gzip(dataArray);
// 加密数据
const wordArray = CryptoJS.lib.WordArray.create(compressed);
const encrypted = CryptoJS.AES.encrypt(wordArray, key2, {
iv: iv2,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
return encrypted.toString();
} catch (error) {
console.error("Encryption error:", error);
throw error;
}
},
decompressAndDecrypt(encryptedData, key = key2, iv = iv2) {
try {
if (!encryptedData || encryptedData.length < 16) {
throw new Error("Invalid or empty encrypted data");
}
// 确保 Base64 格式正确
const properB64Str = encryptedData.trim().replace(/\s+/g, '');
if (!/^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)?$/.test(properB64Str)) {
throw new Error("Invalid Base64 string");
}
// 解密数据
const cipherParams = CryptoJS.lib.CipherParams.create({ ciphertext: CryptoJS.enc.Base64.parse(properB64Str) });
const decrypted = CryptoJS.AES.decrypt(cipherParams, key, {
iv: iv,
padding: CryptoJS.pad.Pkcs7
});
if (!decrypted || !decrypted.words) {
throw new Error("Decryption failed or returned invalid data");
}
function wordArrayToUint8Array(wordArray) {
const byteArray = [];
const words = wordArray.words;
const sigBytes = wordArray.sigBytes;
for (let i = 0; i < sigBytes; i++) {
byteArray.push((words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff);
}
return new Uint8Array(byteArray);
}
const compressedArray = wordArrayToUint8Array(decrypted);
const debugHex = [...compressedArray.slice(0, 32)].map(b => b.toString(16).padStart(2, '0')).join(' ');
// 移除PKCS7 Padding
const decryptedWithoutPadding = removePadding(compressedArray);
// 手动验证是否是合法的GZIP格式
if (decryptedWithoutPadding.length < 10 ||
(decryptedWithoutPadding[0] !== 0x1f || decryptedWithoutPadding[1] !== 0x8b)) {
// 调试输出前32字节
const debugHexPostPadding = [...decryptedWithoutPadding.slice(0, 32)].map(b => b.toString(16).padStart(2, '0')).join('');
return '';
}
// 解压数据
let decompressed;
try {
decompressed = pako.ungzip(decryptedWithoutPadding);
} catch (e) {
console.error("GZIP decompression failed", e);
throw new Error("Failed to decompress data - invalid gzip format");
}
if (!decompressed || decompressed.length === 0) {
throw new Error("Empty decompressed data");
}
// 解压成功,返回解压后的文本数据
return new TextDecoder().decode(decompressed);
} catch (error) {
console.error("Decryption error:", error);
throw error;
}
},
// 移除PKCS7 Padding的函数
removePadding(byteArray) {
// 假设是PKCS7 padding最后一个字节的值即为填充的字节数
const paddingLength = byteArray[byteArray.length - 1];
return byteArray.slice(0, byteArray.length - paddingLength);
}
}
};