目录

  • 锁屏
  • 选择一个钥匙
  • 密钥存储
  • 密钥生成
  • 密钥管理
  • 加密与解密
  • 使用范例
  • 下一步是什么
  • 安全提示

锁屏

如果要保护数据,请保护设备。

为了更加安全,在提供对任何应用程序功能的访问权限之前,我们可以要求用户设置其设备的锁屏(如果尚未设置)。另外,我们将在本系列的稍后部分中介绍的其他一些功能(例如指纹)也需要设置锁定屏幕。

还有一项特殊的系统服务-KeyguardManager可以帮助我们完成此任务。

isDeviceSecure 方法-检查设备是否用PIN,码型或密码保护。可从API 23获得。

isKeyguardSecure 方法-检查键盘锁是否由PIN,图案或密码保护,或者当前是否已锁定SIM卡。可从API 16获得。这不是最佳选择,因为它还在检查SIM卡是否被锁定,但总比没有好。

秘密守护者,注册屏幕

现在,在onStart()“活动”中,只需检查设备是否已使用锁定屏幕进行保护,如果没有,则显示安全警报。

完整的源代码在这里。

选择一个钥匙

现在,当使用锁屏保护设备时,我们可以集中精力于应用程序敏感的数据保护,例如用户密码和机密(请参阅Android中的加密(第1部分),示例项目)。我们已经知道加密将用于此目的。首先,我们需要选择要使用的密钥(对称,非对称)和算法。

我们也知道,对称密钥可从Android 23+ API获得,而非对称密钥可从18+ API获得(请参阅Android中的加密(第1部分),Android密钥存储)。我们的选择是可以预测的,我们将使用非对称密钥,但是仍然选择哪种算法?让我们在文档中寻求帮助:

Android密钥存储系统。可用的密码转换,格式为:算法/模式/填充

RSA-我们可以Cipher在API 18+设备上用于Android密钥存储非对称密钥的唯一一种可用算法。

密钥存储

在Android上,加密密钥存储在中KeyStore

还有一种架构getInstance("type")方法,该方法KeyStore通过遍历已注册安全提供者的列表(从最喜欢的 一个)开始创建具有给定类型的实例我们将搜索“ AndroidKeyStore ”类型。

还有另一个KeyStoreFabric方法:— 从指定的Provider 返回指定类型的对象。getInstance("type", "provider")KeyStore

基本上称之为:

val keyStore = KeyStore.getInstance(“ AndroidKeyStore”)keyStore.provider.name // AndroidKeyStore
keyStore.type // AndroidKeyStorekeyStore.provider.name // AndroidKeyStore
keyStore.type // AndroidKeyStore

与调用几乎相同:

val provider =“ AndroidKeyStore”
val keyStore = KeyStore.getInstance(提供者,提供者)keyStore.provider.name // AndroidKeyStore
keyStore.type // AndroidKeyStorekeyStore.provider.name // AndroidKeyStore
keyStore.type // AndroidKeyStore

但是请注意,如果在不同的提供程序中有多个具有相同名称的注册类型,则getInstance(“type”)method将返回它们中的第一个匹配结果。这有两个不同的方面:

  • 您(或设备供应商)可以创建自己的Provider,并将其设置为最喜欢的,只需设置其位置即可(在本系列文章的后面部分中,您将了解如何进行设置)。从理论上讲,这可能会导致一些混乱,您会出错,而不是预期的密钥存储类型。
  • 另一方面,这种方法可用于解决一些兼容性问题,即系统将AndroidKeyStore在另一个Provider中添加新类型的实现,并保持相同的名称约定(还有另一个系统Provider,称为“ AndroidKeyStoreBCWorkaround”,我们将在“加密和解密”段落)。这使我们可以在不同的API上保持相同的工作代码,这很酷。

getInstance(“type”)到目前为止,该方法一直对我有效。文档样本也引用了此方法,因此,我建议您使用它来获取KeyStore实例,而不是其他getInstance(“type”, “provider”)方法。


如果您仍然有疑问或某些功能无法正常使用,请使用keyStore.provider.namekeyStore.type方法来验证所创建KeyStore实例的详细信息。


获取实例之后,您必须调用load(loadStoreParameter)方法,该方法将基于提供的加载密钥存储数据ProtectionParameter

保护参数可用于检查密钥存储数据的完整性,或用于保护敏感密钥存储数据(例如PrivateKey)的机密性。

对于AndroidKeyStore提供者,我们只需要null作为参数传递,系统将根据我们的应用程序标识符将数据加载到后台。

密钥生成

在Android上,非对称加密密钥的创建方式KeyPairGenerator如下:

与密钥存储区类似,有一种fabric getInstance(“algorithm”, “provider”) 方法,使用该方法来创建密钥。

