iOS指紋登陸

指紋登陸

隨着智能時代的來臨,人們越來越習慣於將重要信息和個人隱私存放於智能手機中。這時手機數據的安全性就變得尤其重要。通常我們使用口令或密碼來保護設備,但是隨着iPhone和Android手機硬件的逐步升級與支持,使用指紋驗證成爲了代替密碼的一種常規方法。

指紋驗證是指通過手機中的觸摸傳感器來識別用戶。通過這種技術我們可以使用指紋解鎖設備或在應用中通過指紋授權使用例如指紋登錄或指紋支付等功能。

爲什麼使用指紋驗證

對於應用而言,使用指紋驗證可以從多方面提升用戶體驗:

  • 指紋驗證是一種更加快捷方便的方法來驗證用戶身份。傳統校驗用戶身份的方法,通常是使用密碼或口令,要想越安全就需要使用越複雜的密碼。相較於輸入冗長且複雜的密碼,指紋識別僅僅需要的是使用指尖觸碰傳感器完成驗證。這無疑能給用戶帶來更加順暢的使用體驗。

  • 指紋不會被遺忘。如上一條所說,通常密碼都是冗長且複雜的,尤其是不常使用的密碼,很容易在一段時間後被用戶忘記。而使用指紋識別則完全沒有這種煩惱,你可以隨時使用指紋驗證。

  • 指紋驗證無需找回功能。由於指紋永遠不會被遺忘,也不會改變。通常密碼找回的功能對於指紋驗證來說就毫無意義。

  • 指紋驗證更加安全。通常爲了方便記憶密碼,用戶傾向於使用方便記憶的信息(比如生日)來生成密碼,這讓密碼變得很容易被破解。而即便使用了較爲複雜的密碼,也無法保證其擁有和指紋一樣的獨特性和安全性。一旦密碼被泄露或盜取,其他人能輕易獲取到用戶信息。

iOS技術背景

Touch ID

iOS設備下的指紋識別是通過iOS設備提供的Touch ID實現。

Touch ID技術包括在iOS設備上的一套先進的硬件與軟件系統:

  • 在iOS硬件設備上的HOME按鍵由藍寶石水晶製成,能作爲透鏡獲取到你手指皮膚下紋理的高清圖片

  • Touch ID會通過你傳入的一系列指紋圖片,通過算法生成出屬於指紋的數字標識,存儲於特殊的芯片上

Touch ID只會存儲通過指紋圖片生成的數字標識,所以不用擔心你真實的指紋泄露。由於指紋的獨特性,Touch ID算出的數字標識能相同的概率是50000之1,就是50000個不同指紋纔可能會有一對可以通過Touch ID相互匹配。所以Touch ID是一項足夠安全的技術。

Touch ID已經備蘋果普遍使用於iTunes Store, App Store和Apple Pay。微信和支付寶的支付也已經使用了Touch ID。所以Touch ID也是一項被廣泛信賴並使用的技術。

Secure Enclave

如在介紹Touch ID時介紹的一樣,Touch ID不會存儲任何關於指紋的圖片,而是存儲的指紋標識。不過即使是這些數字標識也被iOS存儲於一塊叫做Secure Enclave(安全領域)的芯片上。你的指紋信息只會被用於比對是否與設備中存儲的指紋信息進行比對,不能被操作系統,更不會被其他應用訪問。這些信息也不會上傳到蘋果的服務或者被iCloud等雲服務備份,不可能被用於與其他的指紋庫進行比對。

LocalAuthentication

LocalAuthentication framework是我們的app來使用iOS設備上生物信息驗證(Touch ID或者Touch ID)的機制。上文已經介紹過,爲了最大限度的保護用戶信息的私密性和安全性,iOS上使用了Secure Enclave的方式來將驗證數據與設備上的其他系統隔離。用戶的認證信息甚至無法被操作系統訪問,我們通過認證得到的只是一條布爾值的結果。

Keychain

當需要存儲私密信息時,你可以使用Keychain。Keychain是由iOS的Security framework提供的服務,你可以設置keychain中元素的訪問權限爲每次去讀取這項數據時都需要用戶的認證(通過Face ID或者Touch ID)。當每次去請求keychian中數據訪問權限時,LocalAuthentiation Framework會通過系統展示相應的界面提示用戶錄入數據,然後將這些數據傳入Secure Enclave進行比對。比對結束後,Secure Enclave會成功或失敗的結果返回。其間用戶或者操作系統都不會也不能獲取到用戶的指紋信息。

localAuthentication

Android技術背景

BiometricPrompt API 和 FingerprintManager

現在很多安卓手機已經內置了觸摸傳感器,所以安卓在最新發布的Android 8提供了BiometricPrompt來提供指紋識別或面部識別的支持。Android 6以後的版本也可以使用FingerprintManager來提供指紋識別的支持。

Android Keystore System

安卓的Keystore System用於存儲加密的Keys,不過不同於安卓的KeyChain。這些信息只能用於自己的應用中。

概述

在iOS和Android技術背景中我們得知:

  • 我們通過指紋識別能獲取到只是指紋是否匹配,並不能得到其他與指紋信息有關的結果

  • 但是我們可以存儲私密信息,並通過指紋獲取訪問權限

