Android指纹从入门到"放弃"

Android指纹从入门到"放弃"

一、背景

Android在23(Android M)上新增了对指纹识别的硬件支持,应用可以通过调用系统Api实现指纹验证相关功能,相对于传统的手势,密码等验证方式,指纹验证安全性更高,速度也更快。

二、业界方案

1.1、FIDO

FIDO是CFCA提出的一种生物认证标准,通过FIDO sdk、手机硬件、FIDO后台构成了一套指纹验证解决方案,保证指纹验证流程不被篡改,该方案通过与手机厂商合作,客户端侧对秘钥的操作均在TEE环境中,安全性高。FIDO方案不仅需要客户端集成sdk,应用后台也需要植入FIDO后台sdk,业务流程需要由FIDO客户端sdk、应用客户端、应用后台、FIDO后台sdk、FIDO服务端五方共同完成,较为复杂。一般针对指纹支付等安全性级别较高的场景。

1.2、TENCENT SOTER

TENCENT SOTER是一种生物认证标准,同时也是腾讯生物认证平台。TENCENT SOTER主要着眼于如何安全、高效并简单地使用你设备上的传感器进行鉴权——最重要,也是目前用到最多的就是指纹传感器。TENCENT SOTER与FIDO一样,会通过与手机厂商的合作,客户端侧相关秘钥操作均在TEE环境中。TENCENT SOTER采用三级秘钥方案,应用方后台不需要接入sdk,接入相对简单。一般针对指纹支付等安全性级别较高的场景。

1.3、Android Framework

Android系统提供的相关生物识别验证接口,应用可以通过对这些接口的调用实现Android指纹验证功能,但安全性较低,容易被攻击者绕过,若需要使用在支付等安全性级别较高的场景,需要配合额外的安全保护逻辑),且存在较多的兼容性问题。

三、Android原生方案

3.1、Api介绍

  • Android 在23(Android M)上新增了指纹识别Api:FingerprintManager,第三方app可以通过对该类的开发与使用,实现指纹相关功能。开发者通过该Api打开指纹认证流程时,系统仅会打开设备的指纹模块监听,并不会有UI相关展示,需要开发者根据自身App要求弹出对应的交互流程。
  • Android在28(Android P)上新增了生物识别Api:BiometricPrompt,并推荐开发者使用最新的生物识别Api替换原来的FingerprintManager,该Api不仅只针对指纹,而是囊括了指纹、人脸、虹膜等生物特征识别,但现阶段只开放了指纹相关功能。开发者使用该Api进行指纹认证流程时,系统在会打开设备的指纹模块监听的同时,还会弹出一个系统级的Dialog提示用户正在进行指纹解锁流程。

FingerprintManager与BiometricPrompt中,指纹验证涉及的调用接口十分类似,本文就以BiometricPrompt为例

  • 判断当前设备是否可以进行生物识别

BiometricManager : canAuthenticate () (29)

  • 设置弹窗系统弹窗title

BiometricPrompt.Builder(28): setSubtitle (CharSequence subtitle)

  • 设置系统弹窗的取消按钮

BiometricPrompt.Builder(28): setNegativeButton (CharSequence text, Executor executor,DialogInterface.OnClickListener listener)

  • 开启指纹认证流程,开发者调用该Api后,生物识别传感器将打开,同时屏幕会弹出一个系统级Dialog提示用户正在进行生物识别。

BiometricPrompt (28): authenticate (BiometricPrompt.CryptoObject crypto, CancellationSignal cancel, Executor executor, BiometricPrompt.AuthenticationCallback callback)

  • crypto 成功进行生物验证后将使用该对象验证本次流程的可靠性
  • cancel 可以用于结束本次验证流程的对象
  • executor 本次验证流程的执行者(线程相关)
  • callback 用于接收本次验证流程结果的回调
  • 指纹验证流程出现不可重试的错误时(如验证5次不通过),系统会中止指纹验证流程,并在一定时间内不可再调起。

BiometricPrompt.AuthenticationCallback(28): onAuthenticationError(int errorCode, CharSequence errString)

  • errorCode 错误码
  • errString 错误信息
  • 系统识别出指纹,但该指纹未匹配指纹库中指纹

BiometricPrompt.AuthenticationCallback(28): onAuthenticationFailed()

  • 指纹验证流程出现可重试的错误时(如手指滑动过快)

BiometricPrompt.AuthenticationCallback(28): onAuthenticationHelp(int helpCode, CharSequence helpString)

  • helpCode 错误码
  • helpString 错误信息
  • 指纹验证成功时调用

BiometricPrompt.AuthenticationCallback(28): onAuthenticationSucceeded(BiometricPrompt.AuthenticationResult result)

  • result 包含authenticate方法中的crypto等对象

3.2、版本兼容

  • Api23-27:所有功能实现都使用FingerprintManager,弹窗由开发者自定义,非系统弹窗
  • Api28:判断当前设备是否可以进行指纹识别,需要使用FingerprintManager;进行指纹验证流程,需要使用BiometricPrompt
  • Api29+:判断当前设备是否可以进行指纹识别,需要使用BiometricManager;进行指纹验证流程,需要使用BiometricPrompt
  • 也可以使用androidx.biometric包,在大于Api23的所有的Android版本都使用同一套接口,但需要解决将support包全部转为androidx包等一系列问题。