该方法还有另一个简化版本getInstance(“algorithm”)不要使用它。这种方法在所有现有的提供程序中搜索算法,与密钥库不同,密钥存储区我们使用的是非常独特的“ AndroidKeyStore ”类型,算法名称在不同的提供程序中很常见(“ RSA ”几乎无处不在)。在这里,我们需要显式定义我们要使用的提供程序。


KeyPairGenerator实例必须使用规范初始化。在M之前KeyPairGeneratorSpec应使用class提供它:

在Android密钥存储区中,每个密钥必须具有一个标识符-alias。如果您尝试使用已存在的别名将密钥保存到密钥存储中,它将被新密钥覆盖。使用setAlias()builders方法提供别名。


非对称密钥必须使用证书签名。它主要用于客户端-服务器通信中,其中客户端(或服务器)正在验证证书,以确保服务器确实是他声称的身份(而不是中间人)。没有证书,您将无法保存非对称密钥。

如果在一个应用程序中都希望同时使用公钥和私钥,则只需创建一个伪造的,自签名的证书即可。

证书需要一个开始日期和结束日期(有效期),可以使用setStartDatesetEndDate构建器方法进行设置。另外,您还需要提供序列号和证书主题,可以与setSerialNumberand setSubjectbuilder方法一起使用。

伪造的自签名证书的打印输出:

<span style="color:#292929">数据:版本:3(0x2)序列号:1(0x1)
签名算法:sha256WithRSAEncryption 颁发者:CN = MASTER_KEY CA证书有效期:2017年11月7日12:59:12 GMT 不之后:Nov 7 12:59:12 2037 GMT 主题:CN = MASTER_KEY CA证书主题公钥信息:公钥算法:rsaEncryption 公钥:(2048位)模数:00:b8:bf:51:10:fc:8c:7f:39:31:cc:是:43:43:81:f1:8b:5a:55:94:c4:5c:8c:56:51:5a:63:85:36:87:ff:3e:f2:a2:3b:9c: b0:e0:a8:3d:5e:1b:41:9c:00:6e:02:b2:42:d0:9c:e8:2f:4a:52:62:ac:7d:8e:75:a0:5e:58:57:ae:a5:2e:2c:48:0c:7f:cc:1a:95:46:2b:2b:a7:5e:96:69:d7:98:b8:32: 92:7d:80:e9:19:07:da:52:1a:29:de:e1:fb:56:43:60:7f:28:ce:23:ca:ee:12:11:17: 1d:0b:86:76:1a:f1:99:69:81:01:b0:d3:2c:6b:e7:ac:4f:f2:f7:97:88:ef:94:7a:28:a4:66:6e:d5:29:67:84:12:2e:d3:d3:d7:a6:f6:d4:ed:81:a4:24:9b:f2:2a:77:16:d9: 0d:62:31:cd:cc:c4:f0:fc:be:8d:6a:b4:14:fc:26:6b:a0:06:79:95:40:68:0e:da:5e: 25:69:f9:36:fb:eb:35:a5:e2:63:81:f0:88:c2:8e:be:fc:8d:65:ce:99:7f:88:cf:af:50:9a:59:77:dc:cd:76:a9:8c:64:de:e8:57:3b:40:bf:72:21:2c:60:3d:e0:7b:dd:1e: 01:81:3a:24:81:d4:a9:e2:e8:af:80:f6:00:f6:7f:fd:9f:48:d2:f7:96:d1 指数:65537(0x10001)
签名算法:sha256WithRSAEncryption 1f:f6:40:99:1c:c1:62:19:89:1f:35:fb:18:7e:93:1e:99:8c:84 :a4:cd:7b:93:c7:23:46:7c:9a:50:aa:a5:f2:34:07:82:ef:45:28:ac:50:6c:4e:a2:92 :35:e4:75:97:12:47:ef:80:e4:6d:b2:61:e4:4b:7f:79:4c:7c:ee:87:a9:ad:23:a1:ec :e9:1a:2c:8e:0c:04:61:6c:4b:f3:6e:a6:ff:3e:bb:ad:45:5a:c5:0f:ae:4e:7c:d5:93 :d0:98:69:0d:3e:bc:22:1f:85:11:db:0e:80:66:ff:58:4d:57:2f:64:cb:f8:c0:07:c9 :91:f9:7a:a8:48:0e:f6:2a:08:d9:db:89:8c:5b:24:a7:ad:8a:08:f5:aa:3e:ac:99:31 :15:9d:93:4f:d1:c5:7b:2d:41:f2:7e:99:5b:38:b8:1d:1a:63:d2:57:34:10:4b:06:95 :39:41:df:22:38:8d:a9:4f:9b:05:86:46:09:02:51:fc:41:39:54:ca:dd:1d:8e:34:77:01:1b:87:51:22:9c:4b:e8:ae:d5:8d: d8:e6:e1:ba:18:41:94:ef:64:b6:63:d9:2e:06:ea:1e:ae:80:11:5f:71:b2:28:b0:cc: 4e:18:5e:3f:4f:28:ae:4f:90:57:1e:41:51:36:02:94:ad:9b:7d:03:25:e7:f7:8a:4d: 26</span>

