diff --git a/app/build.gradle b/app/build.gradle index 09cd486d7..b94a88f5c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -255,7 +255,7 @@ dependencies { implementation('com.github.liuyueyi.quick-chinese-transfer:quick-transfer-core:0.2.3') //加解密类库 - implementation('cn.hutool:hutool-crypto:5.8.1') + //implementation('cn.hutool:hutool-crypto:5.8.1') //renderscriptToolkit implementation('com.github.android:renderscript-intrinsics-replacement-toolkit:b6363490c3') diff --git a/app/src/main/assets/help/jsHelp.md b/app/src/main/assets/help/jsHelp.md index 420f45ebe..1f91ed457 100644 --- a/app/src/main/assets/help/jsHelp.md +++ b/app/src/main/assets/help/jsHelp.md @@ -54,7 +54,11 @@ java.put(key, value) java.ajax(urlStr): String java.ajaxAll(urlList: Array): Array //返回Response 方法body() code() message() header() raw() toString() -java.connect(urlStr): Response +java.connect(urlStr): StrResponse + +java.post(url: String, body: String, headerMap: Map): Connection.Response +java.get(url: String, headerMap: Map): Connection.Response +java.head(url: String, headerMap: Map): Connection.Response * 使用webView访问网络 * @param html 直接用webView载入的html, 如果html为空直接访问url @@ -128,13 +132,11 @@ deleteFile(path: String) ``` **** > [常见加密解密算法介绍](https://www.yijiyong.com/algorithm/encryption/01-intro.html) -> [相关概念](https://blog.csdn.net/OrangeJack/article/details/82913804) +> [相关概念](https://blog.csdn.net/OrangeJack/article/details/82913804) +> [Android支持的transformation](https://developer.android.google.cn/reference/kotlin/javax/crypto/Cipher?hl=en) * AES +> transformation默认实现AES/ECB/PKCS5Padding ``` -* @param data 传入的原始数据 -* @param key AES加密的key -* @param transformation AES加密的方式 例如AES/ECB/PKCS5Padding -* @param iv ECB模式的偏移向量 java.aesDecodeToString(str: String, key: String, transformation: String, iv: String) java.aesBase64DecodeToString(str: String, key: String, transformation: String, iv: String) @@ -143,24 +145,37 @@ java.aesEncodeToString(str: String, key: String, transformation: String, iv: Str java.aesEncodeToBase64String(str: String, key: String, transformation: String, iv: String) ``` +* DES +> transformation默认实现DES/ECB/PKCS5Padding +``` +java.desDecodeToString(str: String, key: String, transformation: String, iv: String) + +java.desBase64DecodeToString(str: String, key: String, transformation: String, iv: String) + +java.desEncodeToString(str: String, key: String, transformation: String, iv: String) + +java.desEncodeToBase64String(str: String, key: String, transformation: String, iv: String) +``` * 3DES +> tansformation默认实现DESede/ECB/PKCS5Padding ``` -* @param data 被加密的字符串 -* @param key 密钥 -* @param mode 模式 ECB/CBC/CFB/OFB/CTR -* @param padding 补码方式 NoPadding/PKCS5Padding/ -* @param iv 加盐 java.tripleDESEncodeBase64Str(data: String,key: String,mode: String,padding: String,iv: String): String? java.tripleDESDecodeStr(data: String,key: String,mode: String,padding: String,iv: String): String? ``` * 摘要 +> algorithm支持MD5 SHA-1 SHA-224 SHA-256 SHA-384 SHA-512 +``` +java.digestHex(data: String, algorithm: String,): String? + +java.digestBase64Str(data: String, algorithm: String,): String? +``` +* HMac(散列消息鉴别码) +> algorithm支持DESMAC DESMAC/CFB8 DESedeMAC DESedeMAC/CFB8 DESedeMAC64 DESwithISO9797 HmacMD5 HmacSHA* ISO9797ALG3MAC PBEwithSHA* ``` -* @param data 被摘要数据 -* @param algorithm 签名算法 MD5/SHA1/SHA256/SHA512 -java.digestHex(data: String,algorithm: String,): String? +java.HMacHex(data: String, algorithm: String, key: String): String -java.digestBase64Str(data: String,algorithm: String,): String? +java.HMacBase64(data: String, algorithm: String, key: String): String ``` * md5 ``` diff --git a/app/src/main/assets/updateLog.md b/app/src/main/assets/updateLog.md index d689e0f54..f7731b3a4 100644 --- a/app/src/main/assets/updateLog.md +++ b/app/src/main/assets/updateLog.md @@ -15,6 +15,8 @@ * 修复部分txt章节结尾乱码bug * 优化翻页流畅度 +* js添加des HMac +* 登录ui用户信息默认加密方式改变,需要重新登录 **2022/05/21** @@ -322,4 +324,4 @@ eval(String(java.cacheFile(url))) **2022/01/01** * 修复本地txt问题,不在拷贝到私有目录,可以正常打开 -* 优化txt目录识别,取目录数量最多的规则 \ No newline at end of file +* 优化txt目录识别,取目录数量最多的规则 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 0d1c117a3..cad84aba4 100644 --- a/app/src/main/java/io/legado/app/help/JsExtensions.kt +++ b/app/src/main/java/io/legado/app/help/JsExtensions.kt @@ -3,9 +3,6 @@ package io.legado.app.help import android.net.Uri import android.util.Base64 import androidx.annotation.Keep -import cn.hutool.crypto.digest.DigestUtil -import cn.hutool.crypto.symmetric.AES -import cn.hutool.crypto.symmetric.DESede import io.legado.app.constant.AppConst import io.legado.app.constant.AppConst.dateFormat import io.legado.app.constant.AppLog @@ -299,14 +296,6 @@ interface JsExtensions { return EncoderUtils.base64Encode(str, flags) } - fun md5Encode(str: String): String { - return MD5Utils.md5Encode(str) - } - - fun md5Encode16(str: String): String { - return MD5Utils.md5Encode16(str) - } - /** * 格式化时间 */ @@ -602,6 +591,13 @@ interface JsExtensions { return UUID.randomUUID().toString() } + fun androidId(): String { + return AppConst.androidId + } + +//******************对称加密解密************************// + + /////AES /** * AES 解码为 ByteArray * @param str 传入的AES加密的数据 @@ -640,6 +636,31 @@ interface JsExtensions { 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加密的数据 @@ -753,35 +774,78 @@ interface JsExtensions { return aesEncodeToBase64ByteArray(data, key, transformation, iv)?.let { String(it) } } - fun androidId(): String { - return AppConst.androidId - } /** - * AES解密,算法参数经过Base64加密 + * AES加密并转为Base64,算法参数经过Base64加密 * - * @param data 加密的字符串 + * @param data 被加密的字符串 * @param key Base64后的密钥 * @param mode 模式 * @param padding 补码方式 * @param iv Base64后的加盐 - * @return 解密后的字符串 + * @return 加密后的Base64 */ - fun aesDecodeArgsBase64Str( + fun aesEncodeArgsBase64Str( data: String, key: String, mode: String, padding: String, iv: String ): String? { - return AES( - mode, - padding, + return EncoderUtils.encryptAES2Base64( + data.encodeToByteArray(), Base64.decode(key, Base64.NO_WRAP), + "AES/${mode}/${padding}", Base64.decode(iv, Base64.NO_WRAP) - ).decryptStr(data) + )?.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解密 * @@ -799,7 +863,12 @@ interface JsExtensions { padding: String, iv: String ): String? { - return DESede(mode, padding, key.toByteArray(), iv.toByteArray()).decryptStr(data) + return EncoderUtils.decryptDESede( + data.encodeToByteArray(), + key.encodeToByteArray(), + "DESede/${mode}/${padding}", + iv.encodeToByteArray() + )?.let { String(it) } } /** @@ -819,38 +888,14 @@ interface JsExtensions { padding: String, iv: String ): String? { - return DESede( - mode, - padding, + return EncoderUtils.decryptDESede( + data.encodeToByteArray(), Base64.decode(key, Base64.NO_WRAP), + "DESede/${mode}/${padding}", Base64.decode(iv, Base64.NO_WRAP) - ).decryptStr(data) + )?.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 AES( - mode, - padding, - Base64.decode(key, Base64.NO_WRAP), - Base64.decode(iv, Base64.NO_WRAP) - ).encryptBase64(data) - } /** * 3DES加密并转为Base64 @@ -869,7 +914,12 @@ interface JsExtensions { padding: String, iv: String ): String? { - return DESede(mode, padding, key.toByteArray(), iv.toByteArray()).encryptBase64(data) + return EncoderUtils.encryptDESede2Base64( + data.encodeToByteArray(), + key.encodeToByteArray(), + "DESede/${mode}/${padding}", + iv.encodeToByteArray() + )?.let { String(it) } } /** @@ -889,14 +939,16 @@ interface JsExtensions { padding: String, iv: String ): String? { - return DESede( - mode, - padding, + return EncoderUtils.encryptDESede2Base64( + data.encodeToByteArray(), Base64.decode(key, Base64.NO_WRAP), + "DESede/${mode}/${padding}", Base64.decode(iv, Base64.NO_WRAP) - ).encryptBase64(data) + )?.let { String(it) } } +//******************消息摘要/散列消息鉴别码************************// + /** * 生成摘要,并转为16进制字符串 * @@ -907,8 +959,8 @@ interface JsExtensions { fun digestHex( data: String, algorithm: String, - ): String? { - return DigestUtil.digester(algorithm).digestHex(data) + ): String { + return DigestUtils.getDigest(algorithm, data) } /** @@ -921,8 +973,48 @@ interface JsExtensions { fun digestBase64Str( data: String, algorithm: String, - ): String? { - return Base64.encodeToString(DigestUtil.digester(algorithm).digest(data), Base64.NO_WRAP) + ): String { + return Base64.encodeToString(DigestUtils.getDigest(algorithm, data.toByteArray()), Base64.NO_WRAP) + } + + /** + * 生成散列消息鉴别码,并转为16进制字符串 + * + * @param data 被摘要数据 + * @param algorithm 签名算法 + * @param key 密钥 + * @return 16进制字符串 + */ + fun HMacHex( + data: String, + algorithm: String, + key: String + ): String { + return DigestUtils.getHMac(algorithm, key, data) + } + + /** + * 生成散列消息鉴别码,并转为Base64字符串 + * + * @param data 被摘要数据 + * @param algorithm 签名算法 + * @param key 密钥 + * @return Base64字符串 + */ + fun HMacBase64( + data: String, + algorithm: String, + key: String + ): String { + return Base64.encodeToString(DigestUtils.getHMac(algorithm, key.toByteArray(), data.toByteArray()), Base64.NO_WRAP) + } + + fun md5Encode(str: String): String { + return MD5Utils.md5Encode(str) + } + + fun md5Encode16(str: String): String { + return MD5Utils.md5Encode16(str) } } diff --git a/app/src/main/java/io/legado/app/ui/book/remote/RemoteBookAdapter.kt b/app/src/main/java/io/legado/app/ui/book/remote/RemoteBookAdapter.kt index 36dd38f86..3836cdb3d 100644 --- a/app/src/main/java/io/legado/app/ui/book/remote/RemoteBookAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/book/remote/RemoteBookAdapter.kt @@ -2,11 +2,12 @@ package io.legado.app.ui.book.remote import android.content.Context import android.view.ViewGroup -import cn.hutool.core.date.LocalDateTimeUtil import io.legado.app.base.adapter.ItemViewHolder import io.legado.app.base.adapter.RecyclerAdapter import io.legado.app.databinding.ItemRemoteBookBinding import io.legado.app.utils.ConvertUtils +import java.text.SimpleDateFormat +import java.util.Date /** @@ -38,7 +39,7 @@ class RemoteBookAdapter (context: Context, val callBack: CallBack) : tvName.text = item.filename.substringBeforeLast(".") tvContentType.text = item.contentType tvSize.text = ConvertUtils.formatFileSize(item.size) - tvDate.text = LocalDateTimeUtil.format(LocalDateTimeUtil.of(item.lastModify), "yyyy-MM-dd") + tvDate.text = SimpleDateFormat("yyyy-MM-dd").format(Date(item.lastModify)) } } diff --git a/app/src/main/java/io/legado/app/utils/DigestUtils.kt b/app/src/main/java/io/legado/app/utils/DigestUtils.kt new file mode 100644 index 000000000..b708b770c --- /dev/null +++ b/app/src/main/java/io/legado/app/utils/DigestUtils.kt @@ -0,0 +1,62 @@ +package io.legado.app.utils + +import java.security.MessageDigest +import javax.crypto.Mac +import javax.crypto.spec.SecretKeySpec + +object DigestUtils { + + /** + * 消息摘要 + * 支持MD5 SHA-1 SHA-224 SHA-256 SHA-384 SHA-512 + * https://developer.android.google.cn/reference/java/security/MessageDigest?hl=en + */ + fun getDigest( + algorithm: String, + data: String? + ): String { + data ?: return "" + val bytes = getDigest(algorithm, data.toByteArray()) + return StringUtils.byteToHexString(bytes) + } + + fun getDigest( + algorithm: String, + data: ByteArray + ): ByteArray { + return kotlin.runCatching { + val messageDigest = MessageDigest.getInstance(algorithm) + messageDigest.digest(data) + }.getOrThrow() + } + + /** + * 散列消息鉴别码 + * 支持DESMAC DESMAC/CFB8 DESedeMAC DESedeMAC/CFB8 DESedeMAC64 DESwithISO9797 HmacMD5 HmacSHA* ISO9797ALG3MAC PBEwithSHA* + * https://developer.android.google.cn/reference/kotlin/javax/crypto/Mac?hl=en + */ + fun getHMac( + algorithm: String, + key: String, + data: String? + ): String { + data ?: return "" + val bytes = getHMac(algorithm, key.toByteArray(), data.toByteArray()) + return StringUtils.byteToHexString(bytes) + } + + fun getHMac( + algorithm: String, + key: ByteArray, + data: ByteArray + ): ByteArray { + return kotlin.runCatching { + val mac= Mac.getInstance(algorithm) + val keySpec = SecretKeySpec(key, algorithm) + mac.init(keySpec) + mac.update(data) + mac.doFinal() + }.getOrThrow() + } + +} 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 9bf400bad..f410075ec 100644 --- a/app/src/main/java/io/legado/app/utils/EncoderUtils.kt +++ b/app/src/main/java/io/legado/app/utils/EncoderUtils.kt @@ -6,6 +6,9 @@ import javax.crypto.Cipher import javax.crypto.spec.IvParameterSpec import javax.crypto.spec.SecretKeySpec +/** + * transformations https://developer.android.google.cn/reference/kotlin/javax/crypto/Cipher?hl=en + */ @Suppress("unused") object EncoderUtils { @@ -47,7 +50,7 @@ object EncoderUtils { * @param data The data. * @param key The key. * @param transformation The name of the transformation, - * 加密算法/加密模式/填充类型, *DES/CBC/PKCS5Padding*. + * 加密算法/加密模式/填充类型, *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 @@ -56,7 +59,7 @@ object EncoderUtils { fun encryptAES2Base64( data: ByteArray?, key: ByteArray?, - transformation: String? = "DES/ECB/PKCS5Padding", + transformation: String? = "AES/ECB/PKCS5Padding", iv: ByteArray? = null ): ByteArray? { return Base64.encode(encryptAES(data, key, transformation, iv), Base64.NO_WRAP) @@ -68,7 +71,7 @@ object EncoderUtils { * @param data The data. * @param key The key. * @param transformation The name of the transformation, - * 加密算法/加密模式/填充类型, *DES/CBC/PKCS5Padding*. + * 加密算法/加密模式/填充类型, *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 @@ -77,7 +80,7 @@ object EncoderUtils { fun encryptAES( data: ByteArray?, key: ByteArray?, - transformation: String? = "DES/ECB/PKCS5Padding", + transformation: String? = "AES/ECB/PKCS5Padding", iv: ByteArray? = null ): ByteArray? { return symmetricTemplate(data, key, "AES", transformation!!, iv, true) @@ -90,7 +93,7 @@ object EncoderUtils { * @param data The data. * @param key The key. * @param transformation The name of the transformation, - * 加密算法/加密模式/填充类型, *DES/CBC/PKCS5Padding*. + * 加密算法/加密模式/填充类型, *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 @@ -99,7 +102,7 @@ object EncoderUtils { fun decryptBase64AES( data: ByteArray?, key: ByteArray?, - transformation: String = "DES/ECB/PKCS5Padding", + transformation: String = "AES/ECB/PKCS5Padding", iv: ByteArray? = null ): ByteArray? { return decryptAES(Base64.decode(data, Base64.NO_WRAP), key, transformation, iv) @@ -111,7 +114,7 @@ object EncoderUtils { * @param data The data. * @param key The key. * @param transformation The name of the transformation, - * 加密算法/加密模式/填充类型, *DES/CBC/PKCS5Padding*. + * 加密算法/加密模式/填充类型, *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 @@ -120,12 +123,185 @@ object EncoderUtils { fun decryptAES( data: ByteArray?, key: ByteArray?, - transformation: String = "DES/ECB/PKCS5Padding", + 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. @@ -166,4 +342,4 @@ object EncoderUtils { } -} \ No newline at end of file +} diff --git a/app/src/main/java/io/legado/app/utils/MD5Utils.kt b/app/src/main/java/io/legado/app/utils/MD5Utils.kt index 0c27d38b3..377f511e7 100644 --- a/app/src/main/java/io/legado/app/utils/MD5Utils.kt +++ b/app/src/main/java/io/legado/app/utils/MD5Utils.kt @@ -1,9 +1,5 @@ package io.legado.app.utils - -import java.security.MessageDigest -import java.security.NoSuchAlgorithmException - /** * 将字符串转化为MD5 */ @@ -11,25 +7,7 @@ import java.security.NoSuchAlgorithmException object MD5Utils { fun md5Encode(str: String?): String { - if (str == null) return "" - var reStr = "" - try { - val md5: MessageDigest = MessageDigest.getInstance("MD5") - val bytes: ByteArray = md5.digest(str.toByteArray()) - val stringBuffer: StringBuilder = StringBuilder() - for (b in bytes) { - val bt: Int = b.toInt() and 0xff - if (bt < 16) { - stringBuffer.append(0) - } - stringBuffer.append(Integer.toHexString(bt)) - } - reStr = stringBuffer.toString() - } catch (e: NoSuchAlgorithmException) { - e.printOnDebug() - } - - return reStr + return DigestUtils.getDigest("MD5", str) } fun md5Encode16(str: String): String {