轉:http://suntus.github.io/2019/05/09/HKDF%E7%AE%97%E6%B3%95/
是tls1.3中關於密鑰生成的重要的基礎算法,跟密鑰推導密切相關。
HKDF叫HMAC-based KDF(key derivation function),基於HMAC的密鑰推導函數
,所以我們先認識HMAC算法。
1. HMAC
基於一個共同密鑰,在兩個對端之間提供消息完整性確認的機制叫"message authentication codes(MAC),消息認證碼"
。其實就是將消息進行hash,得到的hash值附加到消息之后,隨消息一起發送,對端接收后,同樣進行hash,來驗證消息是否被篡改——關鍵點在不同數據得到的hash值一定不同——其中得到的hash值就是MAC(在別的語境里邊也叫消息摘要)。另外,為了避免使用同樣的hash函數對相同數據進行操作總是得出同樣的摘要,額外加入一個密鑰,這樣使用不同密鑰就可以得出不同的MAC,當然,這個密鑰是兩個對端都知道的。這樣,我們就得到了基於加密hash的消息完整性認證的算法——Hash-based MAC。
1.1 HMAC定義如下:
輸入:
- 使用的加密hash函數H,輸出長度為hashLen
- 使用的密鑰K,長度hashLen <= Klen <= 64,如果K的長度超過64,則先用hash函數進行一次hash,用得到的值作為K
- 需要認證的數據text
輸出:
1 |
消息完整性認證碼HMAC |
過程:
1 |
定義 ipad = 64個0x36, opad = 64個0x5c |
目的:
1 |
為text生成一個HMAC消息完整性認證碼,輸出長度就是hash函數的輸出長度 |
2. HKDF
HKDF的主要目的使用原始的密鑰材料,派生出一個或更多個能達到密碼學強度的密鑰(主要是保證隨機性)——就是將較短的密鑰材料擴展成較長的密鑰材料,過程中需要保證隨機性。
HKDF包含兩個基本模塊,或者說兩個基本使用步驟:1. 提取 Extract, 2. 擴展 Expand
。
- 提取:使用原始的密鑰材料,派生出一個符合密碼學強度的偽隨機密鑰
- 擴展:使用第1步驟提取出來的偽隨機密鑰,擴展出指定長度的密鑰(同時保證隨機性)。
2.1 HKDF-Extract
輸入:
1. HMAC使用的hash函數H,H輸出長度是hashLen
2. 原始密鑰材料IKM(input keying material)
3. 另外的隨機源salt, 如果沒有,默認是hashLen長度的0串
輸出:
1 |
hashLen長度的偽隨機密鑰prk(pseudorandom key) |
過程:
1 |
prk = HKDF-Extract(H, salt, IKM) = HMAC-Hash(H, salt, IKM) |
目的:
1 |
使用salt增加IKM的隨機性 |
2.2 HKDF-Expand
輸入:
1 |
1. HMAC使用的hash函數H,H輸出長度是hashLen |
輸出:
1 |
L長度的OKM(output keying material) |
過程:
1 |
N = ceil(L/hashLen) |
目的:
1 |
將PRK擴展到指定長度L,同時保持密碼學強度(隨機性) |
3. 總結
- HKDF是密鑰推導算法,根據一個原始密鑰材料,推導出指定長度的密鑰;
- HKDF基於HMAC;
- HMAC是基於加密hash函數的消息完整性認證算法,主要目的是認證消息完整性。在這里被用於增加原始密鑰材料的隨機性;
- HKDF包含兩步:(1) 提取Extract, (2) 擴展Expand;
- HKDF-Extract就是HMAC,取IKM的認證碼,也就相當於用額外的隨機源salt(Key)增加了IKM(text)的隨機性;
- HKDf-Expand就是將短密鑰變長,同時保證隨機性。