diff --git a/app/src/main/java/io/legado/app/data/entities/BaseSource.kt b/app/src/main/java/io/legado/app/data/entities/BaseSource.kt index 0c4c186f7..f73d2977e 100644 --- a/app/src/main/java/io/legado/app/data/entities/BaseSource.kt +++ b/app/src/main/java/io/legado/app/data/entities/BaseSource.kt @@ -2,6 +2,7 @@ package io.legado.app.data.entities import android.util.Base64 import com.script.SimpleBindings +import cn.hutool.crypto.symmetric.AES import io.legado.app.constant.AppConst import io.legado.app.constant.AppLog import io.legado.app.data.entities.rule.RowUi @@ -119,10 +120,7 @@ interface BaseSource : JsExtensions { try { val key = AppConst.androidId.encodeToByteArray(0, 16) val cache = CacheManager.get("userInfo_${getKey()}") ?: return null - val encodeBytes = Base64.decode(cache, Base64.DEFAULT) - val decodeBytes = EncoderUtils.decryptAES(encodeBytes, key) - ?: return null - return String(decodeBytes) + return AES(key).decryptStr(cache) } catch (e: Exception) { AppLog.put("获取登陆信息出错", e) return null @@ -139,8 +137,7 @@ interface BaseSource : JsExtensions { fun putLoginInfo(info: String): Boolean { return try { val key = (AppConst.androidId).encodeToByteArray(0, 16) - val encodeBytes = EncoderUtils.encryptAES(info.toByteArray(), key) - val encodeStr = Base64.encodeToString(encodeBytes, Base64.DEFAULT) + val encodeStr = AES(key).encryptBase64(info) CacheManager.put("userInfo_${getKey()}", encodeStr) true } catch (e: Exception) { diff --git a/app/src/main/java/io/legado/app/help/JsExtensions.kt b/app/src/main/java/io/legado/app/help/JsExtensions.kt index 7990165aa..d2ef307c4 100644 --- a/app/src/main/java/io/legado/app/help/JsExtensions.kt +++ b/app/src/main/java/io/legado/app/help/JsExtensions.kt @@ -5,6 +5,7 @@ import android.util.Base64 import androidx.annotation.Keep import cn.hutool.crypto.digest.DigestUtil import cn.hutool.crypto.digest.HMac +import cn.hutool.core.util.HexUtil import io.legado.app.constant.AppConst import io.legado.app.constant.AppConst.dateFormat import io.legado.app.constant.AppLog @@ -245,7 +246,7 @@ interface JsExtensions { ) FileUtils.delete(path) val file = FileUtils.createFileIfNotExist(path) - StringUtils.hexStringToByte(content).let { + HexUtil.decodeHex(content).let { if (it.isNotEmpty()) { file.writeBytes(it) } @@ -510,7 +511,7 @@ interface JsExtensions { val bytes = if (url.isAbsUrl()) { AnalyzeUrl(url, source = getSource()).getByteArray() } else { - StringUtils.hexStringToByte(url) + HexUtil.decodeHex(url) } val bos = ByteArrayOutputStream() val zis = ZipInputStream(ByteArrayInputStream(bytes)) @@ -647,356 +648,6 @@ interface JsExtensions { //******************对称加密解密************************// - /////AES - /** - * AES 解码为 ByteArray - * @param str 传入的AES加密的数据 - * @param key AES 解密的key - * @param transformation AES加密的方式 - * @param iv ECB模式的偏移向量 - */ - fun aesDecodeToByteArray( - str: String, key: String, transformation: String, iv: String - ): ByteArray? { - return try { - EncoderUtils.decryptAES( - data = str.encodeToByteArray(), - key = key.encodeToByteArray(), - transformation, - iv.encodeToByteArray() - ) - } catch (e: Exception) { - e.printOnDebug() - log(e.localizedMessage ?: "aesDecodeToByteArrayERROR") - null - } - } - - /** - * AES 解码为 String - * @param str 传入的AES加密的数据 - * @param key AES 解密的key - * @param transformation AES加密的方式 - * @param iv ECB模式的偏移向量 - */ - - fun aesDecodeToString( - str: String, key: String, transformation: String, iv: String - ): String? { - return aesDecodeToByteArray(str, key, transformation, iv)?.let { String(it) } - } - - /** - * AES解码为String,算法参数经过Base64加密 - * - * @param data 加密的字符串 - * @param key Base64后的密钥 - * @param mode 模式 - * @param padding 补码方式 - * @param iv Base64后的加盐 - * @return 解密后的字符串 - */ - fun aesDecodeArgsBase64Str( - data: String, - key: String, - mode: String, - padding: String, - iv: String - ): String? { - return EncoderUtils.decryptAES( - data.encodeToByteArray(), - Base64.decode(key, Base64.NO_WRAP), - "AES/${mode}/${padding}", - Base64.decode(iv, Base64.NO_WRAP) - )?.let { String(it) } - } - - /** - * 已经base64的AES 解码为 ByteArray - * @param str 传入的AES Base64加密的数据 - * @param key AES 解密的key - * @param transformation AES加密的方式 - * @param iv ECB模式的偏移向量 - */ - - fun aesBase64DecodeToByteArray( - str: String, key: String, transformation: String, iv: String - ): ByteArray? { - return try { - EncoderUtils.decryptBase64AES( - str.encodeToByteArray(), - key.encodeToByteArray(), - transformation, - iv.encodeToByteArray() - ) - } catch (e: Exception) { - e.printOnDebug() - log(e.localizedMessage ?: "aesDecodeToByteArrayERROR") - null - } - } - - /** - * 已经base64的AES 解码为 String - * @param str 传入的AES Base64加密的数据 - * @param key AES 解密的key - * @param transformation AES加密的方式 - * @param iv ECB模式的偏移向量 - */ - - fun aesBase64DecodeToString( - str: String, key: String, transformation: String, iv: String - ): String? { - return aesBase64DecodeToByteArray(str, key, transformation, iv)?.let { String(it) } - } - - /** - * 加密aes为ByteArray - * @param data 传入的原始数据 - * @param key AES加密的key - * @param transformation AES加密的方式 - * @param iv ECB模式的偏移向量 - */ - fun aesEncodeToByteArray( - data: String, key: String, transformation: String, iv: String - ): ByteArray? { - return try { - EncoderUtils.encryptAES( - data.encodeToByteArray(), - key = key.encodeToByteArray(), - transformation, - iv.encodeToByteArray() - ) - } catch (e: Exception) { - e.printOnDebug() - log(e.localizedMessage ?: "aesEncodeToByteArrayERROR") - null - } - } - - /** - * 加密aes为String - * @param data 传入的原始数据 - * @param key AES加密的key - * @param transformation AES加密的方式 - * @param iv ECB模式的偏移向量 - */ - fun aesEncodeToString( - data: String, key: String, transformation: String, iv: String - ): String? { - return aesEncodeToByteArray(data, key, transformation, iv)?.let { String(it) } - } - - /** - * 加密aes后Base64化的ByteArray - * @param data 传入的原始数据 - * @param key AES加密的key - * @param transformation AES加密的方式 - * @param iv ECB模式的偏移向量 - */ - fun aesEncodeToBase64ByteArray( - data: String, key: String, transformation: String, iv: String - ): ByteArray? { - return try { - EncoderUtils.encryptAES2Base64( - data.encodeToByteArray(), - key.encodeToByteArray(), - transformation, - iv.encodeToByteArray() - ) - } catch (e: Exception) { - e.printOnDebug() - log(e.localizedMessage ?: "aesEncodeToBase64ByteArrayERROR") - null - } - } - - /** - * 加密aes后Base64化的String - * @param data 传入的原始数据 - * @param key AES加密的key - * @param transformation AES加密的方式 - * @param iv ECB模式的偏移向量 - */ - fun aesEncodeToBase64String( - data: String, key: String, transformation: String, iv: String - ): String? { - return aesEncodeToBase64ByteArray(data, key, transformation, iv)?.let { String(it) } - } - - - /** - * AES加密并转为Base64,算法参数经过Base64加密 - * - * @param data 被加密的字符串 - * @param key Base64后的密钥 - * @param mode 模式 - * @param padding 补码方式 - * @param iv Base64后的加盐 - * @return 加密后的Base64 - */ - fun aesEncodeArgsBase64Str( - data: String, - key: String, - mode: String, - padding: String, - iv: String - ): String? { - return EncoderUtils.encryptAES2Base64( - data.encodeToByteArray(), - Base64.decode(key, Base64.NO_WRAP), - "AES/${mode}/${padding}", - Base64.decode(iv, Base64.NO_WRAP) - )?.let { String(it) } - } - - /////DES - fun desDecodeToString( - data: String, key: String, transformation: String, iv: String - ): String? { - return EncoderUtils.decryptDES( - data.encodeToByteArray(), - key.encodeToByteArray(), - transformation, - iv.encodeToByteArray() - )?.let { String(it) } - } - - fun desBase64DecodeToString( - data: String, key: String, transformation: String, iv: String - ): String? { - return EncoderUtils.decryptBase64DES( - data.encodeToByteArray(), - key.encodeToByteArray(), - transformation, - iv.encodeToByteArray() - )?.let { String(it) } - } - - fun desEncodeToString( - data: String, key: String, transformation: String, iv: String - ): String? { - return EncoderUtils.encryptDES( - data.encodeToByteArray(), - key.encodeToByteArray(), - transformation, - iv.encodeToByteArray() - )?.let { String(it) } - } - - fun desEncodeToBase64String( - data: String, key: String, transformation: String, iv: String - ): String? { - return EncoderUtils.encryptDES2Base64( - data.encodeToByteArray(), - key.encodeToByteArray(), - transformation, - iv.encodeToByteArray() - )?.let { String(it) } - } - - //////3DES - /** - * 3DES解密 - * - * @param data 加密的字符串 - * @param key 密钥 - * @param mode 模式 - * @param padding 补码方式 - * @param iv 加盐 - * @return 解密后的字符串 - */ - fun tripleDESDecodeStr( - data: String, - key: String, - mode: String, - padding: String, - iv: String - ): String? { - return EncoderUtils.decryptDESede( - data.encodeToByteArray(), - key.encodeToByteArray(), - "DESede/${mode}/${padding}", - iv.encodeToByteArray() - )?.let { String(it) } - } - - /** - * 3DES解密,算法参数经过Base64加密 - * - * @param data 加密的字符串 - * @param key Base64后的密钥 - * @param mode 模式 - * @param padding 补码方式 - * @param iv Base64后的加盐 - * @return 解密后的字符串 - */ - fun tripleDESDecodeArgsBase64Str( - data: String, - key: String, - mode: String, - padding: String, - iv: String - ): String? { - return EncoderUtils.decryptDESede( - data.encodeToByteArray(), - Base64.decode(key, Base64.NO_WRAP), - "DESede/${mode}/${padding}", - Base64.decode(iv, Base64.NO_WRAP) - )?.let { String(it) } - } - - - /** - * 3DES加密并转为Base64 - * - * @param data 被加密的字符串 - * @param key 密钥 - * @param mode 模式 - * @param padding 补码方式 - * @param iv 加盐 - * @return 加密后的Base64 - */ - fun tripleDESEncodeBase64Str( - data: String, - key: String, - mode: String, - padding: String, - iv: String - ): String? { - return EncoderUtils.encryptDESede2Base64( - data.encodeToByteArray(), - key.encodeToByteArray(), - "DESede/${mode}/${padding}", - iv.encodeToByteArray() - )?.let { String(it) } - } - - /** - * 3DES加密并转为Base64,算法参数经过Base64加密 - * - * @param data 被加密的字符串 - * @param key Base64后的密钥 - * @param mode 模式 - * @param padding 补码方式 - * @param iv Base64后的加盐 - * @return 加密后的Base64 - */ - fun tripleDESEncodeArgsBase64Str( - data: String, - key: String, - mode: String, - padding: String, - iv: String - ): String? { - return EncoderUtils.encryptDESede2Base64( - data.encodeToByteArray(), - Base64.decode(key, Base64.NO_WRAP), - "DESede/${mode}/${padding}", - Base64.decode(iv, Base64.NO_WRAP) - )?.let { String(it) } - } - //******************消息摘要/散列消息鉴别码************************// /** diff --git a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt index f35ca3965..a2d71f570 100644 --- a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt +++ b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt @@ -5,6 +5,7 @@ import android.util.Base64 import androidx.annotation.Keep import com.bumptech.glide.load.model.GlideUrl import com.script.SimpleBindings +import cn.hutool.core.util.HexUtil import io.legado.app.constant.AppConst.SCRIPT_ENGINE import io.legado.app.constant.AppConst.UA_NAME import io.legado.app.constant.AppPattern.JS_PATTERN @@ -350,7 +351,7 @@ class AnalyzeUrl( useWebView: Boolean = true, ): StrResponse { if (type != null) { - return StrResponse(url, StringUtils.byteToHexString(getByteArrayAwait())) + return StrResponse(url, HexUtil.encodeHexStr(getByteArrayAwait())) } val concurrentRecord = fetchStart() setCookie(source?.getKey()) diff --git a/app/src/main/java/io/legado/app/utils/EncoderUtils.kt b/app/src/main/java/io/legado/app/utils/EncoderUtils.kt index a9adacb30..fec85ff2c 100644 --- a/app/src/main/java/io/legado/app/utils/EncoderUtils.kt +++ b/app/src/main/java/io/legado/app/utils/EncoderUtils.kt @@ -1,13 +1,9 @@ package io.legado.app.utils import android.util.Base64 -import cn.hutool.crypto.symmetric.SymmetricCrypto -import java.security.spec.AlgorithmParameterSpec -import javax.crypto.spec.IvParameterSpec -import javax.crypto.spec.SecretKeySpec /** - * transformations https://developer.android.google.cn/reference/kotlin/javax/crypto/Cipher?hl=en + * 编码工具 escape base64 */ @Suppress("unused") object EncoderUtils { @@ -42,302 +38,4 @@ object EncoderUtils { return Base64.encodeToString(str.toByteArray(), flags) } - //////////AES Start - - /** - * Return the Base64-encode bytes of AES encryption. - * - * @param data The data. - * @param key The key. - * @param transformation The name of the transformation, - * 加密算法/加密模式/填充类型, *AES/CBC/PKCS5Padding*. - * @param iv The buffer with the IV. The contents of the - * buffer are copied to protect against subsequent modification. - * @return the Base64-encode bytes of AES encryption - */ - @Throws(Exception::class) - fun encryptAES2Base64( - data: ByteArray?, - key: ByteArray?, - transformation: String? = "AES/ECB/PKCS5Padding", - iv: ByteArray? = null - ): ByteArray? { - return Base64.encode(encryptAES(data, key, transformation, iv), Base64.NO_WRAP) - } - - /** - * Return the bytes of AES encryption. - * - * @param data The data. - * @param key The key. - * @param transformation The name of the transformation, - * 加密算法/加密模式/填充类型, *AES/CBC/PKCS5Padding*. - * @param iv The buffer with the IV. The contents of the - * buffer are copied to protect against subsequent modification. - * @return the bytes of AES encryption - */ - @Throws(Exception::class) - fun encryptAES( - data: ByteArray?, - key: ByteArray?, - transformation: String? = "AES/ECB/PKCS5Padding", - iv: ByteArray? = null - ): ByteArray? { - return symmetricTemplate(data, key, "AES", transformation!!, iv, true) - } - - - /** - * Return the bytes of AES decryption for Base64-encode bytes. - * - * @param data The data. - * @param key The key. - * @param transformation The name of the transformation, - * 加密算法/加密模式/填充类型, *AES/CBC/PKCS5Padding*. - * @param iv The buffer with the IV. The contents of the - * buffer are copied to protect against subsequent modification. - * @return the bytes of AES decryption for Base64-encode bytes - */ - @Throws(Exception::class) - fun decryptBase64AES( - data: ByteArray?, - key: ByteArray?, - transformation: String = "AES/ECB/PKCS5Padding", - iv: ByteArray? = null - ): ByteArray? { - return decryptAES(Base64.decode(data, Base64.NO_WRAP), key, transformation, iv) - } - - /** - * Return the bytes of AES decryption. - * - * @param data The data. - * @param key The key. - * @param transformation The name of the transformation, - * 加密算法/加密模式/填充类型, *AES/CBC/PKCS5Padding*. - * @param iv The buffer with the IV. The contents of the - * buffer are copied to protect against subsequent modification. - * @return the bytes of AES decryption - */ - @Throws(Exception::class) - fun decryptAES( - data: ByteArray?, - key: ByteArray?, - transformation: String = "AES/ECB/PKCS5Padding", - iv: ByteArray? = null - ): ByteArray? { - return symmetricTemplate(data, key, "AES", transformation, iv, false) - } - - //////////DES Start - - /** - * Return the Base64-encode bytes of DES encryption. - * - * @param data The data. - * @param key The key. - * @param transformation The name of the transformation, - * 加密算法/加密模式/填充类型, *DES/CBC/PKCS5Padding*. - * @param iv The buffer with the IV. The contents of the - * buffer are copied to protect against subsequent modification. - * @return the Base64-encode bytes of AES encryption - */ - @Throws(Exception::class) - fun encryptDES2Base64( - data: ByteArray?, - key: ByteArray?, - transformation: String? = "DES/ECB/PKCS5Padding", - iv: ByteArray? = null - ): ByteArray? { - return Base64.encode(encryptDES(data, key, transformation, iv), Base64.NO_WRAP) - } - - /** - * Return the bytes of DES encryption. - * - * @param data The data. - * @param key The key. - * @param transformation The name of the transformation, - * 加密算法/加密模式/填充类型, *DES/CBC/PKCS5Padding*. - * @param iv The buffer with the IV. The contents of the - * buffer are copied to protect against subsequent modification. - * @return the bytes of AES encryption - */ - @Throws(Exception::class) - fun encryptDES( - data: ByteArray?, - key: ByteArray?, - transformation: String? = "DES/ECB/PKCS5Padding", - iv: ByteArray? = null - ): ByteArray? { - return symmetricTemplate(data, key, "DES", transformation!!, iv, true) - } - - - /** - * Return the bytes of DES decryption for Base64-encode bytes. - * - * @param data The data. - * @param key The key. - * @param transformation The name of the transformation, - * 加密算法/加密模式/填充类型, *DES/CBC/PKCS5Padding*. - * @param iv The buffer with the IV. The contents of the - * buffer are copied to protect against subsequent modification. - * @return the bytes of AES decryption for Base64-encode bytes - */ - @Throws(Exception::class) - fun decryptBase64DES( - data: ByteArray?, - key: ByteArray?, - transformation: String = "DES/ECB/PKCS5Padding", - iv: ByteArray? = null - ): ByteArray? { - return decryptDES(Base64.decode(data, Base64.NO_WRAP), key, transformation, iv) - } - - /** - * Return the bytes of DES decryption. - * - * @param data The data. - * @param key The key. - * @param transformation The name of the transformation, - * 加密算法/加密模式/填充类型, *DES/CBC/PKCS5Padding*. - * @param iv The buffer with the IV. The contents of the - * buffer are copied to protect against subsequent modification. - * @return the bytes of AES decryption - */ - @Throws(Exception::class) - fun decryptDES( - data: ByteArray?, - key: ByteArray?, - transformation: String = "DES/ECB/PKCS5Padding", - iv: ByteArray? = null - ): ByteArray? { - return symmetricTemplate(data, key, "DES", transformation, iv, false) - } - - //////////DESede Start - - /** - * Return the Base64-encode bytes of DESede encryption. - * - * @param data The data. - * @param key The key. - * @param transformation The name of the transformation, - * 加密算法/加密模式/填充类型, *DESede/CBC/PKCS5Padding*. - * @param iv The buffer with the IV. The contents of the - * buffer are copied to protect against subsequent modification. - * @return the Base64-encode bytes of AES encryption - */ - @Throws(Exception::class) - fun encryptDESede2Base64( - data: ByteArray?, - key: ByteArray?, - transformation: String? = "DESede/ECB/PKCS5Padding", - iv: ByteArray? = null - ): ByteArray? { - return Base64.encode(encryptDESede(data, key, transformation, iv), Base64.NO_WRAP) - } - - /** - * Return the bytes of DESede encryption. - * - * @param data The data. - * @param key The key. - * @param transformation The name of the transformation, - * 加密算法/加密模式/填充类型, *DESede/CBC/PKCS5Padding*. - * @param iv The buffer with the IV. The contents of the - * buffer are copied to protect against subsequent modification. - * @return the bytes of AES encryption - */ - @Throws(Exception::class) - fun encryptDESede( - data: ByteArray?, - key: ByteArray?, - transformation: String? = "DESede/ECB/PKCS5Padding", - iv: ByteArray? = null - ): ByteArray? { - return symmetricTemplate(data, key, "DESede", transformation!!, iv, true) - } - - - /** - * Return the bytes of DESede decryption for Base64-encode bytes. - * - * @param data The data. - * @param key The key. - * @param transformation The name of the transformation, - * 加密算法/加密模式/填充类型, *DESede/CBC/PKCS5Padding*. - * @param iv The buffer with the IV. The contents of the - * buffer are copied to protect against subsequent modification. - * @return the bytes of AES decryption for Base64-encode bytes - */ - @Throws(Exception::class) - fun decryptBase64DESede( - data: ByteArray?, - key: ByteArray?, - transformation: String = "DESede/ECB/PKCS5Padding", - iv: ByteArray? = null - ): ByteArray? { - return decryptDESede(Base64.decode(data, Base64.NO_WRAP), key, transformation, iv) - } - - /** - * Return the bytes of DESede decryption. - * - * @param data The data. - * @param key The key. - * @param transformation The name of the transformation, - * 加密算法/加密模式/填充类型, *DESede/CBC/PKCS5Padding*. - * @param iv The buffer with the IV. The contents of the - * buffer are copied to protect against subsequent modification. - * @return the bytes of AES decryption - */ - @Throws(Exception::class) - fun decryptDESede( - data: ByteArray?, - key: ByteArray?, - transformation: String = "DESede/ECB/PKCS5Padding", - iv: ByteArray? = null - ): ByteArray? { - return symmetricTemplate(data, key, "DESede", transformation, iv, false) - } - - /** - * Return the bytes of symmetric encryption or decryption. - * - * @param data The data. - * @param key The key. - * @param algorithm The name of algorithm. - * @param transformation The name of the transformation, - * 加密算法/加密模式/填充类型, DES/CBC/PKCS5Padding. - * @param iv The buffer with the IV. The contents of the - * buffer are copied to protect against subsequent modification. - * @param isEncrypt True to encrypt, false otherwise. - * @return the bytes of symmetric encryption or decryption - */ - @Suppress("SameParameterValue") - @Throws(Exception::class) - private fun symmetricTemplate( - data: ByteArray?, - key: ByteArray?, - algorithm: String, - transformation: String, - iv: ByteArray?, - isEncrypt: Boolean - ): ByteArray? { - return if (data == null || data.isEmpty() || key == null || key.isEmpty()) null - else { - //hutool support zeropadding - val keySpec = SecretKeySpec(key, algorithm) - var params: AlgorithmParameterSpec? = null - if (iv != null && !iv.isEmpty()) { - params = IvParameterSpec(iv) - } - val symmetricCrypto = SymmetricCrypto(transformation, keySpec, params) - if (isEncrypt) symmetricCrypto.encrypt(data) else symmetricCrypto.decrypt(data) - } - } - - } diff --git a/app/src/main/java/io/legado/app/utils/StringUtils.kt b/app/src/main/java/io/legado/app/utils/StringUtils.kt index 4ae38fe46..770c48dc0 100644 --- a/app/src/main/java/io/legado/app/utils/StringUtils.kt +++ b/app/src/main/java/io/legado/app/utils/StringUtils.kt @@ -287,30 +287,4 @@ object StringUtils { return buf.toString() } - fun byteToHexString(bytes: ByteArray?): String { - if (bytes == null) return "" - val sb = StringBuilder(bytes.size * 2) - for (b in bytes) { - val hex = 0xff and b.toInt() - if (hex < 16) { - sb.append('0') - } - sb.append(Integer.toHexString(hex)) - } - return sb.toString() - } - - fun hexStringToByte(hexString: String): ByteArray { - val hexStr = hexString.replace(" ", "") - val len = hexStr.length - val bytes = ByteArray(len / 2) - var i = 0 - while (i < len) { - // 两位一组,表示一个字节,把这样表示的16进制字符串,还原成一个字节 - bytes[i / 2] = ((Character.digit(hexString[i], 16) shl 4) + - Character.digit(hexString[i + 1], 16)).toByte() - i += 2 - } - return bytes - } }