encrypt.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. import CryptoJS from "crypto-js";
  2. const key = "49PBou+TREIOzSHj";
  3. const key1 = CryptoJS.enc.Utf8.parse("dmngJmmO+9GMw+tu");
  4. const iv1 = CryptoJS.enc.Utf8.parse("sanXyqhk8+U7LPP4");
  5. const key2 = CryptoJS.enc.Utf8.parse(key);
  6. const iv2 = CryptoJS.enc.Utf8.parse("5lDsNRe&UduJ97uS");
  7. // 固定IV 用于密码、get请求参数加密
  8. const defaultIv = CryptoJS.enc.Utf8.parse("5lDsNRe&UduJ97uS");
  9. // 密钥派生参数配置
  10. const PBKDF2_CONFIG = {
  11. // 盐值长度(bits)
  12. saltSize: 128,
  13. // 迭代次数
  14. iterations: 10000,
  15. // 密钥长度(256bit)
  16. keySize: 128 / 32,
  17. hashAlgorithm: CryptoJS.algo.SHA256,
  18. };
  19. const deriveDynamicKey = (token, salt) => {
  20. if (!token || typeof token !== "string") {
  21. throw new Error("Invalid user token");
  22. }
  23. return CryptoJS.PBKDF2(token, salt, {
  24. keySize: PBKDF2_CONFIG.keySize,
  25. iterations: PBKDF2_CONFIG.iterations,
  26. hasher: PBKDF2_CONFIG.hashAlgorithm,
  27. });
  28. };
  29. export const generateDynamicIV = () => {
  30. // 1. 获取当前时间戳(8字节,64位)
  31. const timestamp = Date.now();
  32. // 将时间戳转换为8字节的WordArray(大端序)
  33. const timestampBytes = CryptoJS.enc.Hex.parse(
  34. timestamp.toString(16).padStart(16, "0")
  35. );
  36. // 2. 生成8字节随机数
  37. const randomBytes = CryptoJS.lib.WordArray.random(8);
  38. // 3. 构造IV(16字节)y
  39. const ivWords = [
  40. // 前4字节:随机数的高4字节
  41. randomBytes.words[0],
  42. // 接下来4字节:时间戳的高4字节
  43. timestampBytes.words[0],
  44. // 接下来4字节:随机数的低4字节
  45. randomBytes.words[1],
  46. // 最后4字节:时间戳的低4字节
  47. timestampBytes.words[1],
  48. ];
  49. return CryptoJS.lib.WordArray.create(ivWords, 16);
  50. };
  51. const xorEncrypt = (text) => {
  52. let encrypted = "";
  53. for (let i = 0; i < text.length; i++) {
  54. const charCode = text.charCodeAt(i) ^ key.charCodeAt(i % key.length);
  55. encrypted += String.fromCharCode(charCode);
  56. }
  57. return btoa(encrypted);
  58. };
  59. const xorDecrypt = (encryptedBase64) => {
  60. // 从Base64解码
  61. const decodedStr = atob(encryptedBase64);
  62. let decrypted = "";
  63. // 异或解密
  64. for (let i = 0; i < decodedStr.length; i++) {
  65. const charCode =
  66. decodedStr.charCodeAt(i) ^ key.charCodeAt(i % key.length);
  67. decrypted += String.fromCharCode(charCode);
  68. }
  69. return decrypted;
  70. };
  71. // AES加密
  72. export const encryptByAes = (params, type = "dynamic", token) => {
  73. try {
  74. const isDynamic = type === "dynamic";
  75. // 生成随机盐值
  76. const salt = CryptoJS.lib.WordArray.random(PBKDF2_CONFIG.saltSize);
  77. // 动态派生密钥
  78. const derivedKey = isDynamic ? deriveDynamicKey(token, salt) : key2;
  79. // 生成动态iv
  80. const iv = isDynamic ? generateDynamicIV() : defaultIv;
  81. const data =
  82. typeof params === "string" ? params : JSON.stringify(params);
  83. const srcs = CryptoJS.enc.Utf8.parse(data);
  84. const encrypted = CryptoJS.AES.encrypt(srcs, derivedKey, {
  85. iv: iv,
  86. mode: CryptoJS.mode.CBC,
  87. padding: CryptoJS.pad.Pkcs7,
  88. });
  89. if (isDynamic) {
  90. const str =
  91. encrypted.ciphertext.toString(CryptoJS.enc.Base64) +
  92. "|" +
  93. iv.toString(CryptoJS.enc.Base64) +
  94. "|" +
  95. salt.toString(CryptoJS.enc.Base64) +
  96. "|" +
  97. token;
  98. return xorEncrypt(str);
  99. }
  100. return encrypted.ciphertext.toString(CryptoJS.enc.Base64);
  101. } catch (error) {
  102. console.error("Encryption error:", error);
  103. throw new Error("Encryption failed");
  104. }
  105. };
  106. const isValidBase64 = (str) => {
  107. try {
  108. return btoa(atob(str)) === str;
  109. } catch (e) {
  110. return false;
  111. }
  112. };
  113. export const decryptByAes = (ciphertext) => {
  114. try {
  115. // 初始化解密参数
  116. let cipherToDecrypt = ciphertext;
  117. let iv = defaultIv;
  118. let key = key2;
  119. // 尝试XOR解密并解析参数
  120. const decryptedStr = xorDecrypt(ciphertext);
  121. const parts = decryptedStr.split("|");
  122. if (parts.length === 4) {
  123. const [ciphertextBase64, ivBase64, saltBase64, token] = parts;
  124. if (
  125. token &&
  126. !(isValidBase64(ivBase64) && isValidBase64(saltBase64))
  127. ) {
  128. console.error("解密失败: 无效的IV参数或salt参数!");
  129. return "";
  130. }
  131. // 转换编码
  132. iv = CryptoJS.enc.Base64.parse(ivBase64);
  133. const salt = CryptoJS.enc.Base64.parse(saltBase64);
  134. // 动态派生密钥
  135. key = deriveDynamicKey(token, salt);
  136. cipherToDecrypt = ciphertextBase64;
  137. }
  138. // 解密
  139. const decrypted = CryptoJS.AES.decrypt(
  140. { ciphertext: CryptoJS.enc.Base64.parse(cipherToDecrypt) },
  141. key,
  142. { iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }
  143. );
  144. return decrypted.toString(CryptoJS.enc.Utf8).trim();
  145. } catch (error) {
  146. console.error("AES解密失败:", error);
  147. return "";
  148. }
  149. };