在此基礎上,初步設計了指紋識別的流程。iOS和安卓在指紋識別上的流程由於API的限制不盡相同,但是大概的步驟基本一致:

  1. 打開指紋認證界面獲取獲取權限

  2. 如果步驟1指紋認證成功,獲取到權限後嘗試從設備中獲取用戶登錄所需密鑰

  3. 如果步驟2成功獲取到用戶密鑰,即用戶已經綁定了指紋登陸,那麼獲取用戶密鑰登陸

  4. 如果步驟2未能獲取到用戶密鑰,即用戶還未綁定指紋登陸,那麼開始綁定指紋的流程

  5. 綁定指紋的流程可以分爲前端和後端的工作,先由後端生成用戶登陸所需的獨特密鑰傳回給前端

  6. 前端收到密鑰後將密鑰存儲於本地設備中

  7. 使用獲取到的密鑰就能成功登陸

簡化流程如圖:

flow

紅色方塊爲後端操作,藍色方塊爲前段操作

iOS實現方案

iOS上的指紋登陸方案的主題內容爲:

  • 使用Security framework將用戶密鑰信息存儲於keychain中

  • 使用LocalAuthentication framework來驗證用戶指紋信息,並且獲取到keychain中的密鑰訪問權限

配置工程

要使用Touch ID和Keychain的功能,首先需要將需要的framework添加到工程中。打開工程後選擇對應的Target後點擊Build Phases > Link Binary With Libraries,點擊+號添加LocalAuthentication和Security兩個framework。

framework

開啓指紋登陸

在用戶使用指紋登陸之前,需要用戶先開啓指紋登陸功能。開啓指紋登陸的具體步驟可細分爲以下步驟。

1. 判斷設備是否支持指紋

判斷當前設備是否支持指紋識別,如果支持,在合適的時機提示用戶是否開啓指紋登陸,可以在用戶成功登陸後或設置界面展示相應的界面提示用戶開啓指紋登陸。

var context = LAContext()
var error: NSError?
if context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error) {

2. 確認指紋信息,向服務器請求開啓指紋登陸

當用戶點擊開啓指紋登陸時,iOS設備通過LocalAuthentication framework調起系統指紋認證界面,如果認證通過向服務端發起開啓指紋登陸的請求。

var context = LAContext()
let reason = "請確定開啓指紋登陸"
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { (success, error) in
    if success {
    } else {
    }
})

3. 存儲用戶信息

iOS端收到服務端的響應,將其中的密鑰解析出來,存儲於Keychain中,並設置爲只能通過TouchID訪問。並將用戶名和指紋識別開啓狀態存儲於UserDefault中。

let access = SecAccessControlCreateWithFlags(nil,
                                           kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
                                           .userPresence,
                                           nil)
let query: [String: Any] = [
  kSecClass as String: kSecClassInternetPassword,
  kSecAttrAccount as String: userInfo.name,
  kSecAttrServer as String: AuthInfo.server,
  kSecValueData as String: userInfo.authKey
];
let status = SecItemAdd(query as CFDictionary, nil)
guard status == errSecSuccess else {
}

4. 開啓成功

使用指紋認證

在用戶開啓了指紋登陸功能後,就可以在登陸時試用指紋登陸。指紋登陸的步驟爲:

1. 判斷用戶是否開啓指紋登陸

判斷當前設備是否支持指紋識別,如果支持,檢查設備UserDefault中的數據,判斷當前用戶是否開啓指紋登陸。

var context = LAContext()
var error: NSError?
if context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error) {

2. 獲取用戶數據

如果當前用戶開啓了指紋登陸,調起系統指紋認證界面,申請訪問Keychain的權限,如果認證成功從Keychain中嘗試取得存儲於keychain中的用戶密鑰。

let query: [String: Any] = [
  kSecClass as String: kSecClassInternetPassword,
  kSecAttrServer as String: server,
  kSecMatchLimit as String: kSecMatchLimitOne,
  kSecReturnAttributes as String: true,
  kSecUseOperationPrompt as String: "使用指紋登陸",
  kSecReturnData as String: true
]
var item: CFTypeRef?
let status = SecItemCopyMatching(query as CFDictionary, &item)
guard status == errSecSuccess else {
  return nil
}
guard
  let existingItem = item as? [String : Any],
  let authKeyData = existingItem[kSecValueData as String] as? Data,
  let authKey = String(data: authKeyData, encoding: .utf8),
  let name = existingItem[kSecAttrAccount as String] as? String else {
    return nil
}
let savedUserInfo = UserInfo(name: name, authKey: authKey)

3. 如果成功拿到用戶密鑰,使用密鑰向服務端發起指紋登陸請求。

4. iOS端收到登陸請求的響應,判斷是否登陸成功。

5. 如果響應爲成功,完成登陸邏輯。

Android實現方案

Todo

參考資料

About Touch ID advanced security technology

Logging a User into Your App with Face ID or Touch ID

better-biometrics-in-android-p

security-key-attestation

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章