aes.ts文件
javascript
import CryptoJS from "crypto-js";
import axios from "axios";
export const encrypt = async(data: any) => {
let storeKey = sessionStorage.getItem('a')
let storeIv:any = sessionStorage.getItem('i')
// 如果秘钥或 IV 不存在,尝试获取秘钥
if (!storeKey || !storeIv) {
await fetchSecretKey(); // 确保秘钥已被获取
storeKey = sessionStorage.getItem('a'); // 再次获取秘钥
storeIv = sessionStorage.getItem('i'); // 再次获取 IV
}
if (!storeKey || !storeIv) {
throw new Error("秘钥或 IV 不存在.");
}
let secretKey = storeKey.replace('FiedGSe5fg6', '').replace('F//Eset5fGDet', '')
let key = CryptoJS.enc.Base64.parse(secretKey);
let replaceIv = storeIv.replace('DGers', '').replace('HrdReK', '')
let iv = CryptoJS.enc.Utf8.parse(replaceIv)
let srcs = CryptoJS.enc.Utf8.parse(JSON.stringify(data));
let encrypted = CryptoJS.AES.encrypt(srcs, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7,
});
return encrypted.toString();
};
export const decrypt = async(cipherText: any) => {
let storeKey = sessionStorage.getItem('a')
let storeIv:any = sessionStorage.getItem('i')
// 如果秘钥或 IV 不存在,尝试获取秘钥
if (!storeKey || !storeIv) {
await fetchSecretKey(); // 确保秘钥已被获取
storeKey = sessionStorage.getItem('a'); // 再次获取秘钥
storeIv = sessionStorage.getItem('i'); // 再次获取 IV
}
if (!storeKey || !storeIv) {
throw new Error("秘钥或 IV 不存在.");
}
let secretKey = storeKey.replace('FiedGSe5fg6', '').replace('F//Eset5fGDet', '')
let key = CryptoJS.enc.Base64.parse(secretKey);
let replaceIv = storeIv.replace('DGers', '').replace('HrdReK', '')
let iv = CryptoJS.enc.Utf8.parse(replaceIv)
const decrypted = CryptoJS.AES.decrypt(cipherText, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7,
});
return decrypted.toString(CryptoJS.enc.Utf8);
};
// 获取秘钥并存储在会话缓存中
export const fetchSecretKey = async () => {
// 检查会话缓存中是否已经有秘钥
const cachedKey = sessionStorage.getItem('a');
if (cachedKey) {
return;
}
try {
// 获取当前时间戳
const timestamp = Date.now();
const nonce = generateNonce(); // 生成随机 nonce
// 临时使用一个默认的签名密钥,可以替换为你后端使用的密钥
const tempSecret = 'defaultSecretKey';
const signature = generateSignature(tempSecret, timestamp, nonce); // 生成签名
// 发送请求获取秘钥,带上签名
const response = await axios.post('/api_getKey', {
timestamp,
nonce,
signature,
});
const rawKey = response.data.aesKey;
// 存储到会话缓存中
sessionStorage.setItem('a', rawKey);
sessionStorage.setItem('i', response.data.iv);
} catch (error) {
console.error('Error fetching secret key:', error);
}
};
// 初始化函数,只有第一次项目打开时才执行获取秘钥的逻辑
export const initializeSecretKey = async () => {
const secretKey = sessionStorage.getItem('a')
if (!secretKey) {
await fetchSecretKey(); // 调用获取秘钥的函数
}
};
// 生成随机字符串作为 nonce
const generateNonce = (): string => {
return Math.random().toString(36).substr(2, 15);
};
// 生成签名
const generateSignature = (secretKey: string, timestamp: number, nonce: string): string => {
const message = `${secretKey}${timestamp}${nonce}`;
return CryptoJS.SHA256(message).toString();
};
后端
php
// 获取加密密钥的 API 接口
public function getKey()
{
// 获取请求参数
$timestamp = Request::post('timestamp');
$nonce = Request::post('nonce');
$signature = Request::post('signature');
// 验证签名
if (!$this->verifySignature($timestamp, $nonce, $signature)) {
return json(['error' => '无效签名或请求已过期'], 403);
}
// 签名验证通过后,返回密钥(或其他敏感信息)
// AES密钥
$secretKey = '秘钥';
// 1Ww;w(czeHDyFN@T DGers HrdReK
$iv = '向量';
return json(['aesKey' => $secretKey,'iv' => $iv]);
}
// 签名验证
private function verifySignature($timestamp, $nonce, $signature)
{
// 检查时间戳是否在合理范围内(例如5分钟内)
$now = time() * 1000; // 转换为毫秒
if (abs($now - $timestamp) > 5 * 60 * 1000) {
return false; // 请求超时
}
// 重新生成签名
$dataToSign = 'defaultSecretKey' . $timestamp . $nonce;
$serverSignature = hash('sha256', $dataToSign);
// 比较客户端的签名与服务器生成的签名是否一致
if ($serverSignature !== $signature) {
return false; // 签名不匹配
}
// 如果签名正确,返回 true
return true;
}