3.3、存在问题

3.3.1、UI兼容性问题(针对BiometricPrompt)

由于FingerprintManager是开发方自定义UI,因此不存在UI兼容性问题。BiometricPrompt使用的是系统弹窗,开发者不可以自定义弹窗样式,仅可以设置弹窗上的相关文案及按钮点击事件。因此不同厂商对系统Dialog样式的不同实现,会导致指纹验证流程中出现不同的交互。

华为mate20 Android29(屏下指纹)


WechatIMG3.jpeg

小米Mix2s Android28


WechatIMG1.jpeg

三星Galaxy S8+ Android28


WechatIMG2.jpeg

OPPO R15X Android28


WechatIMG4.jpeg

3.3.2、功能性问题

  • 1、在OPPO R15X上(Android28),BiometricDialog弹出后,点击取消按钮的点击事件没有分发给第三方App。
  • 2、原生系统,当BiometricDialog弹出后,按下Menu/HOME键,指纹验证申请已经取消,但是弹框BiometricDialog无法消失。
  • 3、原生系统,若操作不当,存在在锁屏状态下弹出Dialog导致无法解锁,用户无法进入Launcher进行UI交互的风险。出现这种“意外” 的情况是,比如:UI处在进入申请BiometricPrompt生物识别弹框上下文,由于网络/apk性能等种种原因,并未立马申请弹出Dialog,突然遇到Power熄屏,或者亮屏超时,立马按下Power点亮屏幕。此时三方应用处在onPaused状态,但是异步发起生物识别申请,导致"意外"发生。

3.3.3、安全性问题

上文介绍的指纹验证Api:public void authenticate (BiometricPrompt.CryptoObject crypto, CancellationSignal cancel, Executor executor, BiometricPrompt.AuthenticationCallback callback),若对第一个crypto参数使用方式不正确,则存在指纹验证被绕过的风险

流程

第一步:调用authenticate方法,弹出UI提示用户输入指纹-->第二步:用户验证指纹,用户验证指纹成功-->第三步:调用AuthenticationCallback.onAuthenticationSucceeded方法,执行解锁后逻辑

漏洞

  • root手机
  • 通过hook重写authenticate方法,在authenticate方法中直接调用AuthenticationCallback.onAuthenticationSucceeded方法。若应用未正确使用crypto参数,则此方案绕过第二步验证指纹。

3.4 解决方案

3.4.1、UI兼容性问题

若使用BiometricPrompt则具体UI无法由第三方开发者指定,若要统一UI,建议使用FingerprintManager

3.4.2、功能性问题

若使用BiometricPrompt,则弹窗为系统级弹窗,其展示与消失逻辑无法由
第三方开发者指定,第三方开发者唯一可以控制的就是保证调起指纹识别流程(即调用authenticate方法)的时机正确。

3.4.3、安全性问题

方案一

流程:

  • 在调用authicate方法前,通过AndroidKeyStore生成一把对称秘钥,加密串A得到串B,并用这把秘钥生成crypto对象传入authicate方法。
  • 在AuthenticationCallback.onAuthenticationSucceeded方法中取出crypto对象,并解密串B得到C,比较A与C,若相等则通过。
  • 若跳过验证流程直接调用AuthenticationCallback.onAuthenticationSucceeded,则比较A与C会失败。

问题与总结:

  • 攻击者若在流程中劫持到秘钥,并生成crypto对象传入,则仍可以绕过
  • 兼容性问题小,对安全级别要求低的场景推荐使用

方案二

流程:

  • 在调用authicate方法前,通过AndroidKeyStore生成一对非对称秘钥,设置要访问这把秘钥对必须在生物识别成功之后,利用公钥加密串A得到串B,生成crypto对象传入authicate方法。
  • 在AuthenticationCallback.onAuthenticationSucceeded方法中取出crypto对象,利用私钥解密串B得到C,比较A与C,若相等则通过。
  • 若跳过验证流程直接调用AuthenticationCallback.onAuthenticationSucceeded,则在访问私钥解密数据时,系统会抛出android.security.keystore.KeyPermanentlyInvalidatedException: Key permanently invalidated,无法继续执行。

问题与总结:

  • 该方案相对方案一更加安全,通过AndroidKeystore保证指纹验证流程的不被绕过
  • 由于Android碎片化问题,该方案在使用那把非对称秘钥时,有非常多的兼容性问题

四、总结

上文详细介绍了Android系统提供的指纹接口的使用方式以及使用过程中存在的问题,对比FIDO及TENCENT SOTER方案,我们可以得出以下图表

比较项 TENCENT SOTER Android Framework FIDO
接入成本 较低
是否需要联网 依赖方案
兼容性问题
用户隐私保护 好(不会获取指纹图案) 好(不会获取指纹图案) 好(不会获取指纹图案)
安全性 依赖方案

综合以上,云闪付在对安全性要求相对较低的场景(如解锁),使用Android原生指纹接口配合AndroidKeystore实现,无需联网,速度快,兼容性问题少;在对安全性要求较高的场景(如支付),选择采用第三方FIDO解决方案,兼容性问题少,安全性高。

你可能感兴趣的:(Android指纹从入门到"放弃")