| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- import GameConfigModel from "../store/models/gameConfig.model";
- import { generateRandomIV, sortObj } from "./helper";
- import md5 from 'md5';
- import CryptoJS from 'crypto-js';
- /**
- * 生成签名
- * @param params
- * @returns
- */
- export const generateSign = (params: {
- time: number;
- [key: string]: any;
- }) => {
- const gemeConfig = GameConfigModel.getInstance().get()
- params.time = Math.floor(new Date().getTime() / 1000);
- let newData = sortObj(params);
- let signStr = "";
- for (let k in newData) {
- if (k === "sign") {
- continue;
- }
- if (newData[k] === "") {
- continue;
- }
- if (newData[k] === undefined) {
- continue;
- }
- if (newData[k] === null) {
- continue;
- }
- signStr = signStr + k + "=" + newData[k] + "&";
- }
- signStr =
- signStr.substring(0, signStr.length - 1) +
- "&secret=" +
- gemeConfig.mini_program_id;
- // console.log("加密原串:" + signStr);
- params.sign = md5(signStr);
- let newParams: any = {}
- newParams.encrypt_data = encryptData(params);
- return newParams;
- }
- /**
- * 加密数据
- * @param params
- * @returns
- */
- export const encryptData = (params: any) => {
- console.log('加密前',params)
- const key = import.meta.env.SDK_VITE_KEY;
- // 将参数对象转换为 JSON 字符串
- const data = JSON.stringify(params);
- // 生成 16 字节的随机 IV (AES-256-CBC 需要 16 字节 IV)
- const iv = generateRandomIV(16);
- // 将密钥转换为 WordArray
- // AES-256 需要 32 字节 (256 位) 的密钥
- // 如果 key 长度不够,使用 MD5 哈希来生成 32 字节的密钥
- let keyWordArray;
-
- if (key.length === 32) {
- // 如果 key 正好是 32 字节,直接使用 UTF8 解析
- keyWordArray = CryptoJS.enc.Utf8.parse(key);
- } else {
- // 否则使用 MD5 哈希生成 32 字节的密钥(MD5 生成 16 字节,但 crypto-js 会处理)
- // 对于 AES-256,我们需要 32 字节,可以使用 SHA256 或者重复 MD5
- keyWordArray = CryptoJS.SHA256(key);
- }
- // 使用 AES-256-CBC 加密,返回原始二进制数据
- const encrypted = CryptoJS.AES.encrypt(data, keyWordArray, {
- iv: iv,
- mode: CryptoJS.mode.CBC,
- padding: CryptoJS.pad.Pkcs7
- });
- // 将 IV 和密文拼接(都是 WordArray,直接拼接)
- // PHP 中:$iv . $encrypted (直接拼接二进制数据)
- const combined = iv.concat(encrypted.ciphertext);
- // 将拼接后的数据转换为 Base64 编码
- // PHP 中:base64_encode($iv . $encrypted)
- const base64Encoded = CryptoJS.enc.Base64.stringify(combined);
- // 返回加密后的数据,将原始参数替换为加密数据
- return base64Encoded;
- }
- /**
- * 解密数据
- * @param encryptedData
- * @returns
- */
- export const decryptData = (encryptedData: string) => {
- const key = import.meta.env.SDK_VITE_KEY;
- try {
- // 如果数据为空或无效,直接返回
- if (!encryptedData || typeof encryptedData !== 'string') {
- return encryptedData;
- }
- // Base64 解码
- const combined = CryptoJS.enc.Base64.parse(encryptedData);
- // 提取前 16 字节作为 IV(AES-256-CBC 需要 16 字节 IV)
- const iv = CryptoJS.lib.WordArray.create(combined.words.slice(0, 4), 16);
- // 提取剩余部分作为密文
- const ciphertext = CryptoJS.lib.WordArray.create(combined.words.slice(4), combined.sigBytes - 16);
- // 将密钥转换为 WordArray(与加密方法保持一致)
- let keyWordArray;
- if (key && key.length === 32) {
- // 如果 key 正好是 32 字节,直接使用 UTF8 解析
- keyWordArray = CryptoJS.enc.Utf8.parse(key);
- } else if (key) {
- // 否则使用 SHA256 哈希生成 32 字节的密钥
- keyWordArray = CryptoJS.SHA256(key);
- } else {
- throw new Error('解密密钥不能为空');
- }
- // 创建 CipherParams 对象用于解密
- const cipherParams = CryptoJS.lib.CipherParams.create({
- ciphertext: ciphertext
- });
- // 使用 AES-256-CBC 解密
- const decrypted = CryptoJS.AES.decrypt(cipherParams, keyWordArray, {
- iv: iv,
- mode: CryptoJS.mode.CBC,
- padding: CryptoJS.pad.Pkcs7
- });
- // 将解密后的数据转换为 UTF8 字符串
- const decryptedStr = decrypted.toString(CryptoJS.enc.Utf8);
- console.log("解密后的数据:", JSON.parse(decryptedStr));
- // 解析 JSON 字符串并返回对象
- return JSON.parse(decryptedStr);
- } catch (error) {
- console.error('解密失败:', error);
- // 如果解密失败,返回原始数据
- return encryptedData;
- }
- }
|