是什么

Jetpack Security 是 Google I/O 2019 发布的安全组件库。Security构成简单,主要包含EncryptedFileEncryptedSharedPreferences两个类,分别用来对FileSharedPreferences的读写进行加密解密处理。Security要求min SDK version 23。

EncryptedFile 封装了Google的加密库tink的逻辑,提供FileInputStreamFileOutputStream,可以更安全的进行流的读写。
EncryptedSharedPreferencesSharedPreferences包装类,通过两种方式自动加密键/值:
Key加密使用的是确定性的加密算法,使得秘钥可以被加密
Value加密使用AES-256 GCM加密,不确定加密

Jetpack Security (JetSec)加密库为 Files 和 SharedPreferences 对象的加密操作提供了抽象支持。该库使用了安全且运用广泛的[密码学原语 cryptographic primitives),强化了AndroidKeyStore的使用。使用 EncryptedFile 和 EncryptedSharedPreferences 可以让您在本地保护可能包含敏感数据、API 密钥、OAuth 令牌和其他类型机密信息的文件。

从 5.0 开始,Android 会默认对用户数据分区的内容进行加密,那您为什么还需要加密应用中的数据呢?这是因为在某些场合中,您可能需要额外的保护。如果您的应用使用共享存储(shared storage),则应该对数据进行加密。如果您的应用处理敏感信息,包括但不限于个人身份可识别信息 (Personally Identifiable Information, PII)、健康记录、财务信息或企业数据,那么您的应用应该对其主目录中的数据进行加密。如果可能,我们建议您将此类信息与生物验证操作绑定,以提供额外的保护。

Jetpack Security 基于Tink,而 Tink 是 Google 的一个开源并支持跨平台的安全项目。如果您需要常规加密、混合加密或类似的安全措施,那么 Tink 可能适用于您的项目。Jetpack Security 的数据结构与 Tink 完全兼容。

2018年9月3日,Google宣布了一个新的加密库叫Tink,称 Tink 旨在提供安全、易于使用和难以误用的加密 API,它是基于现有的加密库 BoringSSL( 是谷歌创建的 OpenSSL 分支) 和 Java Cryptography Architecture(Java加密体系结构),加入了Project Wycheproof(它包含一系列安全测试,用来检测加密库(cryptographic libraries)软件是否存在各种已知漏洞。这些软件负责对存储于设备、或互联网上传输的数据进行加密。)项目发现的弱点反制措施。

当前稳定版 1.0.0

谷歌官方文档推荐的 应用安全性最佳做法

如果您存储的数据特别敏感或私密,请考虑使用 Security 库中提供的 EncryptedFile 对象,而不要使用 File 对象。

使用

声明依赖项

如需添加 Security 的依赖项,您必须将 Google Maven 代码库添加到项目中。如需了解详情,请参阅 Google 的 Maven 代码库。

在应用或模块的 build.gradle 文件中添加所需工件的依赖项:

dependencies {implementation "androidx.security:security-crypto:1.0.0"// For Identity Credential APIsimplementation "androidx.security:security-identity-credential:1.0.0-alpha03"// For App Authentication APIsimplementation "androidx.security:security-app-authenticator:1.0.0-alpha02"// For App Authentication API testingandroidTestImplementation "androidx.security:security-app-authenticator:1.0.0-alpha01"
}

秘钥管理

Security库秘钥管理分为两个部分:

秘钥集合(Key set)
包含一个或多个秘钥来加密文件或SharedPreferences数据,存储在SharedPreferences中。
主密钥(Master Key)
用来加密所有秘钥集合,存储在Android Keystore系统中
使用Android Keystore的包装类MasterKeys只用两行就可以制作Master Key。

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

EncryptedSharedPreferences

普通SharedPreferences

        val data = getSharedPreferences("SPNormal", Context.MODE_PRIVATE)val editor = data.edit()editor.putInt("IntSave", 10)editor.apply()val intSaved = data.getInt("IntSave", 1)Log.e("IntSave", intSaved.toString())

key和value都被明文保存在xml中 SPNormal

使用EncryptedSharedPreferences

         val sharedPreferences = EncryptedSharedPreferences.create("SPEncrypted",mainKeyAlias,this,EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM)val editor = sharedPreferences.edit()editor.putInt("IntSave", 10)editor.apply()val intSaved = sharedPreferences.getInt("IntSave", 1)Log.e("IntSave", intSaved.toString())

