encrypt.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. import CryptoJS from 'crypto-js'
  2. const key = '49PBou+TREIOzSHj'
  3. const key1 = CryptoJS.enc.Utf8.parse('dmngJmmO+9GMw+tu')
  4. const key2 = CryptoJS.enc.Utf8.parse(key)
  5. // 固定IV 用于密码、get请求参数加密
  6. const defaultIv = CryptoJS.enc.Utf8.parse('5lDsNRe&UduJ97uS')
  7. // 密钥派生参数配置
  8. const PBKDF2_CONFIG = {
  9. // 盐值长度(bits)
  10. saltSize: 128,
  11. // 迭代次数
  12. iterations: 10000,
  13. // 密钥长度(256bit)
  14. keySize: 256 / 32,
  15. hashAlgorithm: CryptoJS.algo.SHA256
  16. }
  17. // 动态密钥派生器
  18. const deriveDynamicKey = (token, salt) => {
  19. if (!token || typeof token !== 'string') {
  20. throw new Error('Invalid user token')
  21. }
  22. return CryptoJS.PBKDF2(token, salt, {
  23. keySize: PBKDF2_CONFIG.keySize,
  24. iterations: PBKDF2_CONFIG.iterations,
  25. hasher: PBKDF2_CONFIG.hashAlgorithm
  26. })
  27. }
  28. // 动态IV生成器
  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字节)
  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 = decodedStr.charCodeAt(i) ^ key.charCodeAt(i % key.length)
  66. decrypted += String.fromCharCode(charCode)
  67. }
  68. return decrypted
  69. }
  70. // AES加密
  71. export const encryptByAes = (params, type = 'dynamic', token) => {
  72. try {
  73. const isDynamic = type === 'dynamic'
  74. // 生成随机盐值
  75. const salt = CryptoJS.lib.WordArray.random(PBKDF2_CONFIG.saltSize)
  76. // 动态派生密钥
  77. const derivedKey = isDynamic ? deriveDynamicKey(token, salt) : key2
  78. // 生成动态iv
  79. const iv = isDynamic ? generateDynamicIV() : defaultIv
  80. const data = typeof params === 'string' ? params : JSON.stringify(params)
  81. const srcs = CryptoJS.enc.Utf8.parse(data)
  82. const encrypted = CryptoJS.AES.encrypt(srcs, derivedKey, {
  83. iv: iv,
  84. mode: CryptoJS.mode.CBC,
  85. padding: CryptoJS.pad.Pkcs7
  86. })
  87. if (isDynamic) {
  88. const str = encrypted.ciphertext.toString(CryptoJS.enc.Base64) + '|' + iv.toString(CryptoJS.enc.Base64) + '|' + salt.toString(CryptoJS.enc.Base64) + '|' + token
  89. return xorEncrypt(str)
  90. }
  91. return encrypted.ciphertext.toString(CryptoJS.enc.Base64)
  92. } catch (error) {
  93. console.error('Encryption error:', error)
  94. throw new Error('Encryption failed')
  95. }
  96. }
  97. const isValidBase64 = (str) => {
  98. try {
  99. return btoa(atob(str)) === str
  100. } catch (e) {
  101. return false
  102. }
  103. }
  104. export const decryptByAes = (ciphertext) => {
  105. try {
  106. // 初始化解密参数
  107. let cipherToDecrypt = ciphertext
  108. let iv = defaultIv
  109. let key = key2
  110. // 尝试XOR解密并解析参数
  111. const decryptedStr = xorDecrypt(ciphertext)
  112. const parts = decryptedStr.split('|')
  113. if (parts.length === 4) {
  114. const [ciphertextBase64, ivBase64, saltBase64, token] = parts
  115. if (token && !(isValidBase64(ivBase64) && isValidBase64(saltBase64))) {
  116. console.error('解密失败: 无效的IV参数或salt参数!')
  117. return ''
  118. }
  119. // 转换编码
  120. iv = CryptoJS.enc.Base64.parse(ivBase64)
  121. const salt = CryptoJS.enc.Base64.parse(saltBase64)
  122. // 动态派生密钥
  123. key = deriveDynamicKey(token, salt)
  124. cipherToDecrypt = ciphertextBase64
  125. }
  126. // 解密
  127. const decrypted = CryptoJS.AES.decrypt({
  128. ciphertext: CryptoJS.enc.Base64.parse(cipherToDecrypt)
  129. },
  130. key, {
  131. iv,
  132. mode: CryptoJS.mode.CBC,
  133. padding: CryptoJS.pad.Pkcs7
  134. }
  135. )
  136. return decrypted.toString(CryptoJS.enc.Utf8).trim()
  137. } catch (error) {
  138. console.error('AES解密失败:', error)
  139. return ''
  140. }
  141. }