以前我寫過相關的指紋解鎖的文章:
傳送門: 專案需求討論-APP手勢解鎖及指紋解鎖
那時候做的APP解鎖是呼叫系統的指紋解鎖功能,同時,進行指紋驗證的時候,只要是手機中錄製過的指紋,然後在指紋驗證過程中就會認為認證成功。但僅僅這樣,很難滿足一些驗證要求比較高的APP,比如支付型別的APP。不然我不是本人。我是女朋友啊,或者誰,我在你手機裡有個指紋,為了方便解鎖屏。又或者,一般朋友玩你的手機,問你鎖屏密碼,你也會說出來,畢竟想想是鎖屏密碼,然後去設定裡面新增指紋也只需要鎖屏密碼,這時候那個朋友偷偷去錄了個自己的指紋,豈不是你的指紋驗證就形同虛設了。豈不是也就馬上掌握你的支付賬戶了。
我來說下支付寶的指紋相關方式:
(前提:我手機上有左右大拇指的指紋已經錄製好了)
- 你到支付寶的設定介面,開啟指紋支付功能,這時候會跳出彈框,讓你驗證指紋:
這時候如果我用右邊的指紋來進行驗證,這時候指紋驗證通過了。就讓你進行密碼驗證,證明你這個指紋的人同時也是知道密碼的。
你輸入完正確的密碼後,算是正式的繫結上了。就代表你這個指紋具有相應的支付功能。 - 到了支付介面,我們用右手拇指去支付,OK,肯定是沒問題的,如果這時候我故意用左手的拇指去支付,會出錯:
那就說明,我們的指紋具有一個id值,能讓伺服器那邊知道當前這個指紋是不是我們繫結的指紋。
(順便提一句,ios我試了下,當你在手機新增了一個指紋後,他就會不讓你進行支付,比如我們原來是右手拇指支付的,當你新增一個新的指紋後,就算你用右手指紋去付錢,也不行,所以這裡我認為ios是監聽了系統指紋的變化情況,比如新增了指紋。而不僅僅單純是判斷到底具體是哪一個指紋)
這個但是我們知道我們指紋驗證通過的都是系統底層的API,我們的API最後返回驗證結果給我們的內容中,是否帶有相關的引數,我們可以繼續往下看:
在我的文章 專案需求討論-APP手勢解鎖及指紋解鎖 我提過,最後指紋驗證通過是回撥:
@Override
public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
.....
.....
.....
}複製程式碼
我們可以看到指紋驗證通過後的回撥方法引數是FingerprintManager.AuthenticationResult
,我們再來看下這個類
public static class AuthenticationResult {
private Fingerprint mFingerprint;
private CryptoObject mCryptoObject;
/**
* Authentication result
*
* @param crypto the crypto object
* @param fingerprint the recognized fingerprint data, if allowed.
* @hide
*/
public AuthenticationResult(CryptoObject crypto, Fingerprint fingerprint) {
mCryptoObject = crypto;
mFingerprint = fingerprint;
}
/**
* Obtain the crypto object associated with this transaction
* @return crypto object provided to {@link FingerprintManager#authenticate(CryptoObject,
* CancellationSignal, int, AuthenticationCallback, Handler)}.
*/
public CryptoObject getCryptoObject() { return mCryptoObject; }
/**
* Obtain the Fingerprint associated with this operation. Applications are strongly
* discouraged from associating specific fingers with specific applications or operations.
*
* @hide
*/
public Fingerprint getFingerprint() { return mFingerprint; }
};複製程式碼
這個類很簡單,裡面就二個屬性值:Fingerprint
和CryptoObject
,我們再來看Fingerprint
類的內容:
/**
* Container for fingerprint metadata.
* @hide
*/
public final class Fingerprint implements Parcelable {
private CharSequence mName;
private int mGroupId;
private int mFingerId;
private long mDeviceId; // physical device this is associated with
....
....
....
}複製程式碼
沒錯。裡面有mFingerId
等引數。豈不是我們直接拿這個值不就行了??這麼簡單???
答案當然是No,因為你回頭再看上面的AuthenticationResult
類裡面的getFingerprint()方法上面用@hide修飾了,而且我們的Fingerprint
類上面也用@hide修飾了。
但是大家心裡一定會想,那我不是用反射來呼叫getFingerprint()
方法拿到Fingerprint物件,從而再來拿mFingerId
不就好了。
比如我在這裡寫上反射獲取:
@Override
public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
mErrorTextView.removeCallbacks(mResetErrorTextRunnable);
mIcon.setImageResource(R.drawable.ic_fingerprint_success);
mErrorTextView.setTextColor(
mErrorTextView.getResources().getColor(R.color.success_color, null));
mErrorTextView.setText(
mErrorTextView.getResources().getString(R.string.fingerprint_success));
mIcon.postDelayed(new Runnable() {
@Override
public void run() {
mCallback.onAuthenticated();
}
}, SUCCESS_DELAY_MILLIS);
//通過反射來獲取
try {
Method method1 = result.getClass().getMethod("getCryptoObject");
Object cryptoObject = method1.invoke(result, new Object[]{});
Method method2 = result.getClass().getMethod("getFingerprint");
Object fingerPrint = method2.invoke(result, new Object[]{});
} catch ( NoSuchMethodException e ) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}複製程式碼
你會發現就算通過反射來拿Fingerprint
物件,拿到的也是null
。而我用同樣的程式碼來拿CryotoObject物件就是有內容的。
所以這裡我們用反射也出現了問題,那我們自己普通程式設計師開發應該怎麼來處理呢。
(ps:StackOverflow上也有人提出相同的問題:Fingerprint為null,他是直接把android.jar包換了。換成了這裡沒有@hide修飾了。這樣就可以直接在程式碼裡面使用,但是拿到的也是null。)
主角: Tencent/soter
TENCENT SOTER是騰訊於2015年開始制定的生物認證平臺與標準,通過與廠商合作,目前已經在一百餘款、數億部Android裝置上得到支援,並且這個數字還在快速增長。
目前,TENCENT SOTER已經在微信指紋支付、微信公眾號/小程式指紋授權介面等場景使用,並得到了驗證。
接入TENCENT SOTER,你可以在不獲取使用者指紋圖案的前提下,在Android裝置上實現可信的指紋認證,獲得與微信指紋支付一致的安全快捷認證體驗。
為什麼要用TENCENT SOTER:
這裡可以對比下系統原生Android 6.0指紋介面和FIDO方案。
TENCENT SOTER | Android Framework | FIDO | |
---|---|---|---|
安全性 | 高(前後臺支援,有產線生成一機一密根金鑰) | 低(手機被root後易被破解,且無法準確檢測root) | 高(前後臺支援,有產線生成根金鑰) |
接入成本 | 較低(前端極輕量級sdk,後臺無須整合sdk) | 低(無需前後臺sdk) | 高(部署複雜) |
敏感業務可用 | 是(可獲取本機指紋索引) | 否(無法獲取指紋在本機索引,有盜用風險) | 是(可獲取本機指紋索引) |
使用者隱私保護 | 好(不會獲取指紋圖案) | 好(不會獲取指紋圖案) | 好(不會獲取指紋圖案) |
商業隱私保護 | 好(驗證無須請求到中心服務) \ | 較差(需要每一筆驗證都請求到中心驗證伺服器) |
當然最主要的功能是:
同時,對比與原生介面,也有兩個明顯優勢:
支援部分Android L(Android 5.0、5.1)機型指紋認證
可以提供本次認證在本機上的指紋索引以區分手指
更多請看:什麼是TENCENT SOTER
SOTER支援的機型:SOTER 指紋支援機型
所以我們看到了。它可以提供本機上的指紋索引來區分手機。
我們使用github soter上面提供的Demo。我們可以執行demo,這時候出現一些情況:
- 有些人執行demo,可能會開啟指紋功能的時候會失敗,可能是你的機型不支援。我使用小米5不行,使用的OPPO A57就可以了。
- 大家可能看到華為上面一臺都沒有。在issue裡面我們也看到了。騰訊正在和華為洽談,而且說了技術上面是沒有任何問題的。所以後續大家也可以不用擔心
- 最後你用指紋解鎖的時候,可以再回撥函式中檢視相關的log資訊:
其中比較重要的就是soterdemo: use fingerprint payment result: total: SoterCoreResult{errCode=0, errMsg=''}, extData: SoterSignatureResult{rawValue='I'm a demo challenge string', fid='3374914681109099800', counter=42, TEEName='QSEE', TEEVersion='4', FpName='fingerprint', FpVersion='1', cpuId='000000000006b0e13a925a082575ca3e', saltLen=20, jsonValue='{"raw":"I'm a demo challenge string","fid":"3374914681109099800","counter":42,"tee_n":"QSEE","tee_v":"4","fp_n":"fingerprint","fp_v":"1","cpu_id":"000000000006b0e13a925a082575ca3e","uid":"10107"}', signature='J7jNgKFc2TMExrx3dLJAiAFF25cwZvUhGWLQJPhhbHKsHTLi+/eAsJd7gmgAJnZsCQrHq2vnIeW8j0Rj81aRbF1Svv5tNRJt1Gyzewu9Lpa7E5rwTJ97otJPWv3b3nxyDicYQaEZbzqGSYeKga+tUutDlISzvFOLqrikX/OT0W5M0/szFIpkrEAJiMGYNqg451iijN3dM6pB9AXgs6qohz25sWbF6OEthvAO9hI9Ddsm5bn69Ct/3f4eaB3eb/Ljo/Hs8YK//UhkvXn4OcOsnsmHZ6P6jaNcC60iylxxLuPc2PwMd8dRPDKk8S0HEyjT7SpaQqIO2j7/hbi2by0QJg=='}, signature data is: SoterSignatureResult{rawValue='I'm a demo challenge string', fid='3374914681109099800', counter=42, TEEName='QSEE', TEEVersion='4', FpName='fingerprint', FpVersion='1', cpuId='000000000006b0e13a925a082575ca3e', saltLen=20, jsonValue='{"raw":"I'm a demo challenge string","fid":"3374914681109099800","counter":42,"tee_n":"QSEE","tee_v":"4","fp_n":"fingerprint","fp_v":"1","cpu_id":"000000000006b0e13a925a082575ca3e","uid":"10107"}', signature='J7jNgKFc2TMExrx3dLJAiAFF25cwZvUhGWLQJPhhbHKsHTLi+/eAsJd7gmgAJnZsCQrHq2vnIeW8j0Rj81aRbF1Svv5tNRJt1Gyzewu9Lpa7E5rwTJ97otJPWv3b3nxyDicYQaEZbzqGSYeKga+tUutDlISzvFOLqrikX/OT0W5M0/szFIpkrEAJiMGYNqg451iijN3dM6pB9AXgs6qohz25sWbF6OEthvAO9hI9Ddsm5bn69Ct/3f4eaB3eb/Ljo/Hs8YK//UhkvXn4OcOsnsmHZ6P6jaNcC60iylxxLuPc2PwMd8dRPDKk8S0HEyjT7SpaQqIO2j7/hbi2by0QJg=='}複製程式碼
fid='3374914681109099800'
,不同的指紋,這個ID值是不同的。所以我們可以用來判斷了。
還是那句老話,可能我哪裡講的不對。大家請下面留言。多回復多點贊。哈哈。