要求进行用户身份验证才能使用密钥
生成密钥或将密钥导入到
AndroidKeyStore
时,您可以指定密钥仅授权给经过身份验证的
用户使用。用户使用安全锁定屏幕凭据(模式
/PIN/
密码、指纹)的子集进行身份验证。
这是一项高级安全功能,通常仅用于有以下要求的情形:在生成
/
导入密钥后(而不是之前
或当中),应用进程受到攻击不会导致密钥被未经身份验证的用户使用。
如果密钥仅授权给经过身份验证的用户使用,可以将其配置为以下列两种模式之一运行:
经过身份验证的用户可以在一段时间内使用密钥。在用户解锁安全锁定屏幕或使
用
KeyguardManager.createConfirmDeviceCredentialIntent
流程确认其安全锁定屏幕凭据后,
即 可 使 用 此 模 式 中 的 所 有 密 钥 。 每 个 密 钥 的 授 权 持 续 时 间 各 不 相 同 , 并
由
setUserAuthenticationValidityDurationSeconds
在密钥生成或导入时指定。此类密钥只能在
启用安全锁定屏幕时生成或导入(请参阅
KeyguardManager.isDeviceSecure()
)。在安全锁定屏
幕停用(重新配置为“无”、“滑动”或不验证用户身份的其他模式)或被强制重置(例如由
设备管理员执行)时,这些密钥将永久失效。
用户身份验证
会授权与某一密钥关联
的特定加密操作。在此模式中,涉及此类密钥的每
个 操 作 都 需 要 用 户 单 独 授 权 。 目 前 , 此 类 授 权 的 唯 一 方 式 是
指 纹 身 份 验 证
:
FingerprintManager.authenticate
。此类密钥只能在至少注册一个指纹时生成或导入(请参
阅
FingerprintManager.hasEnrolledFingerprints
)。一旦注册新指纹或取消注册所有指纹,这些
密钥将永久失效。
支持的算法
Cipher
KeyGenerator
KeyFactory
KeyPairGenerator
Mac
Signature
SecretKeyFactory
密码
加强密钥安全保护
我们还加入了一个新的
KeyStore
类 ——
StrongBox
,并提供相应的
API
来支持那些提供
了 防 入 侵 硬 件 措 施 的 设 备 , 比 如 独 立 的
CPU
, 内 存 以 及 安 全 存 储 。 您 可 以
在
KeyGenParameterSpec
里进行设置,决定是否把密钥交给
StrongBox
安全芯片来保存。
添加了安全硬件的框图如下:


