Android中的指紋識別demo開發(fā)實例
指紋識別是在Android 6.0之后新增的功能,因此在使用的時候需要先判斷用戶手機的系統(tǒng)版本是否支持指紋識別。另外,實際開發(fā)場景中,使用指紋的主要場景有兩種:
純本地使用。即用戶在本地完成指紋識別后,不需要將指紋的相關(guān)信息給后臺。
與后臺交互。用戶在本地完成指紋識別后,需要將指紋相關(guān)的信息傳給后臺。
由于使用指紋識別功能需要一個加密對象(CryptoObject)該對象一般是由對稱加密或者非對稱加密獲得。上述兩種開發(fā)場景的實現(xiàn)大同小異,主要區(qū)別在于加密過程中密鑰的創(chuàng)建和使用,一般來說,純本地的使用指紋識別功能,只需要對稱加密即可;而與后臺交互則需要使用非對稱加密:將私鑰用于本地指紋識別,識別成功后將加密信息傳給后臺,后臺開發(fā)人員用公鑰解密,以獲得用戶信息。
下面先簡單介紹一下對稱加密和非對稱加密的相關(guān)概念,然后對兩種開發(fā)方式的實現(xiàn)分別進行講解。
對稱加密、非對稱加密和簽名
在正式使用指紋識別功能之前,有必要先了解一下對稱加密和非對稱加密的相關(guān)內(nèi)容。
對稱加密:所謂對稱,就是采用這種加密方法的雙方使用方式用同樣的密鑰進行加密和解密。密鑰是控制加密及解密過程的指令。算法是一組規(guī)則,規(guī)定如何進行加密和解密。因此加密的安全性不僅取決于加密算法本身,密鑰管理的安全性更是重要。因為加密和解密都使用同一個密鑰,如何把密鑰安全地傳遞到解密者手上就成了必須要解決的問題。
非對稱加密:非對稱加密算法需要兩個密鑰:公開密鑰(publickey)和私有密鑰(privatekey)。公開密鑰與私有密鑰是一對,如果用公開密鑰對數(shù)據(jù)進行加密,只有用對應(yīng)的私有密鑰才能解密;如果用私有密鑰對數(shù)據(jù)進行加密,那么只有用對應(yīng)的公開密鑰才能解密。因為加密和解密使用的是兩個不同的密鑰,所以這種算法叫作非對稱加密算法。 非對稱加密算法實現(xiàn)機密信息交換的基本過程是:甲方生成一對密鑰并將其中的一把作為公用密鑰向其它方公開;得到該公用密鑰的乙方使用該密鑰對機密信息進行加密后再發(fā)送給甲方;甲方再用自己保存的另一把專用密鑰對加密后的信息進行解密。
簽名:在信息的后面再加上一段內(nèi)容,可以證明信息沒有被修改過。一般是對信息做一個hash計算得到一個hash值,注意,這個過程是不可逆的,也就是說無法通過hash值得出原來的信息內(nèi)容。在把信息發(fā)送出去時,把這個hash值加密后做為一個簽名和信息一起發(fā)出去。
由以上內(nèi)容可以了解到,對稱加密和非對稱加密的特點如下:
對稱加密的優(yōu)點是速度快,適合于本地數(shù)據(jù)和本地數(shù)據(jù)庫的加密,安全性不如非對稱加密。常見的對稱加密算法有DES、3DES、AES、Blowfish、IDEA、RC5、RC6。
非對稱加密的安全性比較高,適合對需要網(wǎng)絡(luò)傳輸?shù)臄?shù)據(jù)進行加密,速度不如對稱加密。非對稱加密應(yīng)用于SSH, HTTPS, TLS,電子證書,電子簽名,電子身份證等等
指紋識別的對稱加密實現(xiàn)
使用指紋識別的對稱加密功能的主要流程如下:
使用 KeyGenerator 創(chuàng)建一個對稱密鑰,存放在 KeyStore 里。
設(shè)置 KeyGenParameterSpec.Builder.setUserAuthenticationRequired() 為true,
使用創(chuàng)建好的對稱密鑰初始化一個Cipher對象,并用該對象調(diào)用 FingerprintManager.authenticate() 方法啟動指紋傳感器并開始監(jiān)聽。
重寫 FingerprintManager.AuthenticationCallback 的幾個回調(diào)方法,以處理指紋識別成功(onAuthenticationSucceeded())、失?。╫nAuthenticationFailed() 和 onAuthenticationError())等情況。
創(chuàng)建密鑰
創(chuàng)建密鑰要涉及到兩個類:KeyStore 和 KeyGenerator。
KeyStore 是用于存儲、獲取密鑰(Key)的容器,獲取 KeyStore的方法如下:
try { mKeyStore = KeyStore.getInstance("AndroidKeyStore"); } catch (KeyStoreException e) { throw new RuntimeException("Failed to get an instance of KeyStore", e); }
而生成 Key,如果是對稱加密,就需要 KeyGenerator 類。獲取一個 KeyGenerator 對象比較簡單,方法如下:
// 對稱加密, 創(chuàng)建 KeyGenerator 對象 try { mKeyGenerator = KeyGenerator .getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore"); } catch (NoSuchAlgorithmException | NoSuchProviderException e) { throw new RuntimeException("Failed to get an instance of KeyGenerator", e); }
獲得 KeyGenerator 對象后,就可以生成一個 Key 了:
try { keyStore.load(null); KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder(defaultKeyName, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) .setBlockModes(KeyProperties.BLOCK_MODE_CBC) .setUserAuthenticationRequired(true) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { builder.setInvalidatedByBiometricEnrollment(true); } keyGenerator.init(builder.build()); keyGenerator.generateKey(); } catch (CertificateException | NoSuchAlgorithmException | IOException | InvalidAlgorithmParameterException e) { e.printStackTrace(); }
關(guān)于 KeyStrore 和 KeyGenerator 的相關(guān)介紹,推薦閱讀:Android KeyStore + FingerprintManager 存儲密碼
創(chuàng)建并初始化 Cipher 對象
Cipher 對象是一個按照一定的加密規(guī)則,將數(shù)據(jù)進行加密后的一個對象。調(diào)用指紋識別功能需要使用到這個對象。創(chuàng)建 Cipher 對象很簡單,如同下面代碼那樣:
Cipher defaultCipher; try { defaultCipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_CBC + "/" + KeyProperties.ENCRYPTION_PADDING_PKCS7); } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { throw new RuntimeException("創(chuàng)建Cipher對象失敗", e); }
然后使用剛才創(chuàng)建好的密鑰,初始化 Cipher 對象:
try { keyStore.load(null); SecretKey key = (SecretKey) keyStore.getKey(keyName, null); cipher.init(Cipher.ENCRYPT_MODE, key); return true; } catch (IOException | NoSuchAlgorithmException | CertificateException | UnrecoverableKeyException | KeyStoreException | InvalidKeyException e) { throw new RuntimeException("初始化 cipher 失敗", e); }
使用指紋識別功能
真正到了使用指紋識別功能的時候,你會發(fā)現(xiàn)其實很簡單,只是調(diào)用 FingerprintManager 類的的方法authenticate()而已,然后系統(tǒng)會有相應(yīng)的回調(diào)反饋給我們,該方法如下:
public void authenticate(CryptoObject crypto, CancellationSignal cancel, int flags, AuthenticationCallback callback, Handler handler)
該方法的幾個參數(shù)解釋如下:
第一個參數(shù)是一個加密對象。還記得之前我們大費周章地創(chuàng)建和初始化的Cipher對象嗎?這里的 CryptoObject 對象就是使用 Cipher 對象創(chuàng)建創(chuàng)建出來的:new FingerprintManager.CryptoObject(cipher)。
第二個參數(shù)是一個 CancellationSignal 對象,該對象提供了取消操作的能力。創(chuàng)建該對象也很簡單,使用 new CancellationSignal() 就可以了。
第三個參數(shù)是一個標志,默認為0。
第四個參數(shù)是 AuthenticationCallback 對象,它本身是 FingerprintManager 類里面的一個抽象類。該類提供了指紋識別的幾個回調(diào)方法,包括指紋識別成功、失敗等。需要我們重寫。
最后一個 Handler,可以用于處理回調(diào)事件,可以傳null。
完成指紋識別后,還要記得將 AuthenticationCallback 關(guān)閉掉:
public void stopListening() { if (cancellationSignal != null) { selfCancelled = true; cancellationSignal.cancel(); cancellationSignal = null; } }
重寫回調(diào)方法
調(diào)用了 authenticate() 方法后,系統(tǒng)就會啟動指紋傳感器,并開始掃描。這時候根據(jù)掃描結(jié)果,會通過FingerprintManager.AuthenticationCallback類返回幾個回調(diào)方法:
// 成功 onAuthenticationSucceeded() // 失敗 onAuthenticationFaile() // 錯誤 onAuthenticationError()
一般我們需要重寫這幾個方法,以實現(xiàn)我們的功能。關(guān)于onAuthenticationFaile()和onAuthenticationError()的區(qū)別,后面會講到。
指紋識別的非對稱加密實現(xiàn)
其實流程和上面的流程差不多:
使用 KeyPairGenerator 創(chuàng)建一個非對稱密鑰。
使用創(chuàng)建好的私鑰進行簽名,使用該簽名創(chuàng)建一個加密對象,并將該對象作為 FingerprintManager.authenticate() 方法的一個參數(shù),啟動指紋傳感器并開始監(jiān)聽。
重寫 FingerprintManager.AuthenticationCallback 類的幾個回調(diào)方法,以處理指紋識別成功(onAuthenticationSucceeded())、失?。╫nAuthenticationFailed() 和 onAuthenticationError())等情況。
可以看見,指紋識別的非對稱加密方式和對稱加密方式的實現(xiàn)流程是差不多的,它們之間最明顯的差別是在于密鑰的生成與使用。
創(chuàng)建密鑰
這里要使用 KeyPairGenerator 來創(chuàng)建一組非對稱密鑰,首先是獲取 KeyPairGenerator 對象:
// 非對稱加密,創(chuàng)建 KeyPairGenerator 對象 try { mKeyPairGenerator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore"); } catch (NoSuchAlgorithmException | NoSuchProviderException e) { throw new RuntimeException("Failed to get an instance of KeyPairGenerator", e); }
得到了 KeyPairGenerator 對象后,就可以創(chuàng)建 KeyPair(密鑰對)了:
try { // Set the alias of the entry in Android KeyStore where the key will appear // and the constrains (purposes) in the constructor of the Builder mKeyPairGenerator.initialize( new KeyGenParameterSpec.Builder(KEY_NAME, KeyProperties.PURPOSE_SIGN) .setDigests(KeyProperties.DIGEST_SHA256) .setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1")) // Require the user to authenticate with a fingerprint to authorize // every use of the private key .setUserAuthenticationRequired(true) .build()); mKeyPairGenerator.generateKeyPair(); } catch (InvalidAlgorithmParameterException e) { throw new RuntimeException(e); }
簽名
指紋識別的對稱加密實現(xiàn)中使用了Cipher對象來創(chuàng)建CryptoObject對象,而在這里,我們將會使用私鑰進行簽名,用簽名對象來創(chuàng)建CryptoObject對象:
// 使用私鑰簽名 try { mKeyStore.load(null); PrivateKey key = (PrivateKey) mKeyStore.getKey(KEY_NAME, null); mSignature.initSign(key); return true; } catch (KeyPermanentlyInvalidatedException e) { return false; } catch (KeyStoreException | CertificateException | UnrecoverableKeyException | IOException | NoSuchAlgorithmException | InvalidKeyException e) { throw new RuntimeException("Failed to init Cipher", e); }
同樣的,調(diào)用new FingerprintManager.CryptoObject(mSignature)方法創(chuàng)建一個CryptoObject對象。
調(diào)用指紋識別方法
這里的使用方法和前面“指紋識別的對稱加密實現(xiàn)”中的調(diào)用方法是一樣的,都是調(diào)用FingerprintManager.authenticate()方法。這里就不再敘述。
監(jiān)聽回調(diào)
監(jiān)聽回調(diào)也和之前的類似,唯一不同的是,我們在識別成功后需要和后臺進行交互,也就是onAuthenticationSucceeded()中處理的邏輯不一樣。
實際應(yīng)用中的注意事項
判斷用戶是否可以使用指紋識別功能
一般來說,為了增加安全性,要求用戶在手機的“設(shè)置”中開啟了密碼鎖屏功能。當然,使用指紋解鎖的前提是至少錄入了一個指紋。
// 如果沒有設(shè)置密碼鎖屏,則不能使用指紋識別 if (!keyguardManager.isKeyguardSecure()) { Toast.makeText(this, "請在設(shè)置界面開啟密碼鎖屏功能", Toast.LENGTH_LONG).show(); } // 如果沒有錄入指紋,則不能使用指紋識別 if (!fingerprintManager.hasEnrolledFingerprints()) { Toast.makeText(this, "您還沒有錄入指紋, 請在設(shè)置界面錄入至少一個指紋", Toast.LENGTH_LONG).show(); }
這里用到了兩個類:KeyguardManager 和 FingerprintManager,前者是屏幕保護的相關(guān)類。后者是指紋識別的核心類。
關(guān)于指紋識別回調(diào)方法
前面說到AuthenticationCallback類里面的幾個回調(diào)方法,其中有三個是我們開發(fā)中需要用到的:
onAuthenticationError() onAuthenticationSucceeded() onAuthenticationFailed()
關(guān)于這三個回調(diào)方法,有幾點需要注意的:
當指紋識別失敗后,會調(diào)用onAuthenticationFailed()方法,這時候指紋傳感器并沒有關(guān)閉,系統(tǒng)給我們提供了5次重試機會,也就是說,連續(xù)調(diào)用了5次onAuthenticationFailed()方法后,會調(diào)用onAuthenticationError()方法。
當系統(tǒng)調(diào)用了onAuthenticationError()和onAuthenticationSucceeded()后,傳感器會關(guān)閉,只有我們重新授權(quán),再次調(diào)用authenticate()方法后才能繼續(xù)使用指紋識別功能。
當系統(tǒng)回調(diào)了onAuthenticationError()方法關(guān)閉傳感器后,這種情況下再次調(diào)用authenticate()會有一段時間的禁用期,也就是說這段時間里是無法再次使用指紋識別的。當然,具體的禁用時間由手機廠商的系統(tǒng)不同而有略微差別,有的是1分鐘,有的是30秒等等。而且,由于手機廠商的系統(tǒng)區(qū)別,有些系統(tǒng)上調(diào)用了onAuthenticationError()后,在禁用時間內(nèi),其他APP里面的指紋識別功能也無法使用,甚至系統(tǒng)的指紋解鎖功能也無法使用。而有的系統(tǒng)上,在禁用時間內(nèi)調(diào)用其他APP的指紋解鎖功能,或者系統(tǒng)的指紋解鎖功能,就能立即重置指紋識別功能。
以上所述是小編給大家介紹的Android中的指紋識別demo開發(fā)實例,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關(guān)文章
ListView的Adapter使用(綁定數(shù)據(jù)) 之 自定義每一項的布局去綁定數(shù)據(jù)
之前寫的綁定數(shù)據(jù)是只是簡單的綁定了字符串,這次我們將一次綁定多條數(shù)據(jù)并且嘗試用自定義的布局。在這篇文章中首先講解的是用Hashmap 去綁定數(shù)據(jù),第二個例子,講解自定義布局然后綁定數(shù)據(jù)2013-06-06Android SwipereFreshLayout下拉刷新
這篇文章主要介紹了Android SwipereFreshLayout下拉刷新的相關(guān)資料,需要的朋友可以參考下2017-06-0630分鐘搞清楚Android Touch事件分發(fā)機制
30分鐘搞清楚Android Touch事件分發(fā)機制,Touch事件分發(fā)中只有兩個主角:ViewGroup和View,想要深入學習的朋友可以參考本文2016-03-03Android開發(fā)實現(xiàn)生成excel的方法詳解
這篇文章主要介紹了Android開發(fā)實現(xiàn)生成excel的方法,結(jié)合實例形式詳細分析了Android生成Excel的具體步驟與存儲、導(dǎo)入、添加等相關(guān)操作技巧,需要的朋友可以參考下2017-10-10詳解Android創(chuàng)建Handler的必備知識點
本篇文章主要介紹Handler中需要了解的幾個必備知識點,比如Handler創(chuàng)建、異步Handler是個啥及如何創(chuàng)建,感興趣的小伙伴快跟隨小編一起學習一下2022-10-10