key和value都被明文保存在xml中 SPEncrypted

性能对比

性能上有10倍以上的劣化

EncryptedFile

Write File

例如向text文件中中写入 "MY SUPER SECRET INFORMATION"字符串

        val fileToWrite = "my_other_sensitive_data.txt"val encryptedFile = EncryptedFile.Builder(File(filesDir, fileToWrite),this,mainKeyAlias,EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB).build()// Write to a file.try {val outputStream: FileOutputStream? = encryptedFile.openFileOutput()outputStream?.apply {write("MY SUPER SECRET INFORMATION".toByteArray(Charset.forName("UTF-8")))flush()close()}} catch (ex: IOException) {// Error occurred opening file for writing.}

Read File

通过EncryptedFile可以输出明文”MY SUPER SECRET INFORMATION“;
仅使用BufferedReader则会输出不可读的密文

val fileToRead = "my_sensitive_data.txt"
lateinit var byteStream: ByteArrayOutputStream
val encryptedFile = EncryptedFile.Builder(File(context.getFilesDir(), fileToRead),context,masterKeyAlias,EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
).build()try {encryptedFile.openFileInput().use { fileInputStream ->try {val sb = StringBuilder()val br = BufferedReader(InputStreamReader(fileInputStream) as Reader?)br.readLine().forEach {sb.append(it)}br.close()// 输出 MY SUPER SECRET INFORMATION Log.d("fileContents", sb.toString())Toast.makeText(this, sb.toString(), Toast.LENGTH_SHORT).show()} catch (ex: Exception) {// Error occurred opening raw file for reading.} finally {fileInputStream.close()}}
} catch (ex: IOException) {// Error occurred opening encrypted file for reading.
}

完整工具类代码

val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC
val mainKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec)/*** 加密文件*/fun  writeFile(context: Context,fileToWrite:String){val encryptedFile = EncryptedFile.Builder(File(context.filesDir, fileToWrite),context,mainKeyAlias,EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB).build()// Write to a file.try {val outputStream: FileOutputStream? = encryptedFile.openFileOutput()outputStream?.apply {write("MY SUPER SECRET INFORMATION".toByteArray(Charset.forName("UTF-8")))flush()close()}} catch (ex: IOException) {// Error occurred opening file for writing.}
}/***解密文件*/fun readFile(context: Context,fileToRead:String){lateinit var byteStream: ByteArrayOutputStreamval encryptedFile = EncryptedFile.Builder(File(context.filesDir, fileToRead),context,mainKeyAlias,EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB).build()try {encryptedFile.openFileInput().use { fileInputStream ->try {val sb = StringBuilder()val br = BufferedReader(InputStreamReader(fileInputStream) as Reader?)br.readLine().forEach {sb.append(it)}br.close()// 输出 MY SUPER SECRET INFORMATIONLog.e("fileContents", sb.toString())
//                Toast.makeText(context, sb.toString(), Toast.LENGTH_SHORT).show()} catch (ex: Exception) {// Error occurred opening raw file for reading.} finally {fileInputStream.close()}}} catch (ex: IOException) {// Error occurred opening encrypted file for reading.}}/*** 存储字符串** @param context* @param key     存储的键* @param value   存储的值* @throws Exception*/
fun saveSPEncrypted(context: Context, key: String, value: String) {val sharedPreferences = EncryptedSharedPreferences.create("SPEncrypted",mainKeyAlias,context,EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM)val editor = sharedPreferences.edit()editor.putString(key, value)editor.apply()val intSaved = sharedPreferences.getInt("IntSave", 1)Log.e("IntSave", intSaved.toString())
}/*** 获取字符串** @param context* @param key    存储的键* @throws Exception*/
@Throws(Exception::class)
fun getSPEncrypted(context: Context, key: String): String? {val securityPrefs = EncryptedSharedPreferences.create("SPEncrypted",mainKeyAlias,context,EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM)return securityPrefs.getString(key, "")
}

Android JetPack Security简介相关推荐

  1. Jetpack架构组件 (一)-- Android Jetpack 简介

    前言 Android 已经发展十多年了,可以说是比较成熟的技术了,一开始时框架很少,也没有什么规范,所有的代码都是要自己写,比如网络请求,数据库操作,数据解析等等.后来出现了一些框架来帮助开发者快速进 ...

  2. Android Jetpack简介

    文章目录 Android Jetpack简介 Architecture 架构组件 Foundationy 基础组件 Behavior 行为组件 UI 界面组件 Android Jetpack简介 Je ...

  3. Android Jetpack架构组件之 Room(使用、源码篇)

    2019独角兽企业重金招聘Python工程师标准>>> 1.前言 最近简单看了下google推出的框架Jetpack,感觉此框架的内容可以对平时的开发有很大的帮助,也可以解决很多开发 ...

  4. Android Jetpack组件之WorkManger使用介绍

    1.前言 最近简单看了下google推出的框架Jetpack,感觉此框架的内容可以对平时的开发有很大的帮助,也可以解决很多开发中的问题,对代码的逻辑和UI界面实现深层解耦,打造数据驱动型UI界面. A ...

  5. Android Jetpack组件之Navigation使用-源码

    1.前言 最近简单看了下google推出的框架Jetpack,感觉此框架的内容可以对平时的开发有很大的帮助,也可以解决很多开发中的问题,对代码的逻辑和UI界面实现深层解耦,打造数据驱动型UI界面. A ...

  6. Android Jetpack组件之 Room使用-源码

    1.前言 最近简单看了下google推出的框架Jetpack,感觉此框架的内容可以对平时的开发有很大的帮助,也可以解决很多开发中的问题,对代码的逻辑和UI界面实现深层解耦,打造数据驱动型UI界面. A ...

  7. Android Jetpack组件之 Paging使用-源码

    1.前言 最近简单看了下google推出的框架Jetpack,感觉此框架的内容可以对平时的开发有很大的帮助,也可以解决很多开发中的问题,对代码的逻辑和UI界面实现深层解耦,打造数据驱动型UI界面. A ...

  8. Android Jetpack组件之 LiveData使用-源码

    1.前言 最近简单看了下google推出的框架Jetpack,感觉此框架的内容可以对平时的开发有很大的帮助,也可以解决很多开发中的问题,对代码的逻辑和UI界面实现深层解耦,打造数据驱动型UI界面. A ...

  9. Android Jetpack组件之ViewModel使用

    1.前言 最近简单看了下google推出的框架Jetpack,感觉此框架的内容可以对平时的开发有很大的帮助,也可以解决很多开发中的问题,对代码的逻辑和UI界面实现深层解耦,打造数据驱动型UI界面. A ...

最新文章

  1. js ftpclient linux server,Node.JS用Socket实现FTP Server服务器和Client客户端
  2. 我要放弃RedHat Linux了
  3. django博客项目8:文章详情页
  4. perl中Net::FTP帮助文档
  5. 福利 | 全网疯传免费领,一整套算法课程,拿走不谢!
  6. 最常用计算机机箱,电脑机箱的常用材质是什么?
  7. python输入三次密码程序_请教各位大神,为啥以下代码输入修改密码后连输错三次还是能输入...
  8. oracle密码重用,关于Oracle 9i数据库密码重用规则分析
  9. 如何编写高质量的代码二 - 类的设计
  10. while求和java,while语句基本练习(求和思想,统计思想)
  11. 什么是RIA技术,RIA技术概览
  12. 刘备的仁义 ——品《三国演义》
  13. 双料大奖 | 奇点云获评「年度数字化创新最佳实践奖」「年度数字化服务最值得信赖品牌奖」
  14. ESP32入门之程序烧录:烧录错误总结
  15. 解决高度塌陷的几种方法
  16. Springboot课程教学平台设计与实现4mu05计算机毕业设计-课程设计-期末作业-毕设程序代做
  17. KEIL软件错误代码及错误信息
  18. Onvif协议PTZ服务规范(一)PTZ Service Specification
  19. GitLab官网安全更新(2022-06-30)
  20. 不得不知道的一些Java学习资料

热门文章

  1. 【计算机网络】Socket编程
  2. 《2006_ICPR_Low Resolution Character Recognition by Image Quality Evaluation》阅读笔记
  3. 详细理解 https 单向认证和双向认证原理
  4. SiamCAR: Siamese Fully Convolutional Classification and Regression for Visual Tracking
  5. 微信PC电脑桌面端多账号登录微信多开方法
  6. 高性能Golang研讨会【精】
  7. RabbitMQ学习笔记:高级特性TTL(过期时间)
  8. 销毁echart的图表实例
  9. Android GoogleMap接入
  10. 六款Android 应用的自动化测试工具