提供关键细节后,初始化KeyPairGenerator使用规范实例initialize(specification)方法。


在MKeyGenParameterSpec被介绍。它用于初始化非对称和对称密钥。KeyPairGeneratorSpec不推荐使用。

KeyGenParameterSpec要求指定密钥用法的目的。例如,使用创建的密钥KeyProperties.PURPOSE_ENCRYPT不能用于解密。

另外,您必须指定要与此密钥一起使用的阻止模式和加密填充(请参阅“ 加密,模式和填充)。使用setBlockModessetEncryptionPaddings构建方法。

不再需要手动定义伪造的证书,KeyGenParameterSpec它将自动执行。您仍然可以使用以下方法自定义默认值:


最后,当KeyPairGenerator实例使用规范初始化时,使用generateKeyPair()方法创建私钥-公钥对。在Android Key Store提供程序中,此方法将自动 保存 键入 KeyStore

密钥管理

KeyStore 提供的方法可以帮助我们管理保存的密钥:

getKey(“ alias”,“ password”) —返回具有给定别名的键,如果给定别名不存在或未标识与键相关的条目,则返回null。在Android Key Store中,不需要密码。

getCertificate(“ alias”) —返回证书,如果给定的别名不存在或不包含证书,则返回null。

deleteEntry(“ alias”) —删除具有给定别名的密钥。KeyStoreException
如果无法删除该条目,将被抛出。

完整的源代码在这里。

加密与解密

在Android上,加密和解密是通过进行的Cipher

有一种结构getInstance(“transformation”)方法,即在现有的提供程序之间搜索给定的转换(就像我们在上面回顾的其他加密组件中一样),应将其用于创建Cipher实例。

转换表示将用于加密或解密的算法,格式为:“算法/模式/填充”。


getInstance(“transformation”, "provider")这里还存在可以显式指定Provider的Method 。但是请注意,您不应将其与Cipher一起使用。

val转换=“ RSA / ECB / PKCS1Padding”
val提供程序=“ AndroidKeyStore”// API 19
val cipher:Cipher = Cipher.getInstance(transformation)
cipher.provider.name // AndroidOpenSSL// API 23,24
val cipher:Cipher = Cipher.getInstance(transformation)
cipher.provider.name // AndroidKeyStoreBCWorkaroundval cipher:Cipher = Cipher.getInstance(transformation,provider)
//抛出java.security.NoSuchAlgorithmException:
//提供者AndroidKeyStore不提供RSA / ECB / PKCS1Padding// API 19
val cipher:Cipher = Cipher.getInstance(transformation)
cipher.provider.name // AndroidOpenSSL// API 23,24
val cipher:Cipher = Cipher.getInstance(transformation)
cipher.provider.name // AndroidKeyStoreBCWorkaroundval cipher:Cipher = Cipher.getInstance(transformation,provider)
//抛出java.security.NoSuchAlgorithmException:
//提供者AndroidKeyStore不提供RSA / ECB / PKCS1Padding

如您所见,从技术上讲,AndroidKeyStore提供程序不向密码提供RSA算法。而是有AndroidOpenSSLAndroidKeyStoreBCWorkaround提供者,他们知道如何AndroidKeyStore为该算法使用提供者密钥。


要开始使用Cipher实例,我们需要使用Key将其初始化以进行特定操作。使用init(mode, key)方法with对其Cipher.ENCRYPT_MODE进行初始化以进行加密:

或使用init(mode, key)with方法Cipher.DECRYPT_MODE来初始化用于解密的密码:

初始化后,使用doFinal(data)方法,使用此密码来处理加密或解密的数据。

您可以根据需要多次重新初始化创建的密码实例。

完整的源代码在这里。

使用范例

总结一下我们正在讨论的所有内容,让我们尝试加密和解密简单的“ Hello World”消息:

完整的源代码在这里。

