概览
借助人脸识别身份验证功能,用户只需将自己的面孔对准设备即可将其解锁。Android 10 增加了对一种新的人脸识别身份验证堆栈的支持,这种堆栈可安全处理摄像头帧,从而在支持的硬件上进行人脸识别身份验证时保障安全和隐私。Android 10 还提供了一种简单的安全合规实现方法,以支持通过应用集成来完成交易(例如网上银行或其他服务)。
架构
BiometricPrompt API 包括人脸识别、指纹识别和虹膜识别在内的所有生物识别身份验证方法。Face HAL 会与以下组件交互。
图 1. 生物识别堆栈
FaceManager
FaceManager 是一个私有接口,用于维护与 FaceService 之间的连接。Keyguard 通过该接口访问具有自定义界面的人脸识别身份验证硬件。应用无权访问 FaceManager,必须改为使用 BiometricPrompt。
FaceService
该框架实现用于管理对人脸识别身份验证硬件的访问权限。它包含基本的注册和身份验证状态机以及各种其他辅助程序(例如枚举程序)。出于稳定性和安全性方面的考虑,不允许在此进程中运行任何供应商代码。所有供应商代码都通过 Face 1.0 HIDL 接口访问。
faced
这是一个 Linux 可执行文件,用于实现供 FaceService 使用的 Face 1.0 HIDL 接口。它会将自身注册为 IBiometricsFace@1.0,以便 FaceService 能够找到它。
实现
Face HIDL
如需实现 Face HIDL,您必须在某个供应商专用库中实现 IBiometricsFace.hal 的所有方法。
错误消息
错误消息由回调程序发送,并且在消息发送后,状态机会返回到闲置状态。大多数消息都有面向用户的相应字符串,以将相关错误通知用户,但并非所有错误都有面向用户的字符串。如需详细了解错误消息,请参阅 types.hal。所有错误消息均表示某种终止状态,也就是说框架假定 HAL 会在发送错误消息后返回到闲置状态。
采集消息
注册或身份验证期间会传递采集消息,目的是指导用户成功完成注册或身份验证。每个序数在 FaceAuthenticationManager.java 文件中都有一条关联消息。只要提供相应的帮助字符串,就可以添加供应商专用消息。采集消息本身并不表示终止状态,HAL 应根据需要发送尽可能多的消息以完成当前的注册或身份验证过程。如果某条采集消息引发终止状态而使系统无法进一步执行操作,则 HAL 应该在采集消息之后显示错误消息,例如,图片过暗且保持过暗状态而使系统无法进一步执行操作的情况。在这种情况下,在多次尝试仍无进展之后可以发送 UNABLE_TO_PROCESS。
硬件
设备要满足 Android 10 安全系数较高的生物识别技术要求,就必须采用安全的硬件来确保人脸数据的完整性以及进行最终的身份验证比较。Android 兼容性定义文档 (CDD) 列出了所需的安全级别以及可接受的欺骗接受率 (SAR)。不仅需要可信执行环境 (TEE) 来确保处理和识别的安全,还需要安全的相机硬件来防止人脸识别身份验证过程中出现的注入式攻击。例如,图片数据的相关内存页可享有特权并标记为只读,因此只有相机硬件才能更新这些内存页。理想情况下,除 TEE 和硬件外,其他任何进程都不应访问这些内存页。
由于人脸识别身份验证硬件之间的差异很大,因此必须开发特定于硬件的驱动程序来实现人脸识别身份验证,具体取决于特定的设备架构。因此,faced 没有参考实现。
方法
以下均是异步方法,必须立即返回到框架,否则会导致系统运行速度变慢,并且可能导致监控程序重置。建议使用包含多个线程的消息队列,以免阻塞调用程序。所有 GET 请求都应尽可能缓存信息,将调用程序被阻塞的时间缩至最短。
方法
说明
setCallback()
由 FaceService 调用,以使所有消息回归自身。
setActiveUser()
设置为其应用所有后续 HAL 操作的活跃用户。在再次调用该方法之前,始终针对此用户进行身份验证。
revokeChallenge()
通过使 generateChallenge() 生成的质询代码无效来完成安全交易。
enroll()
注册用户的人脸。
cancel()
取消当前操作(例如注册、身份验证、移除或枚举)并将 faced 返回到闲置状态。
enumerate()
枚举与活跃用户关联的所有人脸模板。
remove()
移除与活跃用户关联的某个或所有人脸模板。
authenticate()
对活跃用户进行身份验证。
userActivity()
仅应在 HAL 处于“正在进行身份验证”或“备用”状态时使用此方法。在 HAL 未处于其中一种状态时使用此方法会返回 OPERATION_NOT_SUPPORTED。在 HAL 已在进行身份验证时调用此方法可能会延长系统查找人脸的时间。
resetLockout()
如果识别时被拒绝的次数过多,faced 需要进入锁定状态(LOCKOUT 或 LOCKOUT_PERMANENT)。进入锁定状态后,需要将剩余时间发送到框架以向用户显示。就像 setFeature() 一样,此方法需要有效的硬件身份验证令牌 (HAT) 才能安全重置内部状态。重置锁定仅针对当前用户。
要点:调用上述方法应插入一条消息并返回。请务必使上述方法立即返回到闲置状态。
其余三个方法均为同步方法,应将其阻塞时间缩至最短以免拖延框架。
方法
说明
generateChallenge()
生成唯一且能够确保加密安全性的随机令牌,以指明安全交易已开始。
setFeature()
为当前用户启用或停用某项功能。出于安全方面的考虑,此方法需要 HAT 根据上述质询代码检查用户的 PIN 码/解锁图案/密码
getFeature()
检索该功能的当前启用状态,默认指明或对上述 setFeature() 的调用。如果 Face ID 无效,则实现必须返回 ILLEGAL_ARGUMENT
getAuthenticatorId()
返回与当前人脸集关联的标识符。每当添加人脸时,此标识符都必须发生变更
状态图
框架要求 faced 遵循以下状态图。
图 2. 人脸识别身份验证状态流程