+1
-1
@@ -255,7 +255,7 @@ dependencies {
|
|||||||
implementation('com.github.liuyueyi.quick-chinese-transfer:quick-transfer-core:0.2.3')
|
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
|
//renderscriptToolkit
|
||||||
implementation('com.github.android:renderscript-intrinsics-replacement-toolkit:b6363490c3')
|
implementation('com.github.android:renderscript-intrinsics-replacement-toolkit:b6363490c3')
|
||||||
|
|||||||
@@ -54,7 +54,11 @@ java.put(key, value)
|
|||||||
java.ajax(urlStr): String
|
java.ajax(urlStr): String
|
||||||
java.ajaxAll(urlList: Array<String>): Array<StrResponse?>
|
java.ajaxAll(urlList: Array<String>): Array<StrResponse?>
|
||||||
//返回Response 方法body() code() message() header() raw() toString()
|
//返回Response 方法body() code() message() header() raw() toString()
|
||||||
java.connect(urlStr): Response<String>
|
java.connect(urlStr): StrResponse
|
||||||
|
|
||||||
|
java.post(url: String, body: String, headerMap: Map<String, String>): Connection.Response
|
||||||
|
java.get(url: String, headerMap: Map<String, String>): Connection.Response
|
||||||
|
java.head(url: String, headerMap: Map<String, String>): Connection.Response
|
||||||
|
|
||||||
* 使用webView访问网络
|
* 使用webView访问网络
|
||||||
* @param html 直接用webView载入的html, 如果html为空直接访问url
|
* @param html 直接用webView载入的html, 如果html为空直接访问url
|
||||||
@@ -128,13 +132,11 @@ deleteFile(path: String)
|
|||||||
```
|
```
|
||||||
****
|
****
|
||||||
> [常见加密解密算法介绍](https://www.yijiyong.com/algorithm/encryption/01-intro.html)
|
> [常见加密解密算法介绍](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
|
* 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.aesDecodeToString(str: String, key: String, transformation: String, iv: String)
|
||||||
|
|
||||||
java.aesBase64DecodeToString(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)
|
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
|
* 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.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?
|
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
|
||||||
```
|
```
|
||||||
* @param data 被摘要数据
|
java.digestHex(data: String, algorithm: String,): String?
|
||||||
* @param algorithm 签名算法 MD5/SHA1/SHA256/SHA512
|
|
||||||
java.digestHex(data: String,algorithm: String,): String?
|
|
||||||
|
|
||||||
java.digestBase64Str(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*
|
||||||
|
```
|
||||||
|
java.HMacHex(data: String, algorithm: String, key: String): String
|
||||||
|
|
||||||
|
java.HMacBase64(data: String, algorithm: String, key: String): String
|
||||||
```
|
```
|
||||||
* md5
|
* md5
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
|
|
||||||
* 修复部分txt章节结尾乱码bug
|
* 修复部分txt章节结尾乱码bug
|
||||||
* 优化翻页流畅度
|
* 优化翻页流畅度
|
||||||
|
* js添加des HMac
|
||||||
|
* 登录ui用户信息默认加密方式改变,需要重新登录
|
||||||
|
|
||||||
**2022/05/21**
|
**2022/05/21**
|
||||||
|
|
||||||
@@ -322,4 +324,4 @@ eval(String(java.cacheFile(url)))
|
|||||||
**2022/01/01**
|
**2022/01/01**
|
||||||
|
|
||||||
* 修复本地txt问题,不在拷贝到私有目录,可以正常打开
|
* 修复本地txt问题,不在拷贝到私有目录,可以正常打开
|
||||||
* 优化txt目录识别,取目录数量最多的规则
|
* 优化txt目录识别,取目录数量最多的规则
|
||||||
|
|||||||
@@ -3,9 +3,6 @@ package io.legado.app.help
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.util.Base64
|
import android.util.Base64
|
||||||
import androidx.annotation.Keep
|
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
|
||||||
import io.legado.app.constant.AppConst.dateFormat
|
import io.legado.app.constant.AppConst.dateFormat
|
||||||
import io.legado.app.constant.AppLog
|
import io.legado.app.constant.AppLog
|
||||||
@@ -299,14 +296,6 @@ interface JsExtensions {
|
|||||||
return EncoderUtils.base64Encode(str, flags)
|
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()
|
return UUID.randomUUID().toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun androidId(): String {
|
||||||
|
return AppConst.androidId
|
||||||
|
}
|
||||||
|
|
||||||
|
//******************对称加密解密************************//
|
||||||
|
|
||||||
|
/////AES
|
||||||
/**
|
/**
|
||||||
* AES 解码为 ByteArray
|
* AES 解码为 ByteArray
|
||||||
* @param str 传入的AES加密的数据
|
* @param str 传入的AES加密的数据
|
||||||
@@ -640,6 +636,31 @@ interface JsExtensions {
|
|||||||
return aesDecodeToByteArray(str, key, transformation, iv)?.let { String(it) }
|
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
|
* 已经base64的AES 解码为 ByteArray
|
||||||
* @param str 传入的AES Base64加密的数据
|
* @param str 传入的AES Base64加密的数据
|
||||||
@@ -753,35 +774,78 @@ interface JsExtensions {
|
|||||||
return aesEncodeToBase64ByteArray(data, key, transformation, iv)?.let { String(it) }
|
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 key Base64后的密钥
|
||||||
* @param mode 模式
|
* @param mode 模式
|
||||||
* @param padding 补码方式
|
* @param padding 补码方式
|
||||||
* @param iv Base64后的加盐
|
* @param iv Base64后的加盐
|
||||||
* @return 解密后的字符串
|
* @return 加密后的Base64
|
||||||
*/
|
*/
|
||||||
fun aesDecodeArgsBase64Str(
|
fun aesEncodeArgsBase64Str(
|
||||||
data: String,
|
data: String,
|
||||||
key: String,
|
key: String,
|
||||||
mode: String,
|
mode: String,
|
||||||
padding: String,
|
padding: String,
|
||||||
iv: String
|
iv: String
|
||||||
): String? {
|
): String? {
|
||||||
return AES(
|
return EncoderUtils.encryptAES2Base64(
|
||||||
mode,
|
data.encodeToByteArray(),
|
||||||
padding,
|
|
||||||
Base64.decode(key, Base64.NO_WRAP),
|
Base64.decode(key, Base64.NO_WRAP),
|
||||||
|
"AES/${mode}/${padding}",
|
||||||
Base64.decode(iv, Base64.NO_WRAP)
|
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解密
|
* 3DES解密
|
||||||
*
|
*
|
||||||
@@ -799,7 +863,12 @@ interface JsExtensions {
|
|||||||
padding: String,
|
padding: String,
|
||||||
iv: String
|
iv: String
|
||||||
): 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,
|
padding: String,
|
||||||
iv: String
|
iv: String
|
||||||
): String? {
|
): String? {
|
||||||
return DESede(
|
return EncoderUtils.decryptDESede(
|
||||||
mode,
|
data.encodeToByteArray(),
|
||||||
padding,
|
|
||||||
Base64.decode(key, Base64.NO_WRAP),
|
Base64.decode(key, Base64.NO_WRAP),
|
||||||
|
"DESede/${mode}/${padding}",
|
||||||
Base64.decode(iv, Base64.NO_WRAP)
|
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
|
* 3DES加密并转为Base64
|
||||||
@@ -869,7 +914,12 @@ interface JsExtensions {
|
|||||||
padding: String,
|
padding: String,
|
||||||
iv: String
|
iv: String
|
||||||
): 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,
|
padding: String,
|
||||||
iv: String
|
iv: String
|
||||||
): String? {
|
): String? {
|
||||||
return DESede(
|
return EncoderUtils.encryptDESede2Base64(
|
||||||
mode,
|
data.encodeToByteArray(),
|
||||||
padding,
|
|
||||||
Base64.decode(key, Base64.NO_WRAP),
|
Base64.decode(key, Base64.NO_WRAP),
|
||||||
|
"DESede/${mode}/${padding}",
|
||||||
Base64.decode(iv, Base64.NO_WRAP)
|
Base64.decode(iv, Base64.NO_WRAP)
|
||||||
).encryptBase64(data)
|
)?.let { String(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//******************消息摘要/散列消息鉴别码************************//
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成摘要,并转为16进制字符串
|
* 生成摘要,并转为16进制字符串
|
||||||
*
|
*
|
||||||
@@ -907,8 +959,8 @@ interface JsExtensions {
|
|||||||
fun digestHex(
|
fun digestHex(
|
||||||
data: String,
|
data: String,
|
||||||
algorithm: String,
|
algorithm: String,
|
||||||
): String? {
|
): String {
|
||||||
return DigestUtil.digester(algorithm).digestHex(data)
|
return DigestUtils.getDigest(algorithm, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -921,8 +973,48 @@ interface JsExtensions {
|
|||||||
fun digestBase64Str(
|
fun digestBase64Str(
|
||||||
data: String,
|
data: String,
|
||||||
algorithm: String,
|
algorithm: String,
|
||||||
): String? {
|
): String {
|
||||||
return Base64.encodeToString(DigestUtil.digester(algorithm).digest(data), Base64.NO_WRAP)
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,12 @@ package io.legado.app.ui.book.remote
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import cn.hutool.core.date.LocalDateTimeUtil
|
|
||||||
import io.legado.app.base.adapter.ItemViewHolder
|
import io.legado.app.base.adapter.ItemViewHolder
|
||||||
import io.legado.app.base.adapter.RecyclerAdapter
|
import io.legado.app.base.adapter.RecyclerAdapter
|
||||||
import io.legado.app.databinding.ItemRemoteBookBinding
|
import io.legado.app.databinding.ItemRemoteBookBinding
|
||||||
import io.legado.app.utils.ConvertUtils
|
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(".")
|
tvName.text = item.filename.substringBeforeLast(".")
|
||||||
tvContentType.text = item.contentType
|
tvContentType.text = item.contentType
|
||||||
tvSize.text = ConvertUtils.formatFileSize(item.size)
|
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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -6,6 +6,9 @@ import javax.crypto.Cipher
|
|||||||
import javax.crypto.spec.IvParameterSpec
|
import javax.crypto.spec.IvParameterSpec
|
||||||
import javax.crypto.spec.SecretKeySpec
|
import javax.crypto.spec.SecretKeySpec
|
||||||
|
|
||||||
|
/**
|
||||||
|
* transformations https://developer.android.google.cn/reference/kotlin/javax/crypto/Cipher?hl=en
|
||||||
|
*/
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
object EncoderUtils {
|
object EncoderUtils {
|
||||||
|
|
||||||
@@ -47,7 +50,7 @@ object EncoderUtils {
|
|||||||
* @param data The data.
|
* @param data The data.
|
||||||
* @param key The key.
|
* @param key The key.
|
||||||
* @param transformation The name of the transformation,
|
* @param transformation The name of the transformation,
|
||||||
* 加密算法/加密模式/填充类型, *DES/CBC/PKCS5Padding*.
|
* 加密算法/加密模式/填充类型, *AES/CBC/PKCS5Padding*.
|
||||||
* @param iv The buffer with the IV. The contents of the
|
* @param iv The buffer with the IV. The contents of the
|
||||||
* buffer are copied to protect against subsequent modification.
|
* buffer are copied to protect against subsequent modification.
|
||||||
* @return the Base64-encode bytes of AES encryption
|
* @return the Base64-encode bytes of AES encryption
|
||||||
@@ -56,7 +59,7 @@ object EncoderUtils {
|
|||||||
fun encryptAES2Base64(
|
fun encryptAES2Base64(
|
||||||
data: ByteArray?,
|
data: ByteArray?,
|
||||||
key: ByteArray?,
|
key: ByteArray?,
|
||||||
transformation: String? = "DES/ECB/PKCS5Padding",
|
transformation: String? = "AES/ECB/PKCS5Padding",
|
||||||
iv: ByteArray? = null
|
iv: ByteArray? = null
|
||||||
): ByteArray? {
|
): ByteArray? {
|
||||||
return Base64.encode(encryptAES(data, key, transformation, iv), Base64.NO_WRAP)
|
return Base64.encode(encryptAES(data, key, transformation, iv), Base64.NO_WRAP)
|
||||||
@@ -68,7 +71,7 @@ object EncoderUtils {
|
|||||||
* @param data The data.
|
* @param data The data.
|
||||||
* @param key The key.
|
* @param key The key.
|
||||||
* @param transformation The name of the transformation,
|
* @param transformation The name of the transformation,
|
||||||
* 加密算法/加密模式/填充类型, *DES/CBC/PKCS5Padding*.
|
* 加密算法/加密模式/填充类型, *AES/CBC/PKCS5Padding*.
|
||||||
* @param iv The buffer with the IV. The contents of the
|
* @param iv The buffer with the IV. The contents of the
|
||||||
* buffer are copied to protect against subsequent modification.
|
* buffer are copied to protect against subsequent modification.
|
||||||
* @return the bytes of AES encryption
|
* @return the bytes of AES encryption
|
||||||
@@ -77,7 +80,7 @@ object EncoderUtils {
|
|||||||
fun encryptAES(
|
fun encryptAES(
|
||||||
data: ByteArray?,
|
data: ByteArray?,
|
||||||
key: ByteArray?,
|
key: ByteArray?,
|
||||||
transformation: String? = "DES/ECB/PKCS5Padding",
|
transformation: String? = "AES/ECB/PKCS5Padding",
|
||||||
iv: ByteArray? = null
|
iv: ByteArray? = null
|
||||||
): ByteArray? {
|
): ByteArray? {
|
||||||
return symmetricTemplate(data, key, "AES", transformation!!, iv, true)
|
return symmetricTemplate(data, key, "AES", transformation!!, iv, true)
|
||||||
@@ -90,7 +93,7 @@ object EncoderUtils {
|
|||||||
* @param data The data.
|
* @param data The data.
|
||||||
* @param key The key.
|
* @param key The key.
|
||||||
* @param transformation The name of the transformation,
|
* @param transformation The name of the transformation,
|
||||||
* 加密算法/加密模式/填充类型, *DES/CBC/PKCS5Padding*.
|
* 加密算法/加密模式/填充类型, *AES/CBC/PKCS5Padding*.
|
||||||
* @param iv The buffer with the IV. The contents of the
|
* @param iv The buffer with the IV. The contents of the
|
||||||
* buffer are copied to protect against subsequent modification.
|
* buffer are copied to protect against subsequent modification.
|
||||||
* @return the bytes of AES decryption for Base64-encode bytes
|
* @return the bytes of AES decryption for Base64-encode bytes
|
||||||
@@ -99,7 +102,7 @@ object EncoderUtils {
|
|||||||
fun decryptBase64AES(
|
fun decryptBase64AES(
|
||||||
data: ByteArray?,
|
data: ByteArray?,
|
||||||
key: ByteArray?,
|
key: ByteArray?,
|
||||||
transformation: String = "DES/ECB/PKCS5Padding",
|
transformation: String = "AES/ECB/PKCS5Padding",
|
||||||
iv: ByteArray? = null
|
iv: ByteArray? = null
|
||||||
): ByteArray? {
|
): ByteArray? {
|
||||||
return decryptAES(Base64.decode(data, Base64.NO_WRAP), key, transformation, iv)
|
return decryptAES(Base64.decode(data, Base64.NO_WRAP), key, transformation, iv)
|
||||||
@@ -111,7 +114,7 @@ object EncoderUtils {
|
|||||||
* @param data The data.
|
* @param data The data.
|
||||||
* @param key The key.
|
* @param key The key.
|
||||||
* @param transformation The name of the transformation,
|
* @param transformation The name of the transformation,
|
||||||
* 加密算法/加密模式/填充类型, *DES/CBC/PKCS5Padding*.
|
* 加密算法/加密模式/填充类型, *AES/CBC/PKCS5Padding*.
|
||||||
* @param iv The buffer with the IV. The contents of the
|
* @param iv The buffer with the IV. The contents of the
|
||||||
* buffer are copied to protect against subsequent modification.
|
* buffer are copied to protect against subsequent modification.
|
||||||
* @return the bytes of AES decryption
|
* @return the bytes of AES decryption
|
||||||
@@ -120,12 +123,185 @@ object EncoderUtils {
|
|||||||
fun decryptAES(
|
fun decryptAES(
|
||||||
data: ByteArray?,
|
data: ByteArray?,
|
||||||
key: ByteArray?,
|
key: ByteArray?,
|
||||||
transformation: String = "DES/ECB/PKCS5Padding",
|
transformation: String = "AES/ECB/PKCS5Padding",
|
||||||
iv: ByteArray? = null
|
iv: ByteArray? = null
|
||||||
): ByteArray? {
|
): ByteArray? {
|
||||||
return symmetricTemplate(data, key, "AES", transformation, iv, false)
|
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.
|
* Return the bytes of symmetric encryption or decryption.
|
||||||
@@ -166,4 +342,4 @@ object EncoderUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
package io.legado.app.utils
|
package io.legado.app.utils
|
||||||
|
|
||||||
|
|
||||||
import java.security.MessageDigest
|
|
||||||
import java.security.NoSuchAlgorithmException
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将字符串转化为MD5
|
* 将字符串转化为MD5
|
||||||
*/
|
*/
|
||||||
@@ -11,25 +7,7 @@ import java.security.NoSuchAlgorithmException
|
|||||||
object MD5Utils {
|
object MD5Utils {
|
||||||
|
|
||||||
fun md5Encode(str: String?): String {
|
fun md5Encode(str: String?): String {
|
||||||
if (str == null) return ""
|
return DigestUtils.getDigest("MD5", str)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun md5Encode16(str: String): String {
|
fun md5Encode16(str: String): String {
|
||||||
|
|||||||
Reference in New Issue
Block a user