From 74b67372c657a2555efd0f887c82d02a0c3506de Mon Sep 17 00:00:00 2001 From: zhangmengxiong Date: Mon, 16 May 2022 20:04:24 +0800 Subject: [PATCH 1/5] 666 --- .../main/java/com/mx/keyvalue/MXKeyValue.kt | 25 +++++--- .../java/com/mx/keyvalue/base/IMXKeyValue.kt | 3 +- .../java/com/mx/keyvalue/db/MXDBKeyValue.kt | 23 ++++++- .../java/com/mx/keyvalue/secret/IMXSecret.kt | 4 +- .../com/mx/keyvalue/secret/MXAESSecret.kt | 63 +++++++++++-------- .../java/com/mx/keyvalue/secret/MXNoSecret.kt | 4 +- .../java/com/mx/keyvalue/utils/MXUtils.kt | 10 +-- app/src/main/res/layout/activity_main.xml | 7 +++ 8 files changed, 95 insertions(+), 44 deletions(-) diff --git a/LibKeyValue/src/main/java/com/mx/keyvalue/MXKeyValue.kt b/LibKeyValue/src/main/java/com/mx/keyvalue/MXKeyValue.kt index eb9bee9..76ec80c 100644 --- a/LibKeyValue/src/main/java/com/mx/keyvalue/MXKeyValue.kt +++ b/LibKeyValue/src/main/java/com/mx/keyvalue/MXKeyValue.kt @@ -20,8 +20,9 @@ class MXKeyValue( fun cloneFromSharedPreferences(name: String) { val sp = context.getSharedPreferences(name, Context.MODE_PRIVATE) for (entry in sp.all) { - if (entry.value != null) { - dbKeyValue.set(entry.key, entry.value?.toString(), null) + val value = entry.value?.toString() + if (value != null) { + dbKeyValue.set(entry.key, value, null) } } } @@ -30,18 +31,26 @@ class MXKeyValue( * 设置KV */ fun set(key: String, value: String?, expire_time: Long? = null): Boolean { - val key = key.trim() - if (key.isBlank()) return false - return dbKeyValue.set(key, value?.trim(), expire_time) + val key_trim = key.trim() + if (key_trim.isBlank()) return false + return if (value != null) { + dbKeyValue.set(key_trim, value, expire_time) + } else { + dbKeyValue.delete(key_trim) + } } /** * 获取KV */ fun get(key: String, default: String? = null): String? { - val key = key.trim() - if (key.isBlank()) return default - return dbKeyValue.get(key) ?: default + val key_trim = key.trim() + if (key_trim.isBlank()) return default + return dbKeyValue.get(key_trim) ?: default + } + + fun delete(key: String): Boolean { + return dbKeyValue.delete(key) } fun getAll(): Map { diff --git a/LibKeyValue/src/main/java/com/mx/keyvalue/base/IMXKeyValue.kt b/LibKeyValue/src/main/java/com/mx/keyvalue/base/IMXKeyValue.kt index fe70716..6de043b 100644 --- a/LibKeyValue/src/main/java/com/mx/keyvalue/base/IMXKeyValue.kt +++ b/LibKeyValue/src/main/java/com/mx/keyvalue/base/IMXKeyValue.kt @@ -2,7 +2,8 @@ package com.mx.keyvalue.base internal interface IMXKeyValue { fun get(key: String): String? - fun set(key: String, value: String?, dead_time: Long?): Boolean + fun set(key: String, value: String, dead_time: Long?): Boolean + fun delete(key: String): Boolean fun getAll(): Map diff --git a/LibKeyValue/src/main/java/com/mx/keyvalue/db/MXDBKeyValue.kt b/LibKeyValue/src/main/java/com/mx/keyvalue/db/MXDBKeyValue.kt index e02b80b..7a4b5c5 100644 --- a/LibKeyValue/src/main/java/com/mx/keyvalue/db/MXDBKeyValue.kt +++ b/LibKeyValue/src/main/java/com/mx/keyvalue/db/MXDBKeyValue.kt @@ -55,7 +55,7 @@ internal class MXDBKeyValue( return null } - override fun set(key: String, value: String?, dead_time: Long?): Boolean { + override fun set(key: String, value: String, dead_time: Long?): Boolean { synchronized(lock) { val database = openHelper.writableDatabase try { @@ -78,6 +78,27 @@ internal class MXDBKeyValue( return false } + override fun delete(key: String): Boolean { + synchronized(lock) { + val database = openHelper.writableDatabase + try { + return database.delete( + dbName, + "${MXKVSQLiteOpenHelper.DB_KEY_NAME}=?", + arrayOf(key) + ) > 0 + } catch (e: Exception) { + e.printStackTrace() + } finally { + try { + database.close() + } catch (e: Exception) { + } + } + } + return false + } + override fun getAll(): Map { synchronized(lock) { val database = openHelper.readableDatabase diff --git a/LibKeyValue/src/main/java/com/mx/keyvalue/secret/IMXSecret.kt b/LibKeyValue/src/main/java/com/mx/keyvalue/secret/IMXSecret.kt index 9cf4850..9c97b47 100644 --- a/LibKeyValue/src/main/java/com/mx/keyvalue/secret/IMXSecret.kt +++ b/LibKeyValue/src/main/java/com/mx/keyvalue/secret/IMXSecret.kt @@ -10,11 +10,11 @@ interface IMXSecret { * 对Value加密 * @param key 对应的Key */ - fun encrypt(key: String, value: String?, salt: String): String? + fun encrypt(key: String, value: String, salt: String): String? /** * 对Value解密 * @param key 对应的Key */ - fun decrypt(key: String, secretValue: String?, salt: String): String? + fun decrypt(key: String, secretValue: String, salt: String): String? } \ No newline at end of file diff --git a/LibKeyValue/src/main/java/com/mx/keyvalue/secret/MXAESSecret.kt b/LibKeyValue/src/main/java/com/mx/keyvalue/secret/MXAESSecret.kt index 5e98aac..72c6402 100644 --- a/LibKeyValue/src/main/java/com/mx/keyvalue/secret/MXAESSecret.kt +++ b/LibKeyValue/src/main/java/com/mx/keyvalue/secret/MXAESSecret.kt @@ -14,24 +14,32 @@ import kotlin.random.Random * @param key 加密用的Key */ open class MXAESSecret(private val key: String) : IMXSecret { + companion object { + private val salt_key = arrayOf( + 65, 110, 123, 56, 3, 115, 73, 29, 108, 117, 98, 47, 93, 10, 71, + 21, 32, 98, 15, 22, 95, 27, 67, 29, 114, 119, 73, 80, 29, 23, 118, + 2, 44, 35, 75, 59, 127, 44, 99, 64, 20, 100, 111, 115, 116, 124, + 59, 48, 87, 32, 124, 119, 17, 97, 29, 30, 115, 85, 31, 76, 70, 57, 21, 56, + 36, 18, 122, 24, 60, 125, 100, 15, 75, 86, 104, 54, 111, 113, 117, + 20, 56, 38, 34, 126, 119, 98, 13, 15, 15, 22, 67, 23, 18, 57, 11, + 55, 98, 1, 34, 124, 83, 17, 11, 116, 92, 59, 54, 110, 62, 64, 122, + 126, 124, 95, 58, 7, 70, 89, 119, 108, 31, 75, 47, 42, 114, 87, 34, 113 + ) + private val salt_iv = arrayOf( + 10, 113, 18, 62, 120, 101, 32, 35, 22, 17, 79, 54, 14, 107, 8, 6, + 86, 97, 24, 36, 25, 42, 105, 32, 24, 111, 91, 91, 123, 58, 53, + 18, 108, 103, 126, 24, 30, 100, 41, 30, 63, 49, 42, 114, 126, + 23, 31, 109, 53, 58, 113, 18, 89, 104, 127, 122, 45, 79, 105, + 52, 7, 93, 79, 106, 20, 16, 66, 39, 43, 34, 57, 102, 69, 42, + 100, 127, 9, 76, 126, 4, 70, 65, 58, 56, 99, 38, 127, 27, 97, + 28, 82, 30, 122, 69, 1, 61, 50, 123, 70, 101, 3, 7, 46, 83, 94, + 11, 3, 13, 37, 109, 124, 44, 78, 107, 32, 33, 87, 101, 55, + 4, 29, 37, 50, 84, 39, 109, 67, 2 + ) + } private val transformation = "AES/CBC/PKCS5Padding" - private val source = ('a'..'z') + ('A'..'Z') + ('0'..'9') + arrayOf( - '!', '@', '#', '$', '^', '&', '*', '(', ')', '_', '+', '-', - '=', '~', '`', ';', ':', ',', '<', '.', '>', '/', '?' - ) - private val salt_key = arrayOf( - 46, 85, 38, 47, 86, 0, 15, 54, 57, 56, 29, 22, 44, 109, 78, - 51, 49, 39, 78, 12, 55, 28, 42, 2, 116, 71, 28, 93, 66, 102, 41, 63, - 84, 40, 6, 24, 38, 77, 7, 84, 45, 22, 82, 94, 97, 14, 69, 30, 18, - 51, 57, 94, 118, 124, 86, 126, 119, 103, 114, 84, 103, 42, 105, 40 - ) - private val salt_iv = arrayOf( - 49, 75, 119, 8, 17, 68, 64, 12, 78, 106, 125, 109, 116, 11, 76, - 75, 41, 48, 21, 98, 56, 70, 75, 66, 39, 97, 109, 106, 89, 87, - 32, 111, 50, 100, 44, 12, 72, 37, 94, 40, 116, 31, 40, 6, 42, 49, 54, - 6, 44, 9, 26, 20, 42, 90, 54, 67, 70, 85, 35, 74, 17, 86, 111, 70 - ) + private val source = ('a'..'z') + ('A'..'Z') + ('0'..'9') private var encryptCipher: Cipher? = null private var decryptCipher: Cipher? = null @@ -45,7 +53,7 @@ open class MXAESSecret(private val key: String) : IMXSecret { } keys.append(source[i % source.size]) } - keys.append(list.toCharArray()) + keys.append(list) return MXUtils.md5(keys.toString().toByteArray(), 16).toByteArray() } @@ -58,7 +66,7 @@ open class MXAESSecret(private val key: String) : IMXSecret { } keys.append(source[i % source.size]) } - keys.append(list.toCharArray()) + keys.append(list) return MXUtils.md5(keys.toString().toByteArray(), 16).toByteArray() } @@ -78,18 +86,23 @@ open class MXAESSecret(private val key: String) : IMXSecret { return UUID.randomUUID().toString().replace("-", "").substring(0, length) } - override fun encrypt(key: String, value: String?, salt: String): String? { - value ?: return null - val relBytes = encryptCipher?.doFinal((salt + value + key).toByteArray()) ?: return null + override fun encrypt(key: String, value: String, salt: String): String? { + val relBytes = try { + encryptCipher?.doFinal((salt + value + key).toByteArray()) ?: return null + } catch (e: Exception) { + return null + } val relBase = Base64.encode(relBytes, Base64.DEFAULT) return String(relBase) } - override fun decrypt(key: String, secretValue: String?, salt: String): String? { - secretValue ?: return null - val relBase = String( + override fun decrypt(key: String, secretValue: String, salt: String): String? { + val bytes = try { decryptCipher?.doFinal(Base64.decode(secretValue, Base64.DEFAULT)) ?: return null - ) + } catch (e: Exception) { + return null + } + val relBase = String(bytes) return relBase.substring(salt.length, relBase.length - key.length) } } \ No newline at end of file diff --git a/LibKeyValue/src/main/java/com/mx/keyvalue/secret/MXNoSecret.kt b/LibKeyValue/src/main/java/com/mx/keyvalue/secret/MXNoSecret.kt index 742a6ba..c0eba98 100644 --- a/LibKeyValue/src/main/java/com/mx/keyvalue/secret/MXNoSecret.kt +++ b/LibKeyValue/src/main/java/com/mx/keyvalue/secret/MXNoSecret.kt @@ -8,11 +8,11 @@ open class MXNoSecret : IMXSecret { return "" } - override fun encrypt(key: String, value: String?, salt: String): String? { + override fun encrypt(key: String, value: String, salt: String): String? { return value } - override fun decrypt(key: String, secretValue: String?, salt: String): String? { + override fun decrypt(key: String, secretValue: String, salt: String): String? { return secretValue } } \ No newline at end of file diff --git a/LibKeyValue/src/main/java/com/mx/keyvalue/utils/MXUtils.kt b/LibKeyValue/src/main/java/com/mx/keyvalue/utils/MXUtils.kt index 0eb11b3..b838d51 100644 --- a/LibKeyValue/src/main/java/com/mx/keyvalue/utils/MXUtils.kt +++ b/LibKeyValue/src/main/java/com/mx/keyvalue/utils/MXUtils.kt @@ -17,14 +17,14 @@ internal object MXUtils { fun md5(content: ByteArray, size: Int): String { val hash = MessageDigest.getInstance("MD5").digest(content) - val hex = StringBuilder(hash.size * 2) + val builder = StringBuilder() for (b in hash) { - var str = Integer.toHexString(b.toInt()) + val str = Integer.toHexString(b.toInt() and 0xff) if (b < 0x10) { - str = "0$str" + builder.append('0') } - hex.append(str.substring(str.length - 2)) + builder.append(str) } - return hex.toString().substring(0, size) + return builder.toString().substring(0, size).lowercase() } } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 0c8b7e7..6c2edcf 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -20,4 +20,11 @@ android:layout_height="wrap_content" android:padding="10dp" android:text="读取KEY" /> + + \ No newline at end of file -- Gitee From 2cee053a42a5b32c2b25e01e1a54764e8cdb885b Mon Sep 17 00:00:00 2001 From: zhangmengxiong Date: Mon, 16 May 2022 20:04:31 +0800 Subject: [PATCH 2/5] Update MainActivity.kt --- app/src/main/java/com/mx/example/MainActivity.kt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/mx/example/MainActivity.kt b/app/src/main/java/com/mx/example/MainActivity.kt index 7f93a81..7fd2e83 100644 --- a/app/src/main/java/com/mx/example/MainActivity.kt +++ b/app/src/main/java/com/mx/example/MainActivity.kt @@ -12,6 +12,7 @@ import com.mx.keyvalue.secret.MXAESSecret import kotlinx.android.synthetic.main.activity_main.* import java.lang.StringBuilder import java.util.concurrent.TimeUnit +import kotlin.random.Random class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { @@ -22,7 +23,7 @@ class MainActivity : AppCompatActivity() { application, "mx_kv_test", MXAESSecret("89qew0lkcjz;lkui1=2=--093475kjhzcklj") ) -// KV.cleanAll() + KV.cleanAll() setExpireTxv.setOnClickListener { KV.set( @@ -35,9 +36,13 @@ class MainActivity : AppCompatActivity() { readExpireTxv.setOnClickListener { Toast.makeText(this, KV.get("test_expire_key", "失效"), Toast.LENGTH_SHORT).show() } + deleteTxv.setOnClickListener { + KV.delete("test_expire_key") + Toast.makeText(this, KV.get("test_expire_key", "失效"), Toast.LENGTH_SHORT).show() + } var spend = 0L - val time = 20 + val time = 200 repeat(time) { val key = generalString(12) val value = generalString(1280) @@ -53,8 +58,6 @@ class MainActivity : AppCompatActivity() { } println("平均耗时:${spend / time.toFloat()} ms") - println(KV.getAll().entries.joinToString(",") { "${it.key}, ${it.value}" }) - var boolDelegate by MXBoolDelegate(KV, "bool_test", true) println("测试 MXBoolDelegate -> $boolDelegate") boolDelegate = false -- Gitee From 752c3bcc31021d2a0cb9c6477a91d0ab670138d7 Mon Sep 17 00:00:00 2001 From: zhangmengxiong Date: Mon, 16 May 2022 20:31:31 +0800 Subject: [PATCH 3/5] 666 --- LibKeyValue/src/main/java/com/mx/keyvalue/MXKeyValue.kt | 2 +- .../src/main/java/com/mx/keyvalue/secret/MXAESSecret.kt | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/LibKeyValue/src/main/java/com/mx/keyvalue/MXKeyValue.kt b/LibKeyValue/src/main/java/com/mx/keyvalue/MXKeyValue.kt index 76ec80c..d0d3105 100644 --- a/LibKeyValue/src/main/java/com/mx/keyvalue/MXKeyValue.kt +++ b/LibKeyValue/src/main/java/com/mx/keyvalue/MXKeyValue.kt @@ -33,7 +33,7 @@ class MXKeyValue( fun set(key: String, value: String?, expire_time: Long? = null): Boolean { val key_trim = key.trim() if (key_trim.isBlank()) return false - return if (value != null) { + return if (value != null && value.isNotEmpty()) { dbKeyValue.set(key_trim, value, expire_time) } else { dbKeyValue.delete(key_trim) diff --git a/LibKeyValue/src/main/java/com/mx/keyvalue/secret/MXAESSecret.kt b/LibKeyValue/src/main/java/com/mx/keyvalue/secret/MXAESSecret.kt index 72c6402..e286f8a 100644 --- a/LibKeyValue/src/main/java/com/mx/keyvalue/secret/MXAESSecret.kt +++ b/LibKeyValue/src/main/java/com/mx/keyvalue/secret/MXAESSecret.kt @@ -36,10 +36,13 @@ open class MXAESSecret(private val key: String) : IMXSecret { 11, 3, 13, 37, 109, 124, 44, 78, 107, 32, 33, 87, 101, 55, 4, 29, 37, 50, 84, 39, 109, 67, 2 ) + private val source = ('a'..'z') + ('A'..'Z') + ('0'..'9') + arrayOf( + '!', '@', '#', '$', '^', '&', '*', '(', ')', '_', '+', '-', + '=', '~', '`', ';', ':', ',', '<', '.', '>', '/', '?' + ) } private val transformation = "AES/CBC/PKCS5Padding" - private val source = ('a'..'z') + ('A'..'Z') + ('0'..'9') private var encryptCipher: Cipher? = null private var decryptCipher: Cipher? = null -- Gitee From 74b7fbac1093bf87bde0cb331b8b24cffb4b3a91 Mon Sep 17 00:00:00 2001 From: zhangmengxiong Date: Mon, 16 May 2022 20:37:15 +0800 Subject: [PATCH 4/5] Update MXKeyValue.kt --- LibKeyValue/src/main/java/com/mx/keyvalue/MXKeyValue.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/LibKeyValue/src/main/java/com/mx/keyvalue/MXKeyValue.kt b/LibKeyValue/src/main/java/com/mx/keyvalue/MXKeyValue.kt index d0d3105..4bbb2a5 100644 --- a/LibKeyValue/src/main/java/com/mx/keyvalue/MXKeyValue.kt +++ b/LibKeyValue/src/main/java/com/mx/keyvalue/MXKeyValue.kt @@ -49,8 +49,13 @@ class MXKeyValue( return dbKeyValue.get(key_trim) ?: default } + /** + * 删除Key + */ fun delete(key: String): Boolean { - return dbKeyValue.delete(key) + val key_trim = key.trim() + if (key_trim.isBlank()) return false + return dbKeyValue.delete(key_trim) } fun getAll(): Map { -- Gitee From eaabca667e4c560a6ce276b16cfe6bc8402ff5bf Mon Sep 17 00:00:00 2001 From: zhangmengxiong Date: Fri, 20 May 2022 14:54:36 +0800 Subject: [PATCH 5/5] 666 --- .../main/java/com/mx/keyvalue/MXKeyValue.kt | 7 +++++++ .../java/com/mx/keyvalue/secret/IMXSecret.kt | 21 +++++++++++++++++++ .../com/mx/keyvalue/secret/MXAESSecret.kt | 3 ++- .../main/java/com/mx/example/MainActivity.kt | 1 + 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/LibKeyValue/src/main/java/com/mx/keyvalue/MXKeyValue.kt b/LibKeyValue/src/main/java/com/mx/keyvalue/MXKeyValue.kt index 4bbb2a5..35de783 100644 --- a/LibKeyValue/src/main/java/com/mx/keyvalue/MXKeyValue.kt +++ b/LibKeyValue/src/main/java/com/mx/keyvalue/MXKeyValue.kt @@ -14,6 +14,13 @@ class MXKeyValue( private val dbKeyValue: IMXKeyValue = MXDBKeyValue(context.applicationContext, name.trim(), secret) + init { + if (!secret.validate()) { + // 验证Secret 工具类解密正确性 + throw Exception("${secret::class.java.simpleName} ---> IMXSecret Class validate error.") + } + } + /** * 从SharedPreferences拷贝数据 */ diff --git a/LibKeyValue/src/main/java/com/mx/keyvalue/secret/IMXSecret.kt b/LibKeyValue/src/main/java/com/mx/keyvalue/secret/IMXSecret.kt index 9c97b47..57b0213 100644 --- a/LibKeyValue/src/main/java/com/mx/keyvalue/secret/IMXSecret.kt +++ b/LibKeyValue/src/main/java/com/mx/keyvalue/secret/IMXSecret.kt @@ -1,5 +1,8 @@ package com.mx.keyvalue.secret +import com.mx.keyvalue.utils.MXUtils +import java.util.* + interface IMXSecret { /** * 生成随机密码 @@ -17,4 +20,22 @@ interface IMXSecret { * @param key 对应的Key */ fun decrypt(key: String, secretValue: String, salt: String): String? + + /** + * 验证当前加密类的正确性 + */ + fun validate(): Boolean { + try { + val key = UUID.randomUUID().toString().replace("-", "") + val value = UUID.randomUUID().toString().replace("-", "") + System.currentTimeMillis() + val salt = generalSalt() + val secretKey = encrypt(key, value, salt)!! + val desValue = decrypt(key, secretKey, salt) + MXUtils.log("IMXSecret validate => $value --- $desValue") + return value == desValue + } catch (e: Exception) { + e.printStackTrace() + } + return false + } } \ No newline at end of file diff --git a/LibKeyValue/src/main/java/com/mx/keyvalue/secret/MXAESSecret.kt b/LibKeyValue/src/main/java/com/mx/keyvalue/secret/MXAESSecret.kt index e286f8a..dc001c7 100644 --- a/LibKeyValue/src/main/java/com/mx/keyvalue/secret/MXAESSecret.kt +++ b/LibKeyValue/src/main/java/com/mx/keyvalue/secret/MXAESSecret.kt @@ -36,10 +36,11 @@ open class MXAESSecret(private val key: String) : IMXSecret { 11, 3, 13, 37, 109, 124, 44, 78, 107, 32, 33, 87, 101, 55, 4, 29, 37, 50, 84, 39, 109, 67, 2 ) - private val source = ('a'..'z') + ('A'..'Z') + ('0'..'9') + arrayOf( + private val symbols = arrayOf( '!', '@', '#', '$', '^', '&', '*', '(', ')', '_', '+', '-', '=', '~', '`', ';', ':', ',', '<', '.', '>', '/', '?' ) + private val source = ('a'..'z') + symbols + ('A'..'Z') + symbols + ('0'..'9') + symbols } private val transformation = "AES/CBC/PKCS5Padding" diff --git a/app/src/main/java/com/mx/example/MainActivity.kt b/app/src/main/java/com/mx/example/MainActivity.kt index 7fd2e83..e34de2a 100644 --- a/app/src/main/java/com/mx/example/MainActivity.kt +++ b/app/src/main/java/com/mx/example/MainActivity.kt @@ -9,6 +9,7 @@ import com.fasterxml.jackson.module.kotlin.registerKotlinModule import com.mx.keyvalue.MXKeyValue import com.mx.keyvalue.delegate.* import com.mx.keyvalue.secret.MXAESSecret +import com.mx.keyvalue.secret.MXNoSecret import kotlinx.android.synthetic.main.activity_main.* import java.lang.StringBuilder import java.util.concurrent.TimeUnit -- Gitee