目录

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

锁屏

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

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

还有一项特殊的系统服务-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方法一起使用。

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

数据:  版本: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

提供关键细节后,初始化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”消息:

 

完整的源代码在这里。

更多相关文章

  1. android点滴2
  2. 百度地图开发Marker|Polyline隐藏或显示
  3. 解决requestFeature() must be called before adding content错
  4. Mtk Android(安卓)app 默认激活设备管理器
  5. Android(安卓)图像处理(类型转换,比例缩放,倒影,圆角)
  6. Android中集成QQ登陆和QQ空间分享
  7. Android(安卓)中的 requestWindowFeature 收藏
  8. Android(安卓)G711A 音频编解码,去除“吱吱”电流声,附上so下载地
  9. Android(安卓)使用RecyclerView的方法

随机推荐

  1. Fragment嵌套时注意点
  2. video conference s/w
  3. AsyncTask executeOnExecutor
  4. android按钮样式
  5. 百度SDK定位
  6. Timer的使用
  7. Android(安卓)获取网络流量信息
  8. android 4中文件操作
  9. Android漏洞
  10. Android调用系统camera