encrypted.ts 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. import GameConfigModel from "../store/models/gameConfig.model";
  2. import { generateRandomIV, sortObj } from "./helper";
  3. import md5 from 'md5';
  4. import CryptoJS from 'crypto-js';
  5. /**
  6. * 生成签名
  7. * @param params
  8. * @returns
  9. */
  10. export const generateSign = (params: {
  11. time: number;
  12. [key: string]: any;
  13. }) => {
  14. const gemeConfig = GameConfigModel.getInstance().get()
  15. params.time = Math.floor(new Date().getTime() / 1000);
  16. let newData = sortObj(params);
  17. let signStr = "";
  18. for (let k in newData) {
  19. if (k === "sign") {
  20. continue;
  21. }
  22. if (newData[k] === "") {
  23. continue;
  24. }
  25. if (newData[k] === undefined) {
  26. continue;
  27. }
  28. if (newData[k] === null) {
  29. continue;
  30. }
  31. signStr = signStr + k + "=" + newData[k] + "&";
  32. }
  33. signStr =
  34. signStr.substring(0, signStr.length - 1) +
  35. "&secret=" +
  36. gemeConfig.mini_program_id;
  37. // console.log("加密原串:" + signStr);
  38. params.sign = md5(signStr);
  39. let newParams: any = {}
  40. newParams.encrypt_data = encryptData(params);
  41. return newParams;
  42. }
  43. /**
  44. * 加密数据
  45. * @param params
  46. * @returns
  47. */
  48. export const encryptData = (params: any) => {
  49. console.log('加密前',params)
  50. const key = import.meta.env.SDK_VITE_KEY;
  51. // 将参数对象转换为 JSON 字符串
  52. const data = JSON.stringify(params);
  53. // 生成 16 字节的随机 IV (AES-256-CBC 需要 16 字节 IV)
  54. const iv = generateRandomIV(16);
  55. // 将密钥转换为 WordArray
  56. // AES-256 需要 32 字节 (256 位) 的密钥
  57. // 如果 key 长度不够,使用 MD5 哈希来生成 32 字节的密钥
  58. let keyWordArray;
  59. if (key.length === 32) {
  60. // 如果 key 正好是 32 字节,直接使用 UTF8 解析
  61. keyWordArray = CryptoJS.enc.Utf8.parse(key);
  62. } else {
  63. // 否则使用 MD5 哈希生成 32 字节的密钥(MD5 生成 16 字节,但 crypto-js 会处理)
  64. // 对于 AES-256,我们需要 32 字节,可以使用 SHA256 或者重复 MD5
  65. keyWordArray = CryptoJS.SHA256(key);
  66. }
  67. // 使用 AES-256-CBC 加密,返回原始二进制数据
  68. const encrypted = CryptoJS.AES.encrypt(data, keyWordArray, {
  69. iv: iv,
  70. mode: CryptoJS.mode.CBC,
  71. padding: CryptoJS.pad.Pkcs7
  72. });
  73. // 将 IV 和密文拼接(都是 WordArray,直接拼接)
  74. // PHP 中:$iv . $encrypted (直接拼接二进制数据)
  75. const combined = iv.concat(encrypted.ciphertext);
  76. // 将拼接后的数据转换为 Base64 编码
  77. // PHP 中:base64_encode($iv . $encrypted)
  78. const base64Encoded = CryptoJS.enc.Base64.stringify(combined);
  79. // 返回加密后的数据,将原始参数替换为加密数据
  80. return base64Encoded;
  81. }
  82. /**
  83. * 解密数据
  84. * @param encryptedData
  85. * @returns
  86. */
  87. export const decryptData = (encryptedData: string) => {
  88. const key = import.meta.env.SDK_VITE_KEY;
  89. try {
  90. // 如果数据为空或无效,直接返回
  91. if (!encryptedData || typeof encryptedData !== 'string') {
  92. return encryptedData;
  93. }
  94. // Base64 解码
  95. const combined = CryptoJS.enc.Base64.parse(encryptedData);
  96. // 提取前 16 字节作为 IV(AES-256-CBC 需要 16 字节 IV)
  97. const iv = CryptoJS.lib.WordArray.create(combined.words.slice(0, 4), 16);
  98. // 提取剩余部分作为密文
  99. const ciphertext = CryptoJS.lib.WordArray.create(combined.words.slice(4), combined.sigBytes - 16);
  100. // 将密钥转换为 WordArray(与加密方法保持一致)
  101. let keyWordArray;
  102. if (key && key.length === 32) {
  103. // 如果 key 正好是 32 字节,直接使用 UTF8 解析
  104. keyWordArray = CryptoJS.enc.Utf8.parse(key);
  105. } else if (key) {
  106. // 否则使用 SHA256 哈希生成 32 字节的密钥
  107. keyWordArray = CryptoJS.SHA256(key);
  108. } else {
  109. throw new Error('解密密钥不能为空');
  110. }
  111. // 创建 CipherParams 对象用于解密
  112. const cipherParams = CryptoJS.lib.CipherParams.create({
  113. ciphertext: ciphertext
  114. });
  115. // 使用 AES-256-CBC 解密
  116. const decrypted = CryptoJS.AES.decrypt(cipherParams, keyWordArray, {
  117. iv: iv,
  118. mode: CryptoJS.mode.CBC,
  119. padding: CryptoJS.pad.Pkcs7
  120. });
  121. // 将解密后的数据转换为 UTF8 字符串
  122. const decryptedStr = decrypted.toString(CryptoJS.enc.Utf8);
  123. console.log("解密后的数据:", JSON.parse(decryptedStr));
  124. // 解析 JSON 字符串并返回对象
  125. return JSON.parse(decryptedStr);
  126. } catch (error) {
  127. console.error('解密失败:', error);
  128. // 如果解密失败,返回原始数据
  129. return encryptedData;
  130. }
  131. }