硬件安全性模块
发布时安装了
Android P
的受支持设备可拥有
StrongBox Keymaster
,这个
Keymaster HAL
的
实现位于一个硬件安全性模块内。 该模块包含自己的
CPU
、安全存储空间、真实随机数生
成器以及抵御软件包篡改和未经授权线刷应用的附加机制。 检查存储在
StrongBox
Keymaster
中的密钥时,系统会通过
可信执行环境
(TEE)
证实密钥的完整性
。
为支持低能耗的
StrongBox
实现,为一部分算法和密钥长度提供了支持:
RSA 2048
AES 128
和
256
ECDSA P-256
HMAC-SHA256 (
支持
8-64
字节密钥长度,含首末值
)
Triple DES 168
使用
KeyStore
类生成或导入密钥时,您需要通过将
true
传递给
KeyGenParameterSpec.Builder
类或
KeyProtection.Builder
类中的
setIsStrongBoxBacked()
函数,指示在
StrongBox Keymaster
中存储密钥的偏好。
注:如果
StrongBox Keymaster
不可用于特定算法和与密钥关联的密钥长度,框架会引发一
个
StrongBoxUnavailableException
Android
的密钥库已经推出很多年了,它为应用开发者提供了一种使用加密密钥进行身份验
证和加密的方式。
密钥库将密钥资料存放在应用的进程空间之外
,因此,密钥资料不会在
可能受到网络钓鱼攻击的情形下被应用意外透露给用户,不会通过其他某种渠道泄漏,也不
会在应用遭到入侵时陷入危险之中。
许多设备也在安全硬件中为密钥库密钥提供基于硬件的安全机制,这种机制将密钥资料完全
存储在
Android
系统之外,因此即使
Linux
内核遭受入侵,密钥资料也不会泄漏。在绝大
多数
Android
设备中,
安全硬件
都是主
CPU
的一种特殊模式,其通过硬件与
Linux
内核
及
Android
用户空间强制隔离。有些设备还使用单独的安全微处理器。
Android
提供的
API
可以让应用确定给定密钥库
密钥是否处于安全硬件
中,但是如果操作
系统受到入侵,这些
API
将变得不可靠。密钥认证让设备的安全硬件可以验证某个非对称
密钥是否处于安全硬件中,从而在
Android OS
遭受入侵时为密钥提供保护。
密钥库历史
密钥库最初在
Android 4.0
中引入,密钥采用用户的密码进行加密。
Android 4.1
添加了使用
设备安全硬件的基础架构。
在
Android 6.0
之前,密钥库仅支持
RSA
和
ECDSA
。在
Android 6.0
中,密钥库得到显著
增强,增加了对
AES
和
HMAC
的支持。此外,加密运算的其他关键要素(例如
RSA
补位
1
和
AES
区块链接
2
模式)也移入安全硬件中。
在
Android 6.0
中,密钥库还能够限制特定密钥的使用方式。可以应用的最有用限制是 用户
身份验证绑定。这种限制允许将密钥的使用“绑定”到用户密码(他们的
PIN
码、图案或
口令)或者指纹。对于密码身份验证绑定,应用开发者可以指定一个超时(以秒为单位)。
如果自用户上次输入密码以来所经历的时间已超过指定时间,安全硬件将拒绝要求使用密钥
的任何请求。指纹绑定密钥在每次使用密钥时都会要求新的用户身份验证。
还可以向
Android 6.0+
密钥应用其他更多技术限制。特别是,在创建或导入密钥时,需要
指定密钥可用于哪些
加密目的(加密、解密、签名或验证)
,为初始化向量或随机数指定补
位与分组加密模式、摘要和熵源以及加密运算的其他详细信息。由于指定的信息以加密方式
永久绑定到密钥资料上,密钥库将不允许以任何其他方式使用此密钥。因此,已经获取应用
或系统控制权限的攻击者无法滥用密钥。为了帮助防止攻击,开发者应为给定密钥指定尽可
能窄的用户范围
Android 7.0
中引入了
Android
密钥库最重要的变更之一。预装
Android 7.0+
并带有安全锁
定屏幕的新发布设备必须具有安全硬件,并支持基于
硬件的密码身份验证和密钥库密钥
。
在
Android 7.0
之前,
安全硬件支持比较分散
,不过在未来几年,这项功能将逐渐统一。
在
Android 8.0
中,
密钥认证
已成为预装
Google Play
的所有新设备的强制选项。
为何使用密钥认证?
假设您正在开发一款应用,该应用让银行客户可以访问其银行余额、交易历史记录和账单支
付系统。安全性至关重要;您肯定不希望捡到用户电话的任何人都能访问用户的银行账户。
一种应对方式是使用用户的网站密码。但是这种方式对用户来说通常不方便,因为网站经常
需要复杂的长密码,在小型触摸屏上输入这类密码不是很方便
借助
Android
密钥库,您可以生成一个
非对称的身份验证密钥
(例如
256
位
ECDSA
密钥),
让每位用户使用他们的复杂网络密码登录一次,然后在银行的客户
账户数据库中注册公钥
。
在用户每次打开应用时,您都可以使用该
ECDSA
密钥执行一次质询
-
响应身份验证协议。而
且,如果您进行密钥身份验证绑定,用户在每次打开应用时还可以使用他们的锁定屏幕密码
或指纹进行身份验证。这样一来,他们可以在自己的电话上使用更简单、更方便的身份验证
机制。
如果攻击者入侵
Android
并尝试提取密钥,他们可能会无功而返,因为
密钥储存在安全硬
件中
。
作为一名应用开发者,您可以利用密钥验证在自己的服务器上验证您的应用请求的
ECDSA
密钥确实位于安全硬件中。请注意,在您的应用中使用验证意义不大;如果
Android OS
未
被入侵并值得信赖,那么您可以直接使用
6.0
中引入的
KeyInfo
类
来确定
密钥
是否处于安全
硬件中。如果系统已被入侵,那么该
API
与您在设备上验证密钥认证的任何尝试都是不可
靠的
请注意,密钥认证与
SafetyNet
认证不同。它们的理念相同,不过认证的对象不同,来源也
不同。
密钥库密钥认证
旨在声明加密密钥位于安全硬件中并且具备指定的某些特性。
SafetyNet
认证旨在声明设备是真实设备(不是模拟器)并且设备正在运行已知软件。
SafetyNet
在幕后也使用密钥库密钥认证,因此,如果您想要了解设备完整性,请使用这种
认证。如果您想要确认您的
密钥位于安全硬件
中,请使用密钥认证
.