parent
f5a5d76b1e
commit
b9a66814c1
@ -0,0 +1,78 @@ |
|||||||
|
@file:Suppress("unused") |
||||||
|
|
||||||
|
package xyz.fycz.myreader.greendao.service |
||||||
|
|
||||||
|
import android.text.TextUtils |
||||||
|
import xyz.fycz.myreader.greendao.DbManager |
||||||
|
import xyz.fycz.myreader.greendao.entity.CookieBean |
||||||
|
import xyz.fycz.myreader.greendao.service.api.CookieManager |
||||||
|
import xyz.fycz.myreader.util.utils.NetworkUtils |
||||||
|
|
||||||
|
object CookieStore : CookieManager { |
||||||
|
|
||||||
|
override fun setCookie(url: String, cookie: String?) { |
||||||
|
val cookieBean = CookieBean(NetworkUtils.getSubDomain(url), cookie ?: "") |
||||||
|
DbManager.getDaoSession().cookieBeanDao.insertOrReplace(cookieBean) |
||||||
|
} |
||||||
|
|
||||||
|
override fun replaceCookie(url: String, cookie: String) { |
||||||
|
if (TextUtils.isEmpty(url) || TextUtils.isEmpty(cookie)) { |
||||||
|
return |
||||||
|
} |
||||||
|
val oldCookie = getCookie(url) |
||||||
|
if (TextUtils.isEmpty(oldCookie)) { |
||||||
|
setCookie(url, cookie) |
||||||
|
} else { |
||||||
|
val cookieMap = cookieToMap(oldCookie) |
||||||
|
cookieMap.putAll(cookieToMap(cookie)) |
||||||
|
val newCookie = mapToCookie(cookieMap) |
||||||
|
setCookie(url, newCookie) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
override fun getCookie(url: String): String { |
||||||
|
val cookieBean = DbManager.getDaoSession().cookieBeanDao.load(NetworkUtils.getSubDomain(url)) |
||||||
|
return cookieBean?.cookie ?: "" |
||||||
|
} |
||||||
|
|
||||||
|
override fun removeCookie(url: String) { |
||||||
|
DbManager.getDaoSession().cookieBeanDao.deleteByKey(NetworkUtils.getSubDomain(url)) |
||||||
|
} |
||||||
|
|
||||||
|
override fun cookieToMap(cookie: String): MutableMap<String, String> { |
||||||
|
val cookieMap = mutableMapOf<String, String>() |
||||||
|
if (cookie.isBlank()) { |
||||||
|
return cookieMap |
||||||
|
} |
||||||
|
val pairArray = cookie.split(";".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() |
||||||
|
for (pair in pairArray) { |
||||||
|
val pairs = pair.split("=".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() |
||||||
|
if (pairs.size == 1) { |
||||||
|
continue |
||||||
|
} |
||||||
|
val key = pairs[0].trim { it <= ' ' } |
||||||
|
val value = pairs[1] |
||||||
|
if (value.isNotBlank() || value.trim { it <= ' ' } == "null") { |
||||||
|
cookieMap[key] = value.trim { it <= ' ' } |
||||||
|
} |
||||||
|
} |
||||||
|
return cookieMap |
||||||
|
} |
||||||
|
|
||||||
|
override fun mapToCookie(cookieMap: Map<String, String>?): String? { |
||||||
|
if (cookieMap == null || cookieMap.isEmpty()) { |
||||||
|
return null |
||||||
|
} |
||||||
|
val builder = StringBuilder() |
||||||
|
for (key in cookieMap.keys) { |
||||||
|
val value = cookieMap[key] |
||||||
|
if (value?.isNotBlank() == true) { |
||||||
|
builder.append(key) |
||||||
|
.append("=") |
||||||
|
.append(value) |
||||||
|
.append(";") |
||||||
|
} |
||||||
|
} |
||||||
|
return builder.deleteCharAt(builder.lastIndexOf(";")).toString() |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,28 @@ |
|||||||
|
package xyz.fycz.myreader.greendao.service.api |
||||||
|
|
||||||
|
interface CookieManager { |
||||||
|
|
||||||
|
/** |
||||||
|
* 保存cookie |
||||||
|
*/ |
||||||
|
fun setCookie(url: String, cookie: String?) |
||||||
|
|
||||||
|
/** |
||||||
|
* 替换cookie |
||||||
|
*/ |
||||||
|
fun replaceCookie(url: String, cookie: String) |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取cookie |
||||||
|
*/ |
||||||
|
fun getCookie(url: String): String |
||||||
|
|
||||||
|
/** |
||||||
|
* 移除cookie |
||||||
|
*/ |
||||||
|
fun removeCookie(url: String) |
||||||
|
|
||||||
|
fun cookieToMap(cookie: String): MutableMap<String, String> |
||||||
|
|
||||||
|
fun mapToCookie(cookieMap: Map<String, String>?): String? |
||||||
|
} |
@ -0,0 +1,365 @@ |
|||||||
|
package xyz.fycz.myreader.util.help |
||||||
|
|
||||||
|
import android.util.Base64 |
||||||
|
import android.util.Log |
||||||
|
import androidx.annotation.Keep |
||||||
|
import org.jsoup.Connection |
||||||
|
import org.jsoup.Jsoup |
||||||
|
import xyz.fycz.myreader.greendao.service.CookieStore |
||||||
|
import xyz.fycz.myreader.model.third2.analyzeRule.AnalyzeUrl |
||||||
|
import xyz.fycz.myreader.util.ZipUtils |
||||||
|
import xyz.fycz.myreader.util.utils.* |
||||||
|
import java.io.File |
||||||
|
import java.io.IOException |
||||||
|
import java.net.URLEncoder |
||||||
|
import java.text.SimpleDateFormat |
||||||
|
import java.util.* |
||||||
|
|
||||||
|
/** |
||||||
|
* @author fengyue |
||||||
|
* @date 2021/5/15 19:26 |
||||||
|
*/ |
||||||
|
@Keep |
||||||
|
@Suppress("unused") |
||||||
|
interface JSExtensions { |
||||||
|
/** |
||||||
|
* js实现跨域访问,不能删 |
||||||
|
*/ |
||||||
|
fun ajax(urlStr: String?): String? { |
||||||
|
return try { |
||||||
|
val analyzeUrl = AnalyzeUrl(urlStr) |
||||||
|
OkHttpUtils.getStrResponse(analyzeUrl).blockingFirst().body() |
||||||
|
} catch (e: Exception) { |
||||||
|
e.localizedMessage |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* js实现压缩文件解压 |
||||||
|
*/ |
||||||
|
fun unzipFile(zipPath: String): String { |
||||||
|
if (zipPath.isEmpty()) return "" |
||||||
|
val unzipPath = FileUtils.getCachePath() + File.separator + FileUtils.getNameExcludeExtension(zipPath) |
||||||
|
FileUtils.deleteFile(unzipPath) |
||||||
|
val zipFile = FileUtils.getFile(zipPath) |
||||||
|
val unzipFolder = FileUtils.getFolder(unzipPath) |
||||||
|
ZipUtils.unzipFile(zipFile, unzipFolder) |
||||||
|
FileUtils.deleteFile(zipPath) |
||||||
|
return unzipPath |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* js实现文件夹内所有文件读取 |
||||||
|
*/ |
||||||
|
fun getTxtInFolder(unzipPath: String): String { |
||||||
|
if (unzipPath.isEmpty()) return "" |
||||||
|
val unzipFolder = FileUtils.getFolder(unzipPath) |
||||||
|
val contents = StringBuilder() |
||||||
|
unzipFolder.listFiles().let { |
||||||
|
if (it != null) { |
||||||
|
for (f in it) { |
||||||
|
val charsetName = FileUtils.getFileCharset(f) |
||||||
|
contents.append(String(f.readBytes(), charset(charsetName))) |
||||||
|
.append("\n") |
||||||
|
} |
||||||
|
contents.deleteCharAt(contents.length - 1) |
||||||
|
} |
||||||
|
} |
||||||
|
FileUtils.deleteFile(unzipPath) |
||||||
|
return contents.toString() |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* js实现重定向拦截,不能删 |
||||||
|
*/ |
||||||
|
@Throws(IOException::class) |
||||||
|
operator fun get(urlStr: String?, headers: Map<String?, String?>?): Connection.Response? { |
||||||
|
return Jsoup.connect(urlStr) |
||||||
|
.sslSocketFactory(SSLSocketClient.createSSLSocketFactory()) |
||||||
|
.ignoreContentType(true) |
||||||
|
.followRedirects(false) |
||||||
|
.headers(headers) |
||||||
|
.method(Connection.Method.GET) |
||||||
|
.execute() |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* js实现重定向拦截,不能删 |
||||||
|
*/ |
||||||
|
@Throws(IOException::class) |
||||||
|
fun post( |
||||||
|
urlStr: String?, |
||||||
|
body: String?, |
||||||
|
headers: Map<String?, String?>? |
||||||
|
): Connection.Response? { |
||||||
|
return Jsoup.connect(urlStr) |
||||||
|
.sslSocketFactory(SSLSocketClient.createSSLSocketFactory()) |
||||||
|
.ignoreContentType(true) |
||||||
|
.followRedirects(false) |
||||||
|
.requestBody(body) |
||||||
|
.headers(headers) |
||||||
|
.method(Connection.Method.POST) |
||||||
|
.execute() |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
*js实现读取cookie |
||||||
|
*/ |
||||||
|
fun getCookie(tag: String, key: String? = null): String { |
||||||
|
val cookie = CookieStore.getCookie(tag) |
||||||
|
val cookieMap = CookieStore.cookieToMap(cookie) |
||||||
|
return if (key != null) { |
||||||
|
cookieMap[key] ?: "" |
||||||
|
} else { |
||||||
|
cookie |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* js实现解码,不能删 |
||||||
|
*/ |
||||||
|
fun base64Decode(str: String): String { |
||||||
|
return EncoderUtils.base64Decode(str, Base64.NO_WRAP) |
||||||
|
} |
||||||
|
|
||||||
|
fun base64Decode(str: String, flags: Int): String { |
||||||
|
return EncoderUtils.base64Decode(str, flags) |
||||||
|
} |
||||||
|
|
||||||
|
fun base64DecodeToByteArray(str: String?): ByteArray? { |
||||||
|
if (str.isNullOrBlank()) { |
||||||
|
return null |
||||||
|
} |
||||||
|
return Base64.decode(str, Base64.DEFAULT) |
||||||
|
} |
||||||
|
|
||||||
|
fun base64DecodeToByteArray(str: String?, flags: Int): ByteArray? { |
||||||
|
if (str.isNullOrBlank()) { |
||||||
|
return null |
||||||
|
} |
||||||
|
return Base64.decode(str, flags) |
||||||
|
} |
||||||
|
|
||||||
|
fun base64Encode(str: String): String? { |
||||||
|
return EncoderUtils.base64Encode(str, Base64.NO_WRAP) |
||||||
|
} |
||||||
|
|
||||||
|
fun base64Encode(str: String, flags: Int): String? { |
||||||
|
return EncoderUtils.base64Encode(str, flags) |
||||||
|
} |
||||||
|
|
||||||
|
fun md5Encode(str: String): String { |
||||||
|
return MD5Utils.md5Encode(str) |
||||||
|
} |
||||||
|
|
||||||
|
fun md5Encode16(str: String): String { |
||||||
|
return MD5Utils.md5Encode16(str) |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 时间格式化 |
||||||
|
*/ |
||||||
|
fun timeFormat(time: Long): String { |
||||||
|
val sdf = SimpleDateFormat("yyyy/MM/dd HH:mm") |
||||||
|
return sdf.format(Date(time)) |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* utf8编码转gbk编码 |
||||||
|
*/ |
||||||
|
fun utf8ToGbk(str: String): String { |
||||||
|
val utf8 = String(str.toByteArray(charset("UTF-8"))) |
||||||
|
val unicode = String(utf8.toByteArray(), charset("UTF-8")) |
||||||
|
return String(unicode.toByteArray(charset("GBK"))) |
||||||
|
} |
||||||
|
|
||||||
|
fun encodeURI(str: String): String { |
||||||
|
return try { |
||||||
|
URLEncoder.encode(str, "UTF-8") |
||||||
|
} catch (e: Exception) { |
||||||
|
"" |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
fun encodeURI(str: String, enc: String): String { |
||||||
|
return try { |
||||||
|
URLEncoder.encode(str, enc) |
||||||
|
} catch (e: Exception) { |
||||||
|
"" |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
fun htmlFormat(str: String): String { |
||||||
|
return StringUtils.formatHtml(str) |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 读取本地文件 |
||||||
|
*/ |
||||||
|
fun readFile(path: String): ByteArray { |
||||||
|
return File(path).readBytes() |
||||||
|
} |
||||||
|
|
||||||
|
fun readTxtFile(path: String): String { |
||||||
|
val f = File(path) |
||||||
|
val charsetName = FileUtils.getFileCharset(f) |
||||||
|
return String(f.readBytes(), charset(charsetName)) |
||||||
|
} |
||||||
|
|
||||||
|
fun readTxtFile(path: String, charsetName: String): String { |
||||||
|
return String(File(path).readBytes(), charset(charsetName)) |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 输出调试日志 |
||||||
|
*/ |
||||||
|
fun log(msg: String): String { |
||||||
|
Log.d("JS", msg) |
||||||
|
return msg |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 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 EncoderUtils.decryptAES( |
||||||
|
data = str.encodeToByteArray(), |
||||||
|
key = key.encodeToByteArray(), |
||||||
|
transformation, |
||||||
|
iv.encodeToByteArray() |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 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) } |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 已经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 EncoderUtils.decryptBase64AES( |
||||||
|
data = str.encodeToByteArray(), |
||||||
|
key = key.encodeToByteArray(), |
||||||
|
transformation, |
||||||
|
iv.encodeToByteArray() |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 已经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 EncoderUtils.encryptAES( |
||||||
|
data.encodeToByteArray(), |
||||||
|
key = key.encodeToByteArray(), |
||||||
|
transformation, |
||||||
|
iv.encodeToByteArray() |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 加密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 EncoderUtils.encryptAES2Base64( |
||||||
|
data.encodeToByteArray(), |
||||||
|
key = key.encodeToByteArray(), |
||||||
|
transformation, |
||||||
|
iv.encodeToByteArray() |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 加密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) } |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,141 @@ |
|||||||
|
package xyz.fycz.myreader.util.utils |
||||||
|
|
||||||
|
import android.util.Base64 |
||||||
|
import java.security.spec.AlgorithmParameterSpec |
||||||
|
import javax.crypto.Cipher |
||||||
|
import javax.crypto.spec.IvParameterSpec |
||||||
|
import javax.crypto.spec.SecretKeySpec |
||||||
|
|
||||||
|
@Suppress("unused") |
||||||
|
object EncoderUtils { |
||||||
|
@JvmOverloads |
||||||
|
fun base64Decode(str: String, flags: Int = Base64.DEFAULT): String { |
||||||
|
val bytes = Base64.decode(str, flags) |
||||||
|
return String(bytes) |
||||||
|
} |
||||||
|
|
||||||
|
@JvmOverloads |
||||||
|
fun base64Encode(str: String, flags: Int = Base64.NO_WRAP): String? { |
||||||
|
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, e.g., *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 |
||||||
|
*/ |
||||||
|
fun encryptAES2Base64( |
||||||
|
data: ByteArray?, |
||||||
|
key: ByteArray?, |
||||||
|
transformation: String?, |
||||||
|
iv: ByteArray? |
||||||
|
): 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, e.g., *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 |
||||||
|
*/ |
||||||
|
fun encryptAES( |
||||||
|
data: ByteArray?, |
||||||
|
key: ByteArray?, |
||||||
|
transformation: String?, |
||||||
|
iv: ByteArray? |
||||||
|
): 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, e.g., *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 |
||||||
|
*/ |
||||||
|
fun decryptBase64AES( |
||||||
|
data: ByteArray?, |
||||||
|
key: ByteArray?, |
||||||
|
transformation: String?, |
||||||
|
iv: ByteArray? |
||||||
|
): 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, e.g., *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 |
||||||
|
*/ |
||||||
|
fun decryptAES( |
||||||
|
data: ByteArray?, |
||||||
|
key: ByteArray?, |
||||||
|
transformation: String?, |
||||||
|
iv: ByteArray? |
||||||
|
): ByteArray? { |
||||||
|
return symmetricTemplate(data, key, "AES", 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, e.g., <i>DES/CBC/PKCS5Padding</i>. |
||||||
|
* @param isEncrypt True to encrypt, false otherwise. |
||||||
|
* @return the bytes of symmetric encryption or decryption |
||||||
|
*/ |
||||||
|
|
||||||
|
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 try { |
||||||
|
val keySpec = SecretKeySpec(key, algorithm) |
||||||
|
val cipher = Cipher.getInstance(transformation) |
||||||
|
if (iv == null || iv.isEmpty()) { |
||||||
|
cipher.init(if (isEncrypt) Cipher.ENCRYPT_MODE else Cipher.DECRYPT_MODE, keySpec) |
||||||
|
} else { |
||||||
|
val params: AlgorithmParameterSpec = IvParameterSpec(iv) |
||||||
|
cipher.init( |
||||||
|
if (isEncrypt) Cipher.ENCRYPT_MODE else Cipher.DECRYPT_MODE, |
||||||
|
keySpec, |
||||||
|
params |
||||||
|
) |
||||||
|
} |
||||||
|
cipher.doFinal(data) |
||||||
|
} catch (e: Throwable) { |
||||||
|
e.printStackTrace() |
||||||
|
null |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
@ -1,73 +0,0 @@ |
|||||||
package xyz.fycz.myreader.util.utils; |
|
||||||
|
|
||||||
import java.io.File; |
|
||||||
import java.io.FileInputStream; |
|
||||||
import java.math.BigInteger; |
|
||||||
import java.security.MessageDigest; |
|
||||||
import java.security.NoSuchAlgorithmException; |
|
||||||
|
|
||||||
import xyz.fycz.myreader.util.IOUtils; |
|
||||||
|
|
||||||
|
|
||||||
public class MD5Utils { |
|
||||||
|
|
||||||
public static String strToMd5By32(String str) { |
|
||||||
String reStr = null; |
|
||||||
try { |
|
||||||
MessageDigest md5 = MessageDigest.getInstance("MD5"); |
|
||||||
byte[] bytes = md5.digest(str.getBytes()); |
|
||||||
StringBuilder stringBuffer = new StringBuilder(); |
|
||||||
for (byte b : bytes) { |
|
||||||
int bt = b & 0xff; |
|
||||||
if (bt < 16) { |
|
||||||
stringBuffer.append(0); |
|
||||||
} |
|
||||||
stringBuffer.append(Integer.toHexString(bt)); |
|
||||||
} |
|
||||||
reStr = stringBuffer.toString(); |
|
||||||
} catch (NoSuchAlgorithmException e) { |
|
||||||
e.printStackTrace(); |
|
||||||
} |
|
||||||
return reStr; |
|
||||||
} |
|
||||||
|
|
||||||
public static String strToMd5By16(String str) { |
|
||||||
String reStr = strToMd5By32(str); |
|
||||||
if (reStr != null) { |
|
||||||
reStr = reStr.substring(8, 24); |
|
||||||
} |
|
||||||
return reStr; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 获取单个文件的MD5值 |
|
||||||
* @param file 文件 |
|
||||||
* @param radix 位 16 32 64 |
|
||||||
* |
|
||||||
* @return |
|
||||||
*/ |
|
||||||
|
|
||||||
public static String getFileMD5s(File file, int radix) { |
|
||||||
if (!file.isFile()) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
MessageDigest digest = null; |
|
||||||
FileInputStream in = null; |
|
||||||
byte[] buffer = new byte[1024]; |
|
||||||
int len; |
|
||||||
try { |
|
||||||
digest = MessageDigest.getInstance("MD5"); |
|
||||||
in = new FileInputStream(file); |
|
||||||
while ((len = in.read(buffer, 0, 1024)) != -1) { |
|
||||||
digest.update(buffer, 0, len); |
|
||||||
} |
|
||||||
} catch (Exception e) { |
|
||||||
e.printStackTrace(); |
|
||||||
return null; |
|
||||||
}finally { |
|
||||||
IOUtils.close(in); |
|
||||||
} |
|
||||||
BigInteger bigInt = new BigInteger(1, digest.digest()); |
|
||||||
return bigInt.toString(radix); |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,76 @@ |
|||||||
|
package xyz.fycz.myreader.util.utils |
||||||
|
|
||||||
|
import xyz.fycz.myreader.util.IOUtils |
||||||
|
import java.io.File |
||||||
|
import java.io.FileInputStream |
||||||
|
import java.math.BigInteger |
||||||
|
import java.security.MessageDigest |
||||||
|
import java.security.NoSuchAlgorithmException |
||||||
|
import kotlin.experimental.and |
||||||
|
|
||||||
|
/** |
||||||
|
* 将字符串转化为MD5 |
||||||
|
*/ |
||||||
|
@Suppress("unused") |
||||||
|
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.printStackTrace() |
||||||
|
} |
||||||
|
|
||||||
|
return reStr |
||||||
|
} |
||||||
|
|
||||||
|
fun md5Encode16(str: String): String { |
||||||
|
var reStr = md5Encode(str) |
||||||
|
reStr = reStr.substring(8, 24) |
||||||
|
return reStr |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 获取单个文件的MD5值 |
||||||
|
* @param file 文件 |
||||||
|
* @param radix 位 16 32 64 |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
fun getFileMD5s(file: File, radix: Int): String? { |
||||||
|
if (!file.isFile) { |
||||||
|
return null |
||||||
|
} |
||||||
|
var digest: MessageDigest? = null |
||||||
|
var `in`: FileInputStream? = null |
||||||
|
val buffer = ByteArray(1024) |
||||||
|
var len: Int |
||||||
|
try { |
||||||
|
digest = MessageDigest.getInstance("MD5") |
||||||
|
`in` = FileInputStream(file) |
||||||
|
while (`in`.read(buffer, 0, 1024).also { len = it } != -1) { |
||||||
|
digest.update(buffer, 0, len) |
||||||
|
} |
||||||
|
} catch (e: Exception) { |
||||||
|
e.printStackTrace() |
||||||
|
return null |
||||||
|
} finally { |
||||||
|
IOUtils.close(`in`) |
||||||
|
} |
||||||
|
val bigInt = BigInteger(1, digest!!.digest()) |
||||||
|
return bigInt.toString(radix) |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue