Android指紋從入門到"放棄"
一、背景
Android在23(Android M)上新增了對指紋識別的硬件支持,應(yīng)用可以通過調(diào)用系統(tǒng)Api實(shí)現(xiàn)指紋驗(yàn)證相關(guān)功能,相對于傳統(tǒng)的手勢,密碼等驗(yàn)證方式,指紋驗(yàn)證安全性更高,速度也更快。
二、業(yè)界方案
1.1、FIDO
FIDO是CFCA提出的一種生物認(rèn)證標(biāo)準(zhǔn),通過FIDO sdk、手機(jī)硬件、FIDO后臺構(gòu)成了一套指紋驗(yàn)證解決方案,保證指紋驗(yàn)證流程不被篡改,該方案通過與手機(jī)廠商合作,客戶端側(cè)對秘鑰的操作均在TEE環(huán)境中,安全性高。FIDO方案不僅需要客戶端集成sdk,應(yīng)用后臺也需要植入FIDO后臺sdk,業(yè)務(wù)流程需要由FIDO客戶端sdk、應(yīng)用客戶端、應(yīng)用后臺、FIDO后臺sdk、FIDO服務(wù)端五方共同完成,較為復(fù)雜。一般針對指紋支付等安全性級別較高的場景。
1.2、TENCENT SOTER
TENCENT SOTER是一種生物認(rèn)證標(biāo)準(zhǔn),同時(shí)也是騰訊生物認(rèn)證平臺。TENCENT SOTER主要著眼于如何安全、高效并簡單地使用你設(shè)備上的傳感器進(jìn)行鑒權(quán)——最重要,也是目前用到最多的就是指紋傳感器。TENCENT SOTER與FIDO一樣,會通過與手機(jī)廠商的合作,客戶端側(cè)相關(guān)秘鑰操作均在TEE環(huán)境中。TENCENT SOTER采用三級秘鑰方案,應(yīng)用方后臺不需要接入sdk,接入相對簡單。一般針對指紋支付等安全性級別較高的場景。
1.3、Android Framework
Android系統(tǒng)提供的相關(guān)生物識別驗(yàn)證接口,應(yīng)用可以通過對這些接口的調(diào)用實(shí)現(xiàn)Android指紋驗(yàn)證功能,但安全性較低,容易被攻擊者繞過,若需要使用在支付等安全性級別較高的場景,需要配合額外的安全保護(hù)邏輯),且存在較多的兼容性問題。
三、Android原生方案
3.1、Api介紹
- Android 在23(Android M)上新增了指紋識別Api:FingerprintManager,第三方app可以通過對該類的開發(fā)與使用,實(shí)現(xiàn)指紋相關(guān)功能。開發(fā)者通過該Api打開指紋認(rèn)證流程時(shí),系統(tǒng)僅會打開設(shè)備的指紋模塊監(jiān)聽,并不會有UI相關(guān)展示,需要開發(fā)者根據(jù)自身App要求彈出對應(yīng)的交互流程。
- Android在28(Android P)上新增了生物識別Api:BiometricPrompt,并推薦開發(fā)者使用最新的生物識別Api替換原來的FingerprintManager,該Api不僅只針對指紋,而是囊括了指紋、人臉、虹膜等生物特征識別,但現(xiàn)階段只開放了指紋相關(guān)功能。開發(fā)者使用該Api進(jìn)行指紋認(rèn)證流程時(shí),系統(tǒng)在會打開設(shè)備的指紋模塊監(jiān)聽的同時(shí),還會彈出一個(gè)系統(tǒng)級的Dialog提示用戶正在進(jìn)行指紋解鎖流程。
FingerprintManager與BiometricPrompt中,指紋驗(yàn)證涉及的調(diào)用接口十分類似,本文就以BiometricPrompt為例
- 判斷當(dāng)前設(shè)備是否可以進(jìn)行生物識別
BiometricManager : canAuthenticate () (29)
- 設(shè)置彈窗系統(tǒng)彈窗title
BiometricPrompt.Builder(28): setSubtitle (CharSequence subtitle)
- 設(shè)置系統(tǒng)彈窗的取消按鈕
BiometricPrompt.Builder(28): setNegativeButton (CharSequence text, Executor executor,DialogInterface.OnClickListener listener)
- 開啟指紋認(rèn)證流程,開發(fā)者調(diào)用該Api后,生物識別傳感器將打開,同時(shí)屏幕會彈出一個(gè)系統(tǒng)級Dialog提示用戶正在進(jìn)行生物識別。
BiometricPrompt (28): authenticate (BiometricPrompt.CryptoObject crypto, CancellationSignal cancel, Executor executor, BiometricPrompt.AuthenticationCallback callback)
- crypto 成功進(jìn)行生物驗(yàn)證后將使用該對象驗(yàn)證本次流程的可靠性
- cancel 可以用于結(jié)束本次驗(yàn)證流程的對象
- executor 本次驗(yàn)證流程的執(zhí)行者(線程相關(guān))
- callback 用于接收本次驗(yàn)證流程結(jié)果的回調(diào)
- 指紋驗(yàn)證流程出現(xiàn)不可重試的錯誤時(shí)(如驗(yàn)證5次不通過),系統(tǒng)會中止指紋驗(yàn)證流程,并在一定時(shí)間內(nèi)不可再調(diào)起。
BiometricPrompt.AuthenticationCallback(28): onAuthenticationError(int errorCode, CharSequence errString)
- errorCode 錯誤碼
- errString 錯誤信息
- 系統(tǒng)識別出指紋,但該指紋未匹配指紋庫中指紋
BiometricPrompt.AuthenticationCallback(28): onAuthenticationFailed()
- 指紋驗(yàn)證流程出現(xiàn)可重試的錯誤時(shí)(如手指滑動過快)
BiometricPrompt.AuthenticationCallback(28): onAuthenticationHelp(int helpCode, CharSequence helpString)
- helpCode 錯誤碼
- helpString 錯誤信息
- 指紋驗(yàn)證成功時(shí)調(diào)用
BiometricPrompt.AuthenticationCallback(28): onAuthenticationSucceeded(BiometricPrompt.AuthenticationResult result)
- result 包含authenticate方法中的crypto等對象
3.2、版本兼容
- Api23-27:所有功能實(shí)現(xiàn)都使用FingerprintManager,彈窗由開發(fā)者自定義,非系統(tǒng)彈窗
- Api28:判斷當(dāng)前設(shè)備是否可以進(jìn)行指紋識別,需要使用FingerprintManager;進(jìn)行指紋驗(yàn)證流程,需要使用BiometricPrompt
- Api29+:判斷當(dāng)前設(shè)備是否可以進(jìn)行指紋識別,需要使用BiometricManager;進(jìn)行指紋驗(yàn)證流程,需要使用BiometricPrompt
- 也可以使用androidx.biometric包,在大于Api23的所有的Android版本都使用同一套接口,但需要解決將support包全部轉(zhuǎn)為androidx包等一系列問題。
3.3、存在問題
3.3.1、UI兼容性問題(針對BiometricPrompt)
由于FingerprintManager是開發(fā)方自定義UI,因此不存在UI兼容性問題。BiometricPrompt使用的是系統(tǒng)彈窗,開發(fā)者不可以自定義彈窗樣式,僅可以設(shè)置彈窗上的相關(guān)文案及按鈕點(diǎn)擊事件。因此不同廠商對系統(tǒng)Dialog樣式的不同實(shí)現(xiàn),會導(dǎo)致指紋驗(yàn)證流程中出現(xiàn)不同的交互。
華為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彈出后,點(diǎn)擊取消按鈕的點(diǎn)擊事件沒有分發(fā)給第三方App。
- 2、原生系統(tǒng),當(dāng)BiometricDialog彈出后,按下Menu/HOME鍵,指紋驗(yàn)證申請已經(jīng)取消,但是彈框BiometricDialog無法消失。
- 3、原生系統(tǒng),若操作不當(dāng),存在在鎖屏狀態(tài)下彈出Dialog導(dǎo)致無法解鎖,用戶無法進(jìn)入Launcher進(jìn)行UI交互的風(fēng)險(xiǎn)。出現(xiàn)這種“意外” 的情況是,比如:UI處在進(jìn)入申請BiometricPrompt生物識別彈框上下文,由于網(wǎng)絡(luò)/apk性能等種種原因,并未立馬申請彈出Dialog,突然遇到Power熄屏,或者亮屏超時(shí),立馬按下Power點(diǎn)亮屏幕。此時(shí)三方應(yīng)用處在onPaused狀態(tài),但是異步發(fā)起生物識別申請,導(dǎo)致"意外"發(fā)生。
3.3.3、安全性問題
上文介紹的指紋驗(yàn)證Api:public void authenticate (BiometricPrompt.CryptoObject crypto, CancellationSignal cancel, Executor executor, BiometricPrompt.AuthenticationCallback callback),若對第一個(gè)crypto參數(shù)使用方式不正確,則存在指紋驗(yàn)證被繞過的風(fēng)險(xiǎn)
流程
第一步:調(diào)用authenticate方法,彈出UI提示用戶輸入指紋-->第二步:用戶驗(yàn)證指紋,用戶驗(yàn)證指紋成功-->第三步:調(diào)用AuthenticationCallback.onAuthenticationSucceeded方法,執(zhí)行解鎖后邏輯
漏洞
- root手機(jī)
- 通過hook重寫authenticate方法,在authenticate方法中直接調(diào)用AuthenticationCallback.onAuthenticationSucceeded方法。若應(yīng)用未正確使用crypto參數(shù),則此方案繞過第二步驗(yàn)證指紋。
3.4 解決方案
3.4.1、UI兼容性問題
若使用BiometricPrompt則具體UI無法由第三方開發(fā)者指定,若要統(tǒng)一UI,建議使用FingerprintManager
3.4.2、功能性問題
若使用BiometricPrompt,則彈窗為系統(tǒng)級彈窗,其展示與消失邏輯無法由
第三方開發(fā)者指定,第三方開發(fā)者唯一可以控制的就是保證調(diào)起指紋識別流程(即調(diào)用authenticate方法)的時(shí)機(jī)正確。
3.4.3、安全性問題
方案一
流程:
- 在調(diào)用authicate方法前,通過AndroidKeyStore生成一把對稱秘鑰,加密串A得到串B,并用這把秘鑰生成crypto對象傳入authicate方法。
- 在AuthenticationCallback.onAuthenticationSucceeded方法中取出crypto對象,并解密串B得到C,比較A與C,若相等則通過。
- 若跳過驗(yàn)證流程直接調(diào)用AuthenticationCallback.onAuthenticationSucceeded,則比較A與C會失敗。
問題與總結(jié):
- 攻擊者若在流程中劫持到秘鑰,并生成crypto對象傳入,則仍可以繞過
- 兼容性問題小,對安全級別要求低的場景推薦使用
方案二
流程:
- 在調(diào)用authicate方法前,通過AndroidKeyStore生成一對非對稱秘鑰,設(shè)置要訪問這把秘鑰對必須在生物識別成功之后,利用公鑰加密串A得到串B,生成crypto對象傳入authicate方法。
- 在AuthenticationCallback.onAuthenticationSucceeded方法中取出crypto對象,利用私鑰解密串B得到C,比較A與C,若相等則通過。
- 若跳過驗(yàn)證流程直接調(diào)用AuthenticationCallback.onAuthenticationSucceeded,則在訪問私鑰解密數(shù)據(jù)時(shí),系統(tǒng)會拋出
android.security.keystore.KeyPermanentlyInvalidatedException: Key permanently invalidated,無法繼續(xù)執(zhí)行。
問題與總結(jié):
- 該方案相對方案一更加安全,通過AndroidKeystore保證指紋驗(yàn)證流程的不被繞過
- 由于Android碎片化問題,該方案在使用那把非對稱秘鑰時(shí),有非常多的兼容性問題
四、總結(jié)
上文詳細(xì)介紹了Android系統(tǒng)提供的指紋接口的使用方式以及使用過程中存在的問題,對比FIDO及TENCENT SOTER方案,我們可以得出以下圖表
| 比較項(xiàng) | TENCENT SOTER | Android Framework | FIDO |
|---|---|---|---|
| 接入成本 | 較低 | 低 | 高 |
| 是否需要聯(lián)網(wǎng) | 是 | 依賴方案 | 是 |
| 兼容性問題 | 少 | 多 | 少 |
| 用戶隱私保護(hù) | 好(不會獲取指紋圖案) | 好(不會獲取指紋圖案) | 好(不會獲取指紋圖案) |
| 安全性 | 高 | 依賴方案 | 高 |
綜合以上,云閃付在對安全性要求相對較低的場景(如解鎖),使用Android原生指紋接口配合AndroidKeystore實(shí)現(xiàn),無需聯(lián)網(wǎng),速度快,兼容性問題少;在對安全性要求較高的場景(如支付),選擇采用第三方FIDO解決方案,兼容性問題少,安全性高。