【译】Android中的安全数据— Android中的加密(第2部分)相关推荐

  1. pandas使用dt.day_name函数从dataframe(Series)中的日期数据列中抽取日期对应的星期信息生成新的数据列(Monday、Sunday)

    pandas使用dt.day_name函数从dataframe(Series)中的日期数据列中抽取日期对应的星期信息生成新的数据列(Monday.Sunday) 目录

  2. 【译】Android中的安全数据— Android中的加密(第1部分)

    目录 Java密码体系结构 Android Key Store 样例项目 下一步是什么 安全提示 Java密码体系结构 Android建立在Java密码体系结构(JCA)的基础上,该体系结构提供了用于 ...

  3. 【Android 逆向】修改运行中的 Android 进程的内存数据 ( Android 命令行中获取要调试的应用进程的 PID | 进程注入调试进程内存的 so 库 )

    文章目录 一.Android 命令行中获取要调试的应用进程的 PID 二.进程注入调试进程内存的 so 库 一.Android 命令行中获取要调试的应用进程的 PID 前置博客 [Android 逆向 ...

  4. android 清除应用程序数据,Android – 通过“清除数据”设置选项阻止正在删除的应用程序数据或文件...

    我有一个Android应用程序,可以在少量文件中存储大约25-40K的私有应用程序数据. 默认情况下,系统将这些文件存储在目录/ data / data /'my app package'/ file ...

  5. android动态更新数据库数据,Android数据库更新——上万条数据的插入

    在实际情况下,很可能遇到会向一个表中插入10万条数据,而这样的数据库更新,如果用寻常的方式,在SQLiteOpenHelper.onUpdate()方法中不断的执行SQL语句,那么效率是可想而知的,甚 ...

  6. python在json文件中查找指定数据_Python中json的取值 如何使用python提取json中指定字段的数据...

    python中为什么用json有什么作用 如何用python读取json里面的值啊我爱你,所以我给了你伤害我的权力,只要我能忍受,我会一直陪伴着你,但你不能伤害我太多. 数据如下,我想要读取name. ...

  7. mysql中如何统计数据_mysql中的数据统计方法

    1 数据统计 使用COUNT()函数计算表中的数据数目(比如emp表中的员工数目) mysql> select count(*) from emp; 查询结果如下: +----------+ | ...

  8. 中琅可变数据软件中如何实现叠印效果

    在广告印刷行业或者数码印刷.防伪印刷中,对颜色的印前设置和后期印刷结合处理从来就是不可忽视的,其中叠印的效果应用于很多印刷场景,比如:UV.烫金.印刷黑色和某些专色,它常用于多种数码印刷或者防伪印刷设 ...

  9. 【Android 逆向】修改运行中的 Android 进程的内存数据 ( Android 系统中调试器进程内存流程 | 编译内存调试动态库以及调试程序 )

    文章目录 一.Android 系统中调试器进程内存流程 二.编译内存调试动态库以及调试程序 三.博客资源 一.Android 系统中调试器进程内存流程 修改游戏运行中的内存 , 游戏运行之后 , 游戏 ...

最新文章

  1. linux下的打包与压缩
  2. linux命令0424
  3. mysql locking_Mysql next-key locking,读锁,写锁
  4. ECCV 2020 《Propagating Over Phrase Relations for One-Stage Visual Grounding》论文笔记
  5. mysql执行计划字段解析_MySQL执行计划解析
  6. pyqt5从子目录加载qrc文件_【JVM系统学习之路】一篇看懂类加载
  7. 用计算机演奏打上花火,米津玄师打上花火歌词中文谐音(最好要简单全面)
  8. nodejs搭配phantomjs highcharts后台生成图表
  9. win7关机快捷键_1个U盘+1款软件,电脑小白也能在家轻松重装win7系统
  10. 【学习笔记】第二章——线程与多线程模型
  11. 设计模式之单例模式(一)
  12. VB6获取本机所有IP地址公用函数
  13. 201506110135陈若倩词法分析实验报告
  14. Visual Studio 2015打开ASP.NET MVC的View提示“Object reference not set to an instance of an object“错误的解决方案
  15. 索引大小对语句执行速度的影响
  16. ADT(abstract data types)抽象数据类型
  17. Scratch2exe-ch将sb2文件转换为exe文件
  18. Linux vi 进去命令模式,Linux 下 vi/vim 文本编辑器详细命令使用方法,linux的vi/vim命令vi/vim命令模式,输入模式和末行模式...
  19. 关于“户口,干部身份,职称”等系列问题
  20. input标签 各属性解释

热门文章

  1. 面向对象三大特性,六个原则
  2. 转【查看oracle数据库的连接数以及用户 】
  3. GridView实现自动编号
  4. Git学习笔记:标签管理以及GItHub
  5. R学习笔记:运行时间记录
  6. Python:入门(3)
  7. C++ while(cin>>a) cin输入直到回车结束
  8. ustc小道消息20211213
  9. 科大星云诗社动态20210319
  10. [云炬python3玩转机器学习笔记] 3-1 Jupyter Notebook