【问题标题】:Android API 21 Create Custom Master KeyAndroid API 21 创建自定义主密钥
【发布时间】:2021-03-22 16:50:12
【问题描述】:

我正在尝试创建一个加密的SharedPreferences 实现,但Android website 中给出的示例适用于 API 23 及更高版本。具体来说,问题是使用此代码创建主密钥MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC)

在当前版本的 androidx 安全性 ('androidx.security:security-crypto:1.1.0-alpha01') 上,您可以在技术上为 EncryptedSharedPreferences 创建实现,除了上面的 getOrCreate() 函数状态用于 API仅限23岁及以上。因此,如果我理解正确,我唯一缺少的就是能够执行以下代码行:

private fun createSharedPref(context: Context): SharedPreferences {
    return create(
        "secret_shared_prefs",
        masterKeyAlias,
        context,
        PrefKeyEncryptionScheme.AES256_SIV,
        PrefValueEncryptionScheme.AES256_GCM
    )
}

是创建我自己的自定义 MasterKey。 API 21 中有没有办法做到这一点?

这是我目前的编码方式:

class SharedPreferencesUtil {
    companion object {
        private val masterKeyAlias = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC)
        } else {
            TODO("VERSION.SDK_INT < M")
            //I need help here
        }


        private fun createSharedPref(context: Context): SharedPreferences {
            return create(
                "secret_shared_prefs",
                masterKeyAlias,
                context,
                PrefKeyEncryptionScheme.AES256_SIV,
                PrefValueEncryptionScheme.AES256_GCM
            )
        }


        fun saveObject(context: Context, key: String, data: Any) {
            val gson = Gson()
            val json = gson.toJson(data)
            val prefs = createSharedPref(context)
            prefs.edit().putString(key, json).apply()
        }


        fun getJson(context: Context, key: String): String {
            val prefs = createSharedPref(context)
            val json = prefs.getString(key, "null")
            return json!!
        }


        fun clearPreferences(context: Context) {
            val prefs = createSharedPref(context).edit()
            //remove my data
        }
    }
}

【问题讨论】:

    标签: android kotlin encrypted-shared-preference


    【解决方案1】:

    我找到了一个可行的解决方案 (source)

    我将主密钥的实现替换为如下:

    private fun createMasterKey(context: Context): String {
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC)
        } else {
            val alias = "your_alias"
            val start: Calendar = GregorianCalendar()
            val end: Calendar = GregorianCalendar()
            end.add(Calendar.YEAR, 30)
    
            val spec =
                KeyPairGeneratorSpec.Builder(context) 
                    .setAlias(alias)
                    .setSubject(X500Principal("CN=$alias"))
                    .setSerialNumber(
                        BigInteger.valueOf(
                            Math.abs(alias.hashCode()).toLong()
                        )
                    )
                    .setStartDate(start.time).setEndDate(end.time)
                    .build()
    
            val kpGenerator: KeyPairGenerator = KeyPairGenerator.getInstance(
                "RSA",
                "AndroidKeyStore"
            )
            kpGenerator.initialize(spec)
            val kp: KeyPair = kpGenerator.generateKeyPair()
            kp.public.toString()
        }
    }
    

    【讨论】:

    • MasterKeys 已弃用。 KeyPairGeneratorSpec.Builder 需要 API 18 且已弃用。
    • @CoolMind 你有更好的解决方案吗?
    • @AyxanHaqverdili,对不起,我改变了一个项目,也许稍后会看到源代码。请参阅stackoverflow.com/questions/62498977/… 和其他人。
    • @CoolMind 当您发表评论时,我实际上正在阅读该帖子。它不适用于 API 22,这就是这里的重点。
    • @AyxanHaqverdili,也许吧。我也在 API 21 上测试了我的解决方案。也许看到medium.com/swlh/…medium.com/android-club/…。或者根据 API 版本创建主密钥。
    猜你喜欢
    • 2014-06-19
    • 2016-03-16
    • 2012-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-02
    • 2020-04-15
    相关资源
    最近更新 更多