From 83a9971d661493f08b937cc6576c4604d55dcba7 Mon Sep 17 00:00:00 2001 From: Xwite <1797350009@qq.com> Date: Mon, 23 May 2022 19:51:06 +0800 Subject: [PATCH 1/8] fix(EncoderUtils): change default transformation of AES --- .../java/io/legado/app/utils/EncoderUtils.kt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) 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..94a96a2ad 100644 --- a/app/src/main/java/io/legado/app/utils/EncoderUtils.kt +++ b/app/src/main/java/io/legado/app/utils/EncoderUtils.kt @@ -47,7 +47,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 +56,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 +68,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 +77,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 +90,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 +99,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 +111,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,7 +120,7 @@ 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) From c1fb5b80acafdcfdb8c4b695148c97c173920618 Mon Sep 17 00:00:00 2001 From: Xwite <1797350009@qq.com> Date: Mon, 23 May 2022 21:15:43 +0800 Subject: [PATCH 2/8] feat(EncoderUtils): add DES DESede method --- .../java/io/legado/app/utils/EncoderUtils.kt | 175 +++++++++++++++++- 1 file changed, 174 insertions(+), 1 deletion(-) 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 94a96a2ad..50d67e521 100644 --- a/app/src/main/java/io/legado/app/utils/EncoderUtils.kt +++ b/app/src/main/java/io/legado/app/utils/EncoderUtils.kt @@ -126,6 +126,179 @@ object EncoderUtils { 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 +339,4 @@ object EncoderUtils { } -} \ No newline at end of file +} From c42cf0a59e93eed8475ac8c36a88da4f5f0a3987 Mon Sep 17 00:00:00 2001 From: Xwite <1797350009@qq.com> Date: Mon, 23 May 2022 21:40:38 +0800 Subject: [PATCH 3/8] feat(JsExtensions): use EncoderUtils implement DES/tripleDES bug: iv must be null when mode is `ECB` feat: implements DES docs: update jsHelp.md --- app/src/main/assets/help/jsHelp.md | 10 + .../java/io/legado/app/help/JsExtensions.kt | 171 ++++++++++++------ 2 files changed, 126 insertions(+), 55 deletions(-) diff --git a/app/src/main/assets/help/jsHelp.md b/app/src/main/assets/help/jsHelp.md index 420f45ebe..9e5ba8bc4 100644 --- a/app/src/main/assets/help/jsHelp.md +++ b/app/src/main/assets/help/jsHelp.md @@ -143,6 +143,16 @@ java.aesEncodeToString(str: String, key: String, transformation: String, iv: Str java.aesEncodeToBase64String(str: String, key: String, transformation: String, iv: String) ``` +* DES +``` +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 ``` * @param data 被加密的字符串 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..e42d951b2 100644 --- a/app/src/main/java/io/legado/app/help/JsExtensions.kt +++ b/app/src/main/java/io/legado/app/help/JsExtensions.kt @@ -4,8 +4,6 @@ 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 +297,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 +592,13 @@ interface JsExtensions { return UUID.randomUUID().toString() } + fun androidId(): String { + return AppConst.androidId + } + +//******************对称加密解密************************// + + /////AES /** * AES 解码为 ByteArray * @param str 传入的AES加密的数据 @@ -640,6 +637,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 +775,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 +864,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 +889,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 +915,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 +940,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进制字符串 * @@ -925,4 +978,12 @@ interface JsExtensions { return Base64.encodeToString(DigestUtil.digester(algorithm).digest(data), Base64.NO_WRAP) } + fun md5Encode(str: String): String { + return MD5Utils.md5Encode(str) + } + + fun md5Encode16(str: String): String { + return MD5Utils.md5Encode16(str) + } + } From 9be78577635dded8bd66e723f91cf9f7ae6c6288 Mon Sep 17 00:00:00 2001 From: Xwite <1797350009@qq.com> Date: Mon, 23 May 2022 23:00:35 +0800 Subject: [PATCH 4/8] refactor: implements DigestUtils --- .../java/io/legado/app/help/JsExtensions.kt | 9 ++- .../java/io/legado/app/utils/DigestUtils.kt | 69 +++++++++++++++++++ .../main/java/io/legado/app/utils/MD5Utils.kt | 24 +------ 3 files changed, 74 insertions(+), 28 deletions(-) create mode 100644 app/src/main/java/io/legado/app/utils/DigestUtils.kt 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 e42d951b2..50ec5f276 100644 --- a/app/src/main/java/io/legado/app/help/JsExtensions.kt +++ b/app/src/main/java/io/legado/app/help/JsExtensions.kt @@ -3,7 +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 io.legado.app.constant.AppConst import io.legado.app.constant.AppConst.dateFormat import io.legado.app.constant.AppLog @@ -960,8 +959,8 @@ interface JsExtensions { fun digestHex( data: String, algorithm: String, - ): String? { - return DigestUtil.digester(algorithm).digestHex(data) + ): String { + return DigestUtils.getDigest(algorithm, data) } /** @@ -974,8 +973,8 @@ 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) } fun md5Encode(str: String): String { 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..43597c9c9 --- /dev/null +++ b/app/src/main/java/io/legado/app/utils/DigestUtils.kt @@ -0,0 +1,69 @@ +package io.legado.app.utils + +import java.security.MessageDigest +import java.security.NoSuchAlgorithmException +import javax.crypto.Mac +import javax.crypto.spec.SecretKeySpec + +object DigestUtils { + + /** + * 消息摘要 + * MD2 MD5 SHA-1 SHA-256 SHA-384 SHA-512 + */ + 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 { + lateinit var bytes: ByteArray + try { + val messageDigest = MessageDigest.getInstance(algorithm) + bytes = messageDigest.digest(data) + } catch (e: NoSuchAlgorithmException) { + e.printOnDebug() + } + return bytes + } + + /** + * 散列消息鉴别码 + * HmacMD5 HmacSHA1 HmacSHA224 HmacSHA256 HmacSHA384 HmacSHA512 + */ + 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 { + lateinit var bytes: ByteArray + try { + val mac= Mac.getInstance(algorithm) + val keySpec = SecretKeySpec(key, algorithm) + mac.init(keySpec) + mac.update(data) + bytes = mac.doFinal() + } catch(e: NoSuchAlgorithmException) { + e.printOnDebug() + } + return bytes + } + +} 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 { From 620bd6a7492b2e636955894b3a43b221b27ab42f Mon Sep 17 00:00:00 2001 From: Xwite <1797350009@qq.com> Date: Mon, 23 May 2022 23:44:46 +0800 Subject: [PATCH 5/8] refactor: remove cn.hutool:hutool-crypto for Digest/AES/DES/3DES use `io.legado.app.utils` for dateformat use `java.text.SimpleDateFormat` --- app/build.gradle | 2 +- .../java/io/legado/app/ui/book/remote/RemoteBookAdapter.kt | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 7820fa23c..5594dc4ff 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -249,7 +249,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/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)) } } From 123b9aacf2ac690cd6e6c16c0d4b2ec153e3e568 Mon Sep 17 00:00:00 2001 From: Xwite <1797350009@qq.com> Date: Tue, 24 May 2022 07:07:37 +0800 Subject: [PATCH 6/8] feat(JsExtensions): add Hmac and update docs --- app/src/main/assets/help/jsHelp.md | 32 +++++++++-------- app/src/main/assets/updateLog.md | 4 ++- .../java/io/legado/app/help/JsExtensions.kt | 34 ++++++++++++++++++- 3 files changed, 54 insertions(+), 16 deletions(-) diff --git a/app/src/main/assets/help/jsHelp.md b/app/src/main/assets/help/jsHelp.md index 9e5ba8bc4..d7b312197 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 @@ -130,11 +134,8 @@ deleteFile(path: String) > [常见加密解密算法介绍](https://www.yijiyong.com/algorithm/encryption/01-intro.html) > [相关概念](https://blog.csdn.net/OrangeJack/article/details/82913804) * 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) @@ -144,6 +145,7 @@ 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) @@ -154,23 +156,25 @@ java.desEncodeToString(str: String, key: String, transformation: String, iv: Str 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支持MD2 MD5 SHA-1 SHA-256 SHA-384 SHA-512 +``` +java.digestHex(data: String, algorithm: String,): String? + +java.digestBase64Str(data: String, algorithm: String,): String? +``` +* HMac(散列消息鉴别码) +> algorithm支持HmacMD5 HmacSHA1 HmacSHA224 HmacSHA256 HmacSHA384 HmacSHA512 ``` -* @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 50ec5f276..cad84aba4 100644 --- a/app/src/main/java/io/legado/app/help/JsExtensions.kt +++ b/app/src/main/java/io/legado/app/help/JsExtensions.kt @@ -947,7 +947,7 @@ interface JsExtensions { )?.let { String(it) } } -//******************消息摘要************************// +//******************消息摘要/散列消息鉴别码************************// /** * 生成摘要,并转为16进制字符串 @@ -977,6 +977,38 @@ interface JsExtensions { 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) } From 4c97e17ac4756bd4ee54b1fc629dbee9f1176ed3 Mon Sep 17 00:00:00 2001 From: Xwite <1797350009@qq.com> Date: Tue, 24 May 2022 07:22:23 +0800 Subject: [PATCH 7/8] docs: fix typo and add link --- app/src/main/assets/help/jsHelp.md | 7 ++++--- app/src/main/java/io/legado/app/utils/DigestUtils.kt | 6 ++++-- app/src/main/java/io/legado/app/utils/EncoderUtils.kt | 3 +++ 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/app/src/main/assets/help/jsHelp.md b/app/src/main/assets/help/jsHelp.md index d7b312197..1f91ed457 100644 --- a/app/src/main/assets/help/jsHelp.md +++ b/app/src/main/assets/help/jsHelp.md @@ -132,7 +132,8 @@ 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 ``` @@ -163,14 +164,14 @@ java.tripleDESEncodeBase64Str(data: String,key: String,mode: String,padding: Str java.tripleDESDecodeStr(data: String,key: String,mode: String,padding: String,iv: String): String? ``` * 摘要 -> algorithm支持MD2 MD5 SHA-1 SHA-256 SHA-384 SHA-512 +> 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支持HmacMD5 HmacSHA1 HmacSHA224 HmacSHA256 HmacSHA384 HmacSHA512 +> algorithm支持DESMAC DESMAC/CFB8 DESedeMAC DESedeMAC/CFB8 DESedeMAC64 DESwithISO9797 HmacMD5 HmacSHA* ISO9797ALG3MAC PBEwithSHA* ``` java.HMacHex(data: String, algorithm: String, key: String): String diff --git a/app/src/main/java/io/legado/app/utils/DigestUtils.kt b/app/src/main/java/io/legado/app/utils/DigestUtils.kt index 43597c9c9..f179d3a86 100644 --- a/app/src/main/java/io/legado/app/utils/DigestUtils.kt +++ b/app/src/main/java/io/legado/app/utils/DigestUtils.kt @@ -9,7 +9,8 @@ object DigestUtils { /** * 消息摘要 - * MD2 MD5 SHA-1 SHA-256 SHA-384 SHA-512 + * 支持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, @@ -36,7 +37,8 @@ object DigestUtils { /** * 散列消息鉴别码 - * HmacMD5 HmacSHA1 HmacSHA224 HmacSHA256 HmacSHA384 HmacSHA512 + * 支持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, 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 50d67e521..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 { From 8df2fc3e72385ea2103a8d33c4ca6989ad78ea7e Mon Sep 17 00:00:00 2001 From: Xwite <1797350009@qq.com> Date: Tue, 24 May 2022 10:29:04 +0800 Subject: [PATCH 8/8] fix(DigestUtils): lateinit property not initialize --- .../java/io/legado/app/utils/DigestUtils.kt | 21 ++++++------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/io/legado/app/utils/DigestUtils.kt b/app/src/main/java/io/legado/app/utils/DigestUtils.kt index f179d3a86..b708b770c 100644 --- a/app/src/main/java/io/legado/app/utils/DigestUtils.kt +++ b/app/src/main/java/io/legado/app/utils/DigestUtils.kt @@ -1,7 +1,6 @@ package io.legado.app.utils import java.security.MessageDigest -import java.security.NoSuchAlgorithmException import javax.crypto.Mac import javax.crypto.spec.SecretKeySpec @@ -25,14 +24,10 @@ object DigestUtils { algorithm: String, data: ByteArray ): ByteArray { - lateinit var bytes: ByteArray - try { + return kotlin.runCatching { val messageDigest = MessageDigest.getInstance(algorithm) - bytes = messageDigest.digest(data) - } catch (e: NoSuchAlgorithmException) { - e.printOnDebug() - } - return bytes + messageDigest.digest(data) + }.getOrThrow() } /** @@ -55,17 +50,13 @@ object DigestUtils { key: ByteArray, data: ByteArray ): ByteArray { - lateinit var bytes: ByteArray - try { + return kotlin.runCatching { val mac= Mac.getInstance(algorithm) val keySpec = SecretKeySpec(key, algorithm) mac.init(keySpec) mac.update(data) - bytes = mac.doFinal() - } catch(e: NoSuchAlgorithmException) { - e.printOnDebug() - } - return bytes + mac.doFinal() + }.getOrThrow() } }