這次說一下U2F應用層的協議诡右,在FIDO的規(guī)范中叫做U2F Raw Message Formats。這個協議也就是在前兩篇FIDO U2F HID協議和FIDO U2F NFC協議之上的實現U2F應用的協議域那,其實就是U2F應用的智能卡APDU次员,這個應用真正實現U2F兩步認證的應用注冊和認證登錄淑蔚。
U2F的使用場景一般是分為注冊和認證兩個情形刹衫,下面簡單的說一下U2F的大概使用過程带迟。
注冊:
在支持U2F兩步認證的系統(tǒng)中仓犬,比如Github等婶肩,首先需要在自己的賬戶中綁定U2F設備貌夕,先將自己的U2F令牌插入計算機啡专,Github會通過FIDO客戶端(瀏覽器)向U2F令牌發(fā)送注冊請求们童,這個注冊請求包括了隨機參數慧库、應用參數等要素齐板,令牌給這個應用對應的生成一個用戶密鑰對和對應的key handle,并使用內部attestation certificate對應的私鑰對用戶公鑰眯停、應用參數和隨機參數等信息進行簽名卿泽,并將用戶公鑰签夭、key handle措拇,attestation certificate煌妈,前述簽名等數據返回給應用璧诵。應用首先驗證attestation certificate之宿,并使用attestation certificate驗證了簽名比被,然后將key handle和對應的用戶公鑰保存在用戶賬戶中等缀,完成U2F設備的綁定娇昙。
認證:
用戶登錄到支持U2F兩步認證的系統(tǒng)時冒掌,用戶在應用登錄界面輸入完賬號和口令后股毫,應用通過FIDO客戶端向U2F令牌發(fā)送認證請求铃诬,認證請求包括隨機參數,應用參數颗胡,key length哑蔫,key handle等闸迷。U2F令牌收到認證請求后,首先通過key length和key handle找到對應的注冊信息腥沽,檢查請求認證的應用是否就是最初注冊的應用,如果檢查通過今阳,那么使用對應的用戶私鑰對應用參數茅信、挑戰(zhàn)信息蘸鲸、認證計數器等信息進行簽名酌摇,然后將簽名窑多、認證計數器返回給應用埂息。應用使用注冊時獲得的用戶公鑰對簽名進行驗證耿芹,如果能驗證通過則完成兩步驗證吧秕,應用登錄成功砸彬,否則兩步驗證失敗,拒絕登錄蛀蜜。
1.U2F 消息封包
U2F協議是基于請求-響應方案的磅摹,當請求者發(fā)送一個請求消息到U2F設備中時户誓,U2F會返回一個響應消息給請求者帝美。
請求報文會被封裝后發(fā)送到下一層悼潭。拿簽名請求舉例來說舰褪,U2F協議是FIDO客戶端告訴下一層的通信層它要發(fā)送一個簽名請求抵知,然后發(fā)送原始消息內容。U2F協議也規(guī)定了當如何返回響應的原始消息立砸,如果命令執(zhí)行失敗后的錯誤碼颗祝。
在現在這一版的U2F協議中螺戳,消息的封包是基于ISO7816-4:2005 擴展APDU格式。
1.1 請求消息格式 Request Message Framing
原始的請求消息封裝成一個APDU命令折汞,APDU的格式如下:
CLA INS P1 P2 [Lc <request-data>] [Le]
CLA : 保留給底層傳輸協議使用倔幼,比如ISO/IEC 7816里規(guī)定可以指示是否使用密文,是否計算MAC等等爽待。這里應用應該設置CLA為0损同。
INS : U2F 指令翩腐,具體的定義下面會寫。
P1,P2 : 參數1和2膏燃,每個指令都有各自的定義茂卦。
Lc : request-data的長度,如果沒有request-data,Lc省略组哩。
Le : 期待返回的響應數據的長度幕袱,如果不存在響應數據,Le省略。
APDU的準確格式取決于編碼的選擇摄欲。允許使用兩種不同的APDU編碼:short和extended length迟隅。不同的地方在于請求數據的長度吼野,Lc和期待響應數據的最大長度,Le的編碼。
1.1.1 指令和參數
指令 | INS | P1 | P2 |
---|---|---|---|
U2F_REGISTER | 0x01 | 0x00 | 0x00 |
U2F_AUTHENTICATE | 0x02 | 0x03|0x07|0x08 | 0x00 |
U2F_VERSION | 0x03 | 0x00 | 0x00 |
VENDOR SPECIFIC | 0x40-0xBF | NA | NA |
1.1.2 短編碼 Short Encoding
在短編碼中锐想,請求數據的最大長度是255字節(jié)藕帜。Lc按下面的方法編碼:
Nc=|<request-data>|时甚。如果Nc=0吻贿,那么Lc省略,否則使用Nc的值編碼為一個字節(jié)賦值給Lc。
如果指令不期望應用返回任何響應數據,那么Le可以省略。否則在短編碼中诞仓,Le按下面的方法編碼:
Ne = 響應數據的最大值翼虫,在短編碼中Ne的最大值為256字節(jié)。
Ne的值在1和255之間時,Le直接使用Ne的值诉稍。當Ne=256時,Le的值賦值為0心褐。
1.1.3 擴展長度編碼 Extended Length Encoding
在擴展長度編碼中桶至,請求數據的最大長度為65535字節(jié)伪窖。Lc按下面的方法編碼:
Nc= |<request-data>|。如果Nc=0,Lc省略钞它。否則Lc這樣編碼:0 MSB(Nc) LSB(Nc)
這里MSB(Nc)是Nc的高字節(jié)遭垛,LSB(Nc)是Nc的低字節(jié)溃卡。
換一種說法卷仑,請求數據是以3個字節(jié)開頭,第一個字節(jié)是0助币,然后后面跟著兩個字節(jié)的請求數據長度(大端字節(jié)序)浪听。
如果指令不期望應用返回任何響應數據,Le可以省略眉菱。否則在擴展長度編碼中迹栓,Le按下面的方法編碼:
Ne=響應數的最大長度。在擴展長度編碼中俭缓,Ne的最大值為65535字節(jié)克伊。
當Ne的值在1和65535之間時,Le1=MSB(Ne)华坦,Le2=LSB(Ne)愿吹,這里MSB(Nc)是Nc的高字節(jié),LSB(Nc)是Nc的低字節(jié)惜姐。
當Ne=65536犁跪,Le1=0椿息,Le2=0。
當Lc存在的時候坷衍,比如Nc>0寝优,Le編碼為:Le1 Le2
當Lc不存在的時候,比如Nc=0枫耳,Le編碼為:0 Le1 Le2
換句話說乏矾,當Lc不存在的時候,Le有一個字節(jié)值為0的前綴迁杨。
1.2 響應消息格式 Response Message Framing
原始響應消息的格式如下:
<request-data> SW1 SW2
SW1和SW2是兩個字節(jié)的狀態(tài)字钻心,狀態(tài)字的定義在下面,SW1是高字節(jié)铅协,SW2是低字節(jié)扔役。
1.3 狀態(tài)代碼 Status Code
以下ISO7816-4中定義的的狀態(tài)字,在U2F中有特殊的含義:
- SW_NO_ERROR(0x9000) : 指令執(zhí)行成功警医,沒有錯誤亿胸。
- SW_CONDITIONS_NOT_SATISFIED(0x6985) : 因為需要進行用戶在場測試導致請求被拒絕
- SW_WRONG_DATA(0x6A80) : 因為非法的key handle導致請求被拒絕
- SW_WRONG_LENGTH (0x6700) : 請求長度不正確
- SW_CLA_NOT_SUPPORTED (0x6E00) : CLA字節(jié)不支持
- SW_INS_NOT_SUPPORTED (0x6D00) : 指令INS字節(jié)不支持
U2F的供應商可以定義其他供應商自定義的代碼,提供更多的錯誤信息预皇。U2F FIDO客戶端只處理上面列出的錯誤代碼侈玄。
2.注冊消息
2.1注冊消息 U2F_REGISTER
注冊消息是需要使用U2F認證的網站在第一使用時,需要注冊U2F設備的一個操作吟温,注冊請求消息有兩部分序仙,如上圖所示:
challenge parameter[32 bytes], challenge parameter是對客戶端數據(Client Data)進行SHA-256運算得到的哈希值鲁豪。Client Data是一個由FIDO客戶端準備的JSON數據結構潘悼。
application parameter[32 bytes],application parameter是請求注冊的應用id的SHA-256結果爬橡。
2.2 注冊消息的響應: 錯誤 需要Test-of-User-Presence
如果U2F令牌無法獲得Test-of-User-Presence測試治唤,那么令牌將返回這個消息。
2.3 注冊消息的響應: 成功
如果注冊成功糙申,U2F令牌會創(chuàng)建一個新的密鑰對宾添。需要注意的是U2F令牌在返回注冊成功的響應消息之前,需要用戶確認(一般是帶觸點按鍵的柜裸,按下按鍵或者觸點缕陕,沒有按鍵的一般是拔插一下設備),否則令牌應該返回錯誤碼test-of-user-presence-required疙挺。
如果注冊成功扛邑,返回的響應消息格式如上圖所示。
reserved byte [1字節(jié)] 保留字節(jié)永遠是0x05
user public key [65bytes] 橢圓曲線公鑰铐然,x,y表示的P-256 NIST橢圓曲線上的點(未壓縮)
key handle length byte [1byte] key handle的長度蔬崩,值為0-255之間的無符號數
key handle [長度根據上面handle lenght確定] U2F令牌用來區(qū)分產生的密鑰對的
attestation certificate [變長] X.509 DER格式的證書恶座;解析X.509證書可以明確的確定結尾,剩下的字節(jié)就是signature了
signature [變長舱殿,71-73字節(jié)] ECDSA簽名(在P-256上)對下面數據進行的簽名奥裸,簽名的數據為0x00,application parameter, challenge parameter,key handle,user public key
簽名依賴方可以使用attestation certificate中的公鑰進行驗證险掀。依賴方也應該驗證attestation certificate是可信的CA頒發(fā)的沪袭。
一旦依賴方驗證了簽名,它就應該保存public key和key handle樟氢,這樣就可以在之后的認證操作中使用了冈绊。
說明
這里的attestation certificate是一批硬件里都用相同的證書,并不會每一個U2F硬件單獨使用一個證書埠啃。曾經某個互聯網大廠搞物聯網安全的負責人說死宣,怎么可能一堆硬件都用同樣的證書呢,肯定是每個硬件單獨有證書如何如何碴开。實際上FIDO這里設計的是毅该,一批硬件都用相同的attestation certificate,如果這批硬件有風險潦牛,直接吊銷這批硬件使用的證書即可停用整批硬件眶掌。
3.認證消息
3.1 認證請求消息 U2F_AUTHENTICATE
這個消息是U2F令牌進行認證的指令,FIDO客戶端首先連接依賴方獲得一個挑戰(zhàn)值(隨機數)巴碗,然后構造認證請求報文下發(fā)到U2F令牌中朴爬,認證請求報文有下面5部分:
-
control byte[P1]
值取0x07的時候表示check-only,U2F令牌只是簡單的檢查傳入的key handle是不是這個令牌產生的橡淆,并且是不是給這個應用創(chuàng)建的召噩。如果是,U2F令牌必須返回一個認證響應逸爵。
值取0x03時具滴,表示強制用戶出示并簽名,U2F令牌執(zhí)行一個真實的簽名并響應一個認證應答消息(好別扭)
值取0x08的時候表示不強制用戶出示并簽名师倔,在不用驗證用戶存在的情況下抵蚊,就讓U2F令牌執(zhí)行簽名
challenge parameter [32bytes] Client Data的SHA-256哈希數據,Client Data是FIDO客戶端生成的一個json數據結構
application parameter [32bytes] 是請求注冊的應用id的SHA-256結果
key handle length byte [1 byte] key handle的長度溯革,取值為0-255的無符號數
key handle [變長] 注冊時獲得的key handle
3.2 注冊指令的響應:錯誤 需要Test-of-User-Presence
3.3 注冊指令的響應:錯誤 Bad KeyHandle
U2F令牌如果發(fā)現key handle不是自己創(chuàng)建的贞绳,或者key handle是這個U2F令牌創(chuàng)建的,但是是對應其他的application parameter致稀,直接返回Bad Key Handle錯誤冈闭。
3.4 注冊指令的響應:成功
如果認證成功,返回響應如下
U2F令牌在處理完認證請求消息后抖单,返回上面的消息萎攒。
user presence byte [1 byte] bit0設置為1遇八,表示用戶確認過了(這一版的協議不明確的要求在進行認證請求是用戶確認的方式)。這個字節(jié)剩下的bit耍休,FIDO保留以后使用刃永,現在都設置為0即可。
counter [4bytes] 一個大端的計數器羊精,U2F令牌每次認證都增加一次斯够。
-
signature 對以下數據的ECDSA簽名(P-256):
- application parameter 來自認證請求
- user presence byte [1 byte] 參看上面定義
- counter [4 bytes] 參看上面的定義
- challenge paraeter [32 bytes] 來自認證請求
簽名使用ANSI X9.62格式進行編碼。
依賴方使用注冊時獲得的的公鑰來驗證簽名喧锦。
4 其他消息 Other Messages
4.1 獲得版本號 U2F_VERSION
FIDO客戶端用來獲得U2F協議的版本读规。版本的描述在U2F_V2這個文檔中。
響應消息的原始數據為ASCII編碼的字符串'U2F_V2',不含引號和任何結束符燃少。
短編碼APDU指令如下:
CLA | INS | P1 | P2 | Le |
---|---|---|---|---|
00 | 03 | 00 | 00 | 00 |
擴展長度編碼APDU指令如下:
CLA | INS | P1 | P2 | Le |
---|---|---|---|---|
00 | 03 | 00 | 00 | 00 00 00 |
4.2 擴展和廠商定義指令
U2F_VENDOR_FIRST 和 U2F_VENDOR_LAST之間的指令可以用來作為廠商定義指令束亏。比如廠商可以加一些測試用的指令。FIDO客戶端永遠不會生成調用這些命令的請求阵具。這個范圍之外的指令為RFU或者還沒使用碍遍。