概览
Security
库提供了与读取和写入静态数据以及密钥创建和验证相关的安全最佳做法的实现。
该库使用构建器模式为以下安全等级提供安全的默认设置:
- 在可靠加密和良好性能之间取得平衡的强安全性这种安全等级适用于银行应用和聊天应用等消费者应用,以及执行证书吊销检查的企业应用。
- 最高安全性这种安全等级适用于需要由硬件支持的密钥库和需要用户介入以提供密钥访问权限的应用。
秘钥管理
- Security库可以使用多个秘钥集,可以对文件和sp进行加密。秘钥集被存储在sp中
- 主秘钥被存储在系统秘钥库中
Security加密操作
依赖
使用Security
库需要导入以下依赖
implementation("androidx.security:security-crypto:1.0.0") implementation("androidx.security:security-identity-credential:1.0.0-alpha02") implementation("androidx.security:security-app-authenticator:1.0.0-alpha02") androidTestImplementation("androidx.security:security-app-authenticator:1.0.0-alpha01") 复制代码
存在的问题
Security
库支持的最低api版本是24,我们有以下两种方式解决:
- manifest中声明
<uses-sdk tools:overrideLibrary="androidx.security.identity.credential,androidx.security" />
- 提升最低api版本为24,不过这样就需要对高于api24和低于api24两种情况分别做适配了
使用Security进行文件加密操作
写入加密数据
无法重复写入
当要写入的文件已经存在时,重复写入数据的时候openFileOutput
方法会抛出异常,原因就是无法重复写入,见注释:
写入数据:
- 代码
- 本例代码中
EncryptedFile.Builder
的构建耗时最长,在我的手机上能达到300-600ms
的水平,所以非敏感的文件尽量不要用到加密 - 另外存储进文件的数据膨胀也很大,这意味着占用了更大的存储空间
val encrypt = EncryptedFile.Builder( getFile("安安安安卓写入文件加密数据.txt").apply { if (exists()) {//如果已存在就先删除文件 delete() } }, this@MainActivity, "随便写个key", EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB ).build() startRecord() encrypt.openFileOutput().apply { write("随便写入点字符串".toByteArray(charset = Charsets.UTF_8)) flush() close() } 复制代码
- 效果
读取加密数据
val encrypt = EncryptedFile.Builder( getFile( "安安安安卓写入文件加密数据.txt" ), this@MainActivity, "随便写个key", EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB ).build() startRecord() val bytes = BufferedInputStream(encrypt.openFileInput()).readBytes() val result = String(bytes, charset = Charsets.UTF_8) 复制代码
使用Security进行SharePreference进行加密操作
Security
库提供了EncryptedSharedPreferences
对存入sp的key-value进行加密
不过众所周知的sp是个坑爹的东西,所以仍然只应该把EncryptedSharedPreferences
运用到敏感的数据存储上
写入数据到Shar
share = EncryptedSharedPreferences.create( "encryptdata", "key", this@MainActivity, EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM ) share.edit().let { it.putString("key", "SharePreference数据") it.apply() } 复制代码
从SharePreference读取数据
share = EncryptedSharedPreferences.create( "encryptdata", "key", this@MainActivity, EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM ) val value = share.getString("key", "")