|
|
|
@ -371,6 +371,26 @@ export function getHost() { |
|
|
|
return hostName; |
|
|
|
return hostName; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function safeUtf8(words) { |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
return CryptoJS.enc.Utf8.stringify(words) || '' |
|
|
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
|
|
return '' |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function normalizeCipherText(value) { |
|
|
|
|
|
|
|
let normalized = String(value ?? '').replace(/\s+/g, '').replace(/\r|\n/g, '') |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
if (/%[0-9A-Fa-f]{2}/.test(normalized)) { |
|
|
|
|
|
|
|
normalized = decodeURIComponent(normalized) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} catch (e) {} |
|
|
|
|
|
|
|
// URL-safe Base64
|
|
|
|
|
|
|
|
normalized = normalized.replace(/-/g, '+').replace(/_/g, '/') |
|
|
|
|
|
|
|
return normalized |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
export function Encrypt(Okey, Oiv, payload) { |
|
|
|
export function Encrypt(Okey, Oiv, payload) { |
|
|
|
const key = CryptoJS.enc.Utf8.parse(Okey); |
|
|
|
const key = CryptoJS.enc.Utf8.parse(Okey); |
|
|
|
const iv = CryptoJS.enc.Utf8.parse(Oiv); |
|
|
|
const iv = CryptoJS.enc.Utf8.parse(Oiv); |
|
|
|
@ -386,7 +406,7 @@ export function Decryption(Okey, Oiv, value) { |
|
|
|
if (typeof value !== 'string' && typeof value !== 'number') return '' |
|
|
|
if (typeof value !== 'string' && typeof value !== 'number') return '' |
|
|
|
const key = CryptoJS.enc.Utf8.parse(Okey); |
|
|
|
const key = CryptoJS.enc.Utf8.parse(Okey); |
|
|
|
const iv = CryptoJS.enc.Utf8.parse(Oiv); |
|
|
|
const iv = CryptoJS.enc.Utf8.parse(Oiv); |
|
|
|
const normalized = String(value).replace(/\s+/g, '') |
|
|
|
const normalized = normalizeCipherText(value) |
|
|
|
const options = { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 } |
|
|
|
const options = { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 } |
|
|
|
|
|
|
|
|
|
|
|
// 1) 历史 Hex 密文
|
|
|
|
// 1) 历史 Hex 密文
|
|
|
|
@ -396,38 +416,80 @@ export function Decryption(Okey, Oiv, value) { |
|
|
|
key, |
|
|
|
key, |
|
|
|
options, |
|
|
|
options, |
|
|
|
) |
|
|
|
) |
|
|
|
const hexText = CryptoJS.enc.Utf8.stringify(hexDecrypt) |
|
|
|
const hexText = safeUtf8(hexDecrypt) |
|
|
|
if (hexText) return hexText |
|
|
|
if (hexText) return hexText |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 2) 兼容原 OpenSSL/Base64 字符串解密(ASR 等存量逻辑)
|
|
|
|
// 2) 兼容原 OpenSSL/Base64 字符串解密(ASR 等存量逻辑)
|
|
|
|
const opensslDecrypt = CryptoJS.AES.decrypt(normalized, key, options) |
|
|
|
const opensslDecrypt = CryptoJS.AES.decrypt(normalized, key, options) |
|
|
|
const opensslText = CryptoJS.enc.Utf8.stringify(opensslDecrypt) |
|
|
|
const opensslText = safeUtf8(opensslDecrypt) |
|
|
|
if (opensslText) return opensslText |
|
|
|
if (opensslText) return opensslText |
|
|
|
|
|
|
|
|
|
|
|
// 3) 显式按裸 Base64 ciphertext 再试(与 Encrypt 输出对齐)
|
|
|
|
// 3) 显式按裸 Base64 ciphertext 再试(与 Encrypt 输出对齐)
|
|
|
|
const rawDecrypt = CryptoJS.AES.decrypt( |
|
|
|
try { |
|
|
|
{ ciphertext: CryptoJS.enc.Base64.parse(normalized) }, |
|
|
|
const rawDecrypt = CryptoJS.AES.decrypt( |
|
|
|
key, |
|
|
|
{ ciphertext: CryptoJS.enc.Base64.parse(normalized) }, |
|
|
|
options, |
|
|
|
key, |
|
|
|
) |
|
|
|
options, |
|
|
|
return CryptoJS.enc.Utf8.stringify(rawDecrypt) |
|
|
|
) |
|
|
|
|
|
|
|
return safeUtf8(rawDecrypt) |
|
|
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
|
|
return '' |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
export function decryptByVersionNo1(versionNo1Cipher, cipherText) { |
|
|
|
export function decryptByVersionNo1(versionNo1Cipher, cipherText) { |
|
|
|
if (!versionNo1Cipher || !cipherText) return '' |
|
|
|
if (!versionNo1Cipher || !cipherText) return '' |
|
|
|
|
|
|
|
const normalizedCipher = normalizeCipherText(cipherText) |
|
|
|
const year = new Date().getFullYear() |
|
|
|
const year = new Date().getFullYear() |
|
|
|
const versionNo1 = DecryptionECB(`${year}${year}${year}${year}`, versionNo1Cipher) |
|
|
|
// 兼容跨年:versionNo1 可能按加密当年的 year 生成
|
|
|
|
const key = versionNo1.substring(0, 16) |
|
|
|
const yearCandidates = [year, year - 1, year - 2, year + 1] |
|
|
|
const iv = versionNo1.substring(16, 32) |
|
|
|
|
|
|
|
if (key.length !== 16 || iv.length !== 16) return '' |
|
|
|
for (const y of yearCandidates) { |
|
|
|
return Decryption(key, iv, cipherText) |
|
|
|
const versionNo1 = DecryptionECB(`${y}${y}${y}${y}`, versionNo1Cipher) |
|
|
|
|
|
|
|
if (!versionNo1 || versionNo1.length < 32) continue |
|
|
|
|
|
|
|
const key = versionNo1.substring(0, 16) |
|
|
|
|
|
|
|
const iv = versionNo1.substring(16, 32) |
|
|
|
|
|
|
|
if (key.length !== 16 || iv.length !== 16) continue |
|
|
|
|
|
|
|
const plain = Decryption(key, iv, normalizedCipher) |
|
|
|
|
|
|
|
if (plain) return plain.replace(/^["']+|["']+$/g, '').trim() |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return '' |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
export function DecryptionECB(keyECB, valueECB) { |
|
|
|
export function DecryptionECB(keyECB, valueECB) { |
|
|
|
const key = CryptoJS.enc.Utf8.parse(keyECB); |
|
|
|
if (valueECB === undefined || valueECB === null || valueECB === '') return '' |
|
|
|
const decrypt = CryptoJS.AES.decrypt(valueECB, key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 }); |
|
|
|
const key = CryptoJS.enc.Utf8.parse(keyECB) |
|
|
|
return CryptoJS.enc.Utf8.stringify(decrypt); |
|
|
|
const normalized = normalizeCipherText(valueECB) |
|
|
|
|
|
|
|
const options = { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 1) Hex
|
|
|
|
|
|
|
|
if (/^[0-9A-Fa-f]+$/.test(normalized) && normalized.length % 32 === 0) { |
|
|
|
|
|
|
|
const hexDecrypt = CryptoJS.AES.decrypt( |
|
|
|
|
|
|
|
{ ciphertext: CryptoJS.enc.Hex.parse(normalized) }, |
|
|
|
|
|
|
|
key, |
|
|
|
|
|
|
|
options, |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
const hexText = safeUtf8(hexDecrypt) |
|
|
|
|
|
|
|
if (hexText) return hexText |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 2) OpenSSL/Base64 string
|
|
|
|
|
|
|
|
const opensslDecrypt = CryptoJS.AES.decrypt(normalized, key, options) |
|
|
|
|
|
|
|
const opensslText = safeUtf8(opensslDecrypt) |
|
|
|
|
|
|
|
if (opensslText) return opensslText |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 3) raw Base64 ciphertext
|
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
const rawDecrypt = CryptoJS.AES.decrypt( |
|
|
|
|
|
|
|
{ ciphertext: CryptoJS.enc.Base64.parse(normalized) }, |
|
|
|
|
|
|
|
key, |
|
|
|
|
|
|
|
options, |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
return safeUtf8(rawDecrypt) |
|
|
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
|
|
return '' |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
export function isSit() { |
|
|
|
export function isSit() { |
|
|
|
|