美文网首页问题研究
(译)使用AndroidX安全库加密SharedPreferen

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

作者: 于卫国 | 来源:发表于2020-02-09 16:42 被阅读0次

    本文译自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,文件内容如下:

    <?xml version='1.0' encoding='utf-8' standalone='yes' ?>
    <map>
        <string name="some_key">some_data</string>
    </map>
    

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

    <?xml version='1.0' encoding='utf-8' standalone='yes' ?>
    <map>
        <string name="ATP1ABa3NIlOap2c7iNkVaUcQmTocrnpkXl0PyI=">AU+p3hwqCgvlDOtIaawFHWVDf4rFsqghM7ivFTEJesrRp19D+zk7tqsqlGZPLAbryHI=</string>
        <string name="__androidx_security_crypto_encrypted_prefs_key_keyset__">12a901802f1a5d2fbc5cd3c9b545a89ca8ace8f125f8e601a8ac51929303ead8a2bbdf5428bd054360b97c1727ef93ef63b64f43ceac92156f3aee9402dd247009d9779571c6ceacfcd4e7123665cc9dd94c44c5c2c6241a8de070d365d94010f8affb6097d4b0fec1c628120a8f901c23caa03d32ecc6ce270e3cc3341e6455b87a80474b3818c3ad678faa4199a9a45078b218c89b8c5a8cbd1780a68b4f8196eb5153b6422df2bdfee6541a44089680d49f03123c0a30747970652e676f6f676c65617069732e636f6d2f676f6f676c652e63727970746f2e74696e6b2e4165735369764b65791001189680d49f032001</string>
        <string name="__androidx_security_crypto_encrypted_prefs_value_keyset__">128801da6fdef289b2c6e2933c341b1b3df3b39330671d76df362ba8b0a1d807cdc9d2d4d7bc3062139377e4fa61428f3817c0e368c3196c95fdbcca3c37075e7132abae1fe0f128ceef7278a06a01e0cacf29edc1f3c1c1d37875c27c0cf5d86d0b2bb39efcac84828f664838b77aa4c406028af912e860cad8bff51aca6aaf45167d5ab5c8e57bf05db61a44089cbca7fd04123c0a30747970652e676f6f676c65617069732e636f6d2f676f6f676c652e63727970746f2e74696e6b2e41657347636d4b65791001189cbca7fd042001</string>
    </map>
    

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

    结语

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

    相关文章

      网友评论

        本文标题:(译)使用AndroidX安全库加密SharedPreferen

        本文链接:https://www.haomeiwen.com/subject/mkoixhtx.html