(function() { //by LoyDgIk const jvString = java.lang.String; const jvArray = java.lang.reflect.Array; const Byte = java.lang.Byte; const Integer = java.lang.Integer; const StandardCharsets = java.nio.charset.StandardCharsets; const MessageDigest = java.security.MessageDigest; const Base64 = android.util.Base64; const StringBuffer = java.lang.StringBuffer; const Cipher = javax.crypto.Cipher; const IvParameterSpec = javax.crypto.spec.IvParameterSpec; const SecretKeySpec = javax.crypto.spec.SecretKeySpec; const FileUtil = com.example.hikerview.utils.FileUtil; //CryptoUtil //互转类 function Data(bytes) { this.bytes = bytes; this.length = bytes.length; } Object.assign(Data, { parseStr(str, charset) { return new Data(toJvString(str).getBytes(charset)); }, parseUTF8(str) { return Data.parseStr(str, StandardCharsets.UTF_8); }, parseUTF16(str) { return Data.parseStr(str, StandardCharsets.UTF_16); }, parseHex(str) { return new Data(hexDecodeToByteArray(str)); }, parseBase64(str, flags) { return new Data(base64DecodeToByteArray(str, flags)); }, parseLatin1(str) { return Data.parseStr(str, StandardCharsets.ISO_8859_1); }, parseUTF16LE(str) { return Data.parseStr(str, StandardCharsets.UTF_16LE); }, parseInputStream(stream) { return new Data(FileUtil.toBytes(stream)); } }); Object.assign(Data.prototype, { toHex() { return bytesToHex(this.bytes); }, toBytes() { return this.bytes; }, toString(charset) { return bytesToString(this.bytes, charset); }, toLatin1() { return this.toString(StandardCharsets.ISO_8859_1); }, toUTF16LE() { return this.toString(StandardCharsets.UTF_16LE); }, toUTF16() { return this.toString(StandardCharsets.UTF_16); }, toBase64(flags) { return String(Base64.encodeToString(this.bytes, flags || Base64.DEFAULT)); }, toDigest() { return new Digest(this); }, toInputStream() { return FileUtil.toInputStream(this.bytes); } }); //摘要类 function Digest(data) { this.data = data; } Digest.digest = function(data, algorithm) { try { let md = MessageDigest.getInstance(algorithm); md.update(data.toBytes()); let hashInBytes = md.digest(); return String(bytesToHex(hashInBytes)); } catch (e) { throw (e); } } Object.assign(Digest.prototype, { md5() { return Digest.digest(this.data, "MD5"); }, sha256() { return Digest.digest(this.data, "SHA-256"); }, md2() { return Digest.digest(this.data, "MD2"); }, sha1() { return Digest.digest(this.data, "SHA-1"); }, sha512() { return Digest.digest(this.data, "SHA-512"); }, sha384() { return Digest.digest(this.data, "SHA-384"); } }); function process(operation, cipherType, input, key, option) { option = option || {}; validate(key, option.mode, cipherType); if (typeof input === "string") { input = operation === Cipher.ENCRYPT_MODE ? Data.parseUTF8(input) : Data.parseBase64(input); } let secretKey = new SecretKeySpec(key.toBytes(), cipherType); let cipher = Cipher.getInstance(option.mode || cipherType); if (option.iv != null) { cipher.init(operation, secretKey, new IvParameterSpec(option.iv.toBytes())); } else { cipher.init(operation, secretKey); } return new Data(cipher.doFinal(input.toBytes())); } const AES = { encrypt(data, key, option) { return result = process(Cipher.ENCRYPT_MODE, "AES", data, key, option); }, decrypt(data, key, option) { return process(Cipher.DECRYPT_MODE, "AES", data, key, option); } } const DES = { encrypt(data, key, option) { return process(Cipher.ENCRYPT_MODE, "DES", data, key, option); }, decrypt(data, key, option) { return process(Cipher.DECRYPT_MODE, "DES", data, key, option); } } const DESede = { encrypt(data, key, option) { return process(Cipher.ENCRYPT_MODE, "DESede", data, key, option); }, decrypt(data, key, option) { return process(Cipher.DECRYPT_MODE, "DESede", data, key, option); } } function validate(key, mode, cipherType) { if (key == null) { throw new Error("Key must not be null or empty."); } if (mode && !mode.startsWith(cipherType)) { throw new Error("Invalid mode."); } let expectedKeyLength = []; switch (cipherType) { case "AES": expectedKeyLength = [16, 24, 36]; break; case "DESede": expectedKeyLength = [24]; break; case "DES": expectedKeyLength = [8]; break; default: throw new Error("Invalid cipher type."); } if (!expectedKeyLength.includes(key.length)) { throw new Error("Invalid key length. Key length must be " + expectedKeyLength.join(" or ") + " bytes for " + cipherType + "."); } } /*mode AES/CBC/PKCS5Padding AES/CBC/NoPadding AES/ECB/PKCS5Padding AES/ECB/NoPadding AES/CFB/NoPadding AES/CFB/PKCS5Padding AES/OFB/NoPadding AES/OFB/PKCS5Padding AES/CTR/NoPadding AES/CTR/PKCS5Padding DES/CBC/PKCS5Padding DES/CBC/NoPadding DES/ECB/PKCS5Padding DES/ECB/NoPadding DES/CFB/NoPadding DES/CFB/PKCS5Padding DES/OFB/NoPadding DES/OFB/PKCS5Padding DES/CTR/NoPadding DES/CTR/PKCS5Padding */ function bytesToString(bytes, charset) { return String(new jvString(bytes, charset || StandardCharsets.UTF_8)); } function base64EncodeToByteArray(str, flags) { return Base64.encode(str.getBytes(StandardCharsets.UTF_8), flags || Base64.DEFAULT); } function base64DecodeToByteArray(str, flags) { if (str == null) { return null; } return Base64.decode(str, flags || Base64.DEFAULT); } function hexDecodeToByteArray(cipherText) { cipherText = String(cipherText); let str = cipherText.toLowerCase(); let length = str.length; let bArr = java.lang.reflect.Array.newInstance(java.lang.Byte.TYPE, length / 2); for (let i = 0, o = 0; i < length; i += 2, o++) { let a = str[i + 1], b = str[i]; if (b != "0") { a = b + a; } let hexInt = Integer.parseInt(new jvString(a), 16); let inty = hexInt > 127 ? hexInt - 255 - 1 : hexInt; bArr[o] = inty; } return bArr; } function bytesToHex(data) { let strBuffer = new StringBuffer(); for (let i = 0; i < data.length; i++) { //strBuffer.append(Integer.toHexString(0xff & data[i])); strBuffer.append(jvString.format("%02x", Byte(data[i]))); } return String(strBuffer.toString()); } function toJvString(str) { if (typeof str === "string") { return new jvString(str); } else { return str; } } $.exports = { Data, Digest, AES, DES, DESede }; })() let 图片解密 = function(key,iv,kiType,mode) { function hexStringToBytes(cipherText) { cipherText = String(cipherText); let str = cipherText.toLowerCase(); let length = str.length; let bArr = java.lang.reflect.Array.newInstance(java.lang.Byte.TYPE, length / 2); for (let i = 0, o = 0; i < length; i += 2, o++) { let a = str[i + 1], b = str[i]; if (b != "0") { a = b + a; } let hexInt = java.lang.Integer.parseInt(new java.lang.String(a), 16); let inty = hexInt > 127 ? hexInt - 255 - 1 : hexInt; bArr[o] = inty; } return bArr; } let javaImport = new JavaImporter(); javaImport.importPackage( Packages.com.example.hikerview.utils, Packages.java.lang, Packages.java.security, Packages.javax.crypto, Packages.javax.crypto.spec ); with(javaImport) { function getBytes(str) { let bytes; if (kiType === "Base64") { bytes = _base64.decode(str, _base64.NO_WRAP); } else if (kiType === "Hex") { bytes = hexStringToBytes(str); } else { bytes = String(str).getBytes("UTF-8"); } return bytes; } kiType = kiType || "String"; mode = mode || 'AES/CBC/PKCS5Padding'; key = getBytes(key); iv = getBytes(iv); function decryptData(cipherText) { let secretKeySpec = new SecretKeySpec(key, "AES"); let ivParameterSpec = new IvParameterSpec(iv); let cipher = Cipher.getInstance(mode); cipher.init(2, secretKeySpec, ivParameterSpec); return cipher.doFinal(cipherText); } let bytes = FileUtil.toBytes(input); bytes = decryptData(bytes); return FileUtil.toInputStream(bytes); } } //最新方法 CryptoUtil = $.require("hiker://assets/crypto-java.js"); str_key = CryptoUtil.Data.parseUTF8("BH6MxHTGX2cUUGRdWAg5Vt20awucQsiQ"); str_iv = CryptoUtil.Data.parseUTF8("7RUK0XQYLDMqNWob"); aes = word => CryptoUtil.AES.decrypt(word, str_key, { mode: "AES/CBC/PKCS5Padding", iv: str_iv }).toString(); log(aes(fetch("https://alldown.magictool.cn/pro/qsyApi.php?url=https://v.douyin.com/iLku17Bh/&token=lKKln239WEOjfweLLAP02JNs")));