(译)使用AndroidX安全库加密SharedPreferences

本文译自Encrypting Shared Preferences with the AndroidX Security Library,介绍了AndroidX安全库中EncryptedSharedPreferences的使用。备注:仅支持minSdkVersion 23及以上。

本文首发:http://yuweiguocn.github.io/

《离思五首·其四》
曾经沧海难为水,除却巫山不是云。
取次花丛懒回顾,半缘修道半缘君。
-唐代,元稹

Android框架给我们提供了SharedPreferences,它是一个用于存储小量键值数据很好的工具。当存储一些敏感数据,重要的是SharedPreferences存储的数据是明文的。我们应该加密敏感的数据不要让它被窥视。我们可以怎样做?

一种方法是我们使用Android密钥库自己写加密包装SharedPreferences。不幸的是这会相当复杂并且涉及大量配置。另一种方法是使用第三方库,这意味着我们需要花时间找到一个合适的。值得庆幸的是AndroidX安全库最近被添加,这让min-sdk为23+的应用存储加密SharedPreferences变得容易和方便。

详细使用

首先在module的build.gradle文件中添加依赖。

implementation "androidx.security:security-crypto:1.0.0-alpha02"

这是在写本文时的最新版本。查看library’s releases page获取最新版本。

需要注意的是这个库当前是alpha阶段。这意味着虽然功能是稳定的,部分API在后续版本可能被修改或移除。

添加了依赖之后,下一步是在Android KeyStore创建一个加密master key和store。安全库提供了一个容易的方法处理这个。将下面的代码添加到你计划创建EncryptedSharedPreferences实例前面。

val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC
val masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec)

我们指定了一个默认的key,AES256_GCM_SPEC,用于创建master key。虽然推荐使用这个规范,如果你需要对如何生成密钥有更多的控制你也可以自定义KeyGenParameterSpec。

最后我们只需要一个EncryptedSharedPreferences实例,它对SharedPreferences进行了包装并且为我们处理所有的加密。不同于SharedPreferences,我们可以从Context#getSharedPreferences或Activity#getPreferences获取,我们需要创建自己的EncryptedSharedPreferences实例。

val sharedPreferences = EncryptedSharedPreferences.create(
    "shared_preferences_filename",
    masterKeyAlias,
    context,
    EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
    EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)

我们指定了shared preferences的文件名,之前创建的masterKeyAlias,和一个context。最后两个参数是key和value加密的scheme。它们是库提供的唯一的选项。

创建了EncryptedSharedPreferences实例后,可以使用它像SharedPreferences一样读取和存储值。总而言之,就像下面的代码一样:

val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC
val masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec)
val sharedPreferences = EncryptedSharedPreferences.create(
    "shared_preferences_filename",
    masterKeyAlias,
    context,
    EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
    EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
// storing a value
sharedPreferences
    .edit()
    .putString("some_key", "some_data")
    .apply()
// reading a value
sharedPreferences.getString("some_key", "some_default_value") // -> "some_data"

再次检查结果

我们怎样知道数据被加密了?让我们看下shared preferences文件中的内容。如果你想shared preferences文件中的内容,可以从StackOverflow找到答案。使用正常的SharedPreferences,文件内容如下:



    some_data

正如我们看到的,key和value没有被加密。使用EncryptedSharedPreferences,文件内容就像这样:



    AU+p3hwqCgvlDOtIaawFHWVDf4rFsqghM7ivFTEJesrRp19D+zk7tqsqlGZPLAbryHI=
    12a901802f1a5d2fbc5cd3c9b545a89ca8ace8f125f8e601a8ac51929303ead8a2bbdf5428bd054360b97c1727ef93ef63b64f43ceac92156f3aee9402dd247009d9779571c6ceacfcd4e7123665cc9dd94c44c5c2c6241a8de070d365d94010f8affb6097d4b0fec1c628120a8f901c23caa03d32ecc6ce270e3cc3341e6455b87a80474b3818c3ad678faa4199a9a45078b218c89b8c5a8cbd1780a68b4f8196eb5153b6422df2bdfee6541a44089680d49f03123c0a30747970652e676f6f676c65617069732e636f6d2f676f6f676c652e63727970746f2e74696e6b2e4165735369764b65791001189680d49f032001
    128801da6fdef289b2c6e2933c341b1b3df3b39330671d76df362ba8b0a1d807cdc9d2d4d7bc3062139377e4fa61428f3817c0e368c3196c95fdbcca3c37075e7132abae1fe0f128ceef7278a06a01e0cacf29edc1f3c1c1d37875c27c0cf5d86d0b2bb39efcac84828f664838b77aa4c406028af912e860cad8bff51aca6aaf45167d5ab5c8e57bf05db61a44089cbca7fd04123c0a30747970652e676f6f676c65617069732e636f6d2f676f6f676c652e63727970746f2e74696e6b2e41657347636d4b65791001189cbca7fd042001

可以看到key和value被加密了并且存储了两个keysets,一个是shared preference的keys另一个是values。Keysets包含加密和解密shared preference数据的key。之前创建的master key用于加密这些keysets,这样它们就可以和提供的数据一起存储在shared preference文件中。

结语

Android的SharedPreferences对于存储key-value数据是一个很有用的工具,对于敏感数据,这是一个很好的加密它的方法。最近的AndroidX安全库是一个受欢迎的新功能,它为我们提供了一个简单易用的加密方案。

你可能感兴趣的:((译)使用AndroidX安全库加密SharedPreferences)