提到指紋支付,你會怎麼做?
假如有一天,產品經理安排你做指紋支付,並且要下版本就上,你會怎麼做?
如果是產品大哥,就從工位下面抽出一把指甲刀架在他脖子上,讓他跪在牆角唱征服;
如果是產品妹子,就讓她請你喝咖啡,然後談天說地,趁此機會告訴她「還是選擇世界和平吧,比做指紋支付簡單多了。」
當然,想象還是太溫柔了。真正做過指紋支付專案的在下,經常會在半夜三更回憶起當年做指紋支付需求時候的噩夢,在夢裡,我就給自己加戲,手撕產品經理。
也許產品大大們會發出**:「指紋支付而已,客戶端現成的介面,有何難?」
系統介面行不行?
好在,從android 6.0開始,系統提供了標準的fingerprintmanager。這一重大利好,讓做著類似需求的程式猿們彷彿在黑暗中看到一絲光明,因為這個介面看上去是那麼簡單易用。無論你是什麼品牌的手機,只要是android 6.0或更新的系統,按照下面的寫法,就可以實現指紋認證功能:
fingeprintmanager mfingeprintmanager = ...
mfingeprintmanager.authenticate(null,
mcancellationsignal, 0 , new authenticationcallback
(), null);
複製**
設計本身也很簡單:
系統認證介面
看上去很完美,彷彿實現指紋支付根本不用開發1個版本,只用1小時,對不對!
但是仔細看下這個介面,感覺**不太對:介面僅僅返回認證成功/失敗,如果直接信任這個結果,手機被root了,豈不是隨時可以將認證結果從false改為true?
那我們換一種思路:root的手機不讓用指紋支付行不行?
傻孩子,那你怎麼判斷手機是不是root呢?不也是通過android介面獲取的值麼?這個值一樣可以被改掉。
這張圖看上去不明覺厲,原理其實並不難:google在android 6.0之後,允許使用者在應用中生成一對非對稱金鑰,將私鑰儲存在tee中(什麼是tee?稍後會講),任何人,包括應用自己甚至android系統都無法獲取私鑰,除非使用者使用指紋授權才能使用,簽名或者加密傳入的資料,然後輸出密文。這樣的話,就可以利用金鑰的簽名-驗籤機制(小白不懂什麼是簽名驗籤?google下咯~或者看這篇文章解釋簽名的部分),只有使用者使用指紋簽名之後,才能產生正確的簽名,後台驗籤即可,這樣就能保證鏈路安全。
這個設計非常巧妙,但是google百密一疏:如果黑客在金鑰生成的時候就攔截了請求,替換為自己的金鑰,那麼後面簽名和加密,用的也是黑客的金鑰,那麼整套系統的設計也就崩塌了。
hack示意
另外還有乙個問題,如果僅僅返回true/false,那麼只要是錄入到裝置內的指紋,就可以假冒你的身份支付。這對於家裡有熊孩子的家長來說,簡直就是銀行卡噩夢。雪上加霜的是,對於android裝置而言(其實ios也是一樣),只要知道了鎖屏密碼就可以錄入新的指紋。如果支付後台直接信任指紋認證結果,就相當於將原本非常秘密的支付密碼,退化到了鎖屏密碼的級別。這樣,無論支付後台做了多麼嚴密的風控策略,按照木桶原理,從根本上整個系統就是不符合支付安全的。
研究過這些之後,發現並不可直接使用任何乙個方案,場面一度尷尬。沒有合適的輪子,怎麼辦?
沒有輪子,能造輪子麼?
讓我們回頭看看android系統的指紋介面設計:
那google沒有做到什麼呢?
如果以做標準的要求來實現soter,那麼除了剛剛所述的系統介面缺陷之外,系統設計時還需要考慮:
如何產生乙個可信的信任根(裝置根金鑰)?
裝置根金鑰流程
廠商在產線上對裝置下發生成裝置根金鑰命令;
有了裝置根金鑰之後,認證鏈的構造邏輯就清晰了很多:採用金鑰鏈的形式,用已認證的金鑰來認證未認證的金鑰就可以了!
如何構造完整認證流程?
方**有了,實施就變得簡單。
架構
soter架構圖
我們十分欣賞google的指紋和金鑰模組介面設計,因此,我們與廠商合作,在此基礎上新增patch包,即可迅速實現整個上層架構。
準備應用金鑰(ask)
準備應用金鑰流程示意圖
應用第一次啟動時,或者在第一次使用業務之前,請求生成裝置根金鑰;
金鑰生成之後,私鑰在被tee保護,加密儲存;
公鑰和裝置id等相關資訊,在tee內直接被裝置金鑰私鑰簽名之後,返回給應用;
應用將公鑰相關資訊和簽名傳輸至應用後台;
tam使用對應的裝置金鑰公鑰驗籤,通過之後返回給應用;
應用後台儲存對應的應用公鑰。
傳輸給後台的原串示例:
注2:本意為類unix系統中使用者id,在android系統中,一般而言每乙個應用都有乙個uid,可用於區分應用以及許可權控制。注意,uid不同,對應的應用金鑰與業務金鑰均不同,後台應將uid與cpu_id一起區分金鑰。
準備業務金鑰(auth key)
準備業務金鑰流程示意圖
應用在開通業務時(如指紋支付),請求生成業務金鑰。同時,在生成時宣告該金鑰除非使用者指紋授權,否則私鑰不可使用。
金鑰生成之後,私鑰在被tee保護,加密儲存;
公鑰和裝置id等相關資訊,在tee內直接被應用金鑰私鑰簽名之後,返回給應用;
應用將公鑰相關資訊和簽名傳輸至應用後台;
驗籤成功之後,應用後台儲存對應的業務金鑰。
傳輸資料與含義與應用金鑰相同,不再贅述。
認證流程
認證流程示意圖
客戶端請求後台,獲取挑戰因子;
獲取挑戰因子之後,將挑戰因子送往tee,準備簽名結構體,準備簽名;
應用請求使用者指紋授權;
使用者指紋授權後,直接將本次認證使用指紋在本裝置內的索引傳輸給金鑰模組,在tee內使用業務金鑰私鑰簽名挑戰因子以及該索引。
應用獲取原串與簽名串後,傳輸至應用後台。應用後台使用對應的業務金鑰公鑰驗籤,如果成功,則此次認證或者開通請求合法。
傳輸給後台原串示例
流程是否符合要求?
輪子造好了,我們在自我欣賞的路上越走越遠。回過頭來看,soter是否滿足了我們的要求呢?
當然了,我們的方案得到了各大廠商、晶元上的認可,在短時間內,已經擁有了數億裝置的支援,覆蓋幾乎所有的主流手機品牌,因此應用接入完全無須考慮是否需要多裝置適配,或者質疑適配不足。順便,我們支援了vivo和oppo的5.x指紋機型,即使系統本身不具有統一的指紋介面。
然而,還有最後兩點沒有做到:
解決這兩個問題的方法只有:開源!
我們開源了什麼?
為了滿足不同應用的不同場景,我們開源了:
使用soter最快能多塊?如果你只需要做鎖屏之類對安全性要求不高的需求,只需要:
在專案的build.gradle中,新增 soter依賴
dependencies 複製**
在 androidmanifest.xml中新增使用指紋許可權
"android.permission.use_fingerprint"/>複製**
initializeparam param = new initializeparam.initializeparambuilder()
.setscenes(0) // 場景值常量,後續使用該常量進行金鑰生成或指紋認證
.build();
soterprocesscallback() ,
param);複製**
需要在使用指紋認證之前生成相關金鑰
soterprocesscallback() ,false, true, 0, null, null);複製**
金鑰生成完畢之後,可以使用封裝介面呼叫指紋感測器進行認證。
authenticationparam param = new authenticationparam.authenticationparambuilder()
.setscene(0)
.setcontext(mainactivity.this)
.setfingerprintcanceller(msoterfingerprintcanceller)
.setprefilledchallenge("test challenge")
.setsoterfingerprintstatecallback(new
soterfingerprintstatecallback
() ).build();
soterprocesscallback() , param);複製**
那麼,讓我們再回顧下開頭的場景:「我們要做指紋支付,下個版本上…」,想必你已經知道怎麼做了,括弧逃~
問答為什麼手機屏下指紋技術難以實現?
作業系統指紋識別概述
微信怎麼做授權登入的流程
發布一下自己寫的乙個簡易的授權登入的 可以直接複製使用 html 如下 class mai btn open type getuserinfo bindgetuserinfo bindgetuserinfo 授權登入 med wxjs page next function e 生命週期函式 監聽頁面...
怎麼申請微信支付介面
12 設定登入帳號基本資訊。3查收自己的註冊郵箱,點選鏈結,啟用帳號。4選擇自己對應的選項,進行商戶資訊登記。56 78確認開始申請,線上確認命名規則協議。點選下一步。9填寫認證相關資料及發票資訊。10end 12.申請函必須加蓋公章 2將準備好的申請函交給相關商務人員進行提交。end1 2點選 填...
微信支付服務商怎麼賺錢 怎樣成為支付寶微信的服務商
2019年4月17日,支付寶的刷臉支付終端 蜻蜓 宣布推出二代產品,在發布會現場十秒一千臺機器瞬間搶光,2天,蜻蜓 二代訂單量破萬,僅僅幾天過後,蜻蜓 二代乙個月的庫存便被銷售一空。而在 蜻蜓 大規模商用背後,除了支付寶本身的演算法與風控體系進化作為托底之外,還要依靠一項功不可沒的產品 3d結構光攝...