
最新の暗号化アルゴリズムの場合、暗号強度に影響を与える要因の1つはキーの長さです。NIST標準によると、アルゴリズムの暗号強度は少なくとも112ビットである必要があります。対称アルゴリズムの場合、これは最小キー長が224ビットであることを意味し、数値理論に基づく非対称アルゴリズムの場合(たとえば、RSAアルゴリズムの因数分解問題の解決)、信頼できる最小長は2048ビットです[1]。楕円曲線の暗号化では、大きなキーを使用しても節約できません。
しかし、既存のキーが、選択したアルゴリズムで安全に使用できるほど長くない場合はどうなるでしょうか。それとも、私たちが持っているよりも多くのキーが必要ですか?ここで、KDF(Key Derivation Function)が役に立ちます。これは、疑似ランダム関数を使用して、特定の秘密値(文献ではマスターキー、場合によってはマスターキーと呼ばれます)に基づいて1つ以上の暗号的に強力な秘密鍵を生成する関数です。そして特に重要なのは、作業の結果として生成されるキーの長さを設定できることです。その強度は、同じ長さのランダムキーと同じになります[2]、[3]。
KDF . , - HKDF, , Python'.
1. KDF
, KDF , "--" (- - extract-and-expand):
"" . - "" , . ;
, , "" . .
![図1.KDFのアルゴリズム[4] 図1.KDFのアルゴリズム[4]](https://habrastorage.org/getpro/habr/upload_files/1c8/bcc/d4e/1c8bccd4ef00c38fffa625fe7c0734a2.png)
.
Randomness Extraction:
- - :
:
SKM (Source Keying Material) - ( ) , PRK, - . , "" KDF;
XTR (randomness eXTRactor) - . , SKM PRK. , ( );
PRK (PseudoRandom Key) - . ;
XTSalt (eXTractor Salt) - , .. ( ) , , . .
, . - KDF . , HKDF, , -.
Key Expansion:
(PRK) L, . :
:
PRF* (PseudoRandom Function with variable length) - , . , counter feedback mode;
CTXInfo (context information) - ( , , , ). , , , ;
PRK - ;
DKM (Derived Keying Material) - L.
, . ? ?
, . , KDF "" , . , "" , .
, - (-) , , . , premaster secret TLS , (IETF). , , , , PRF* ( PRF* ).
2. HKDF
HKDF (HMAC Key Derivation Function) KDF. KDF ( PRF*), , HMAC.
HKDF
HMAC , - , - , . HashLen ( ), . || ("") . HMAC(key, a || b) , - key a b.
, HKDF :
XTS, SKM CTXInfo , KDF, K(i), i = 1,...,t :
PRK = HMAC-Hash(XTS, SKM) - , (SKM) (PRK). PRK , HMAC (HMAC-Hash) HashLen . , - , "" - . , SKM , PRK .
K(1) = HMAC-Hash(PRK, CTXinfo || 0),
K(i+1) = HMAC-Hash(PRK, K(i) || CTXinfo || i), 1 ≤ i < t,
t = L/HashLen - "", L. i . , HashLen, L K. L: L ≤ 255 * HashLen.
![図2.HKDFの作業スキーム[4] 図2.HKDFの作業スキーム[4]](https://habrastorage.org/getpro/habr/upload_files/205/a2a/ff1/205a2aff1c895a67d1937409307ad397.png)
KDF, - ; , HashLen. , , -, XTSalt PRK.

. . , "" , . , , , .. , HKDF , . SKM.
3. HKDF
HKDF : Java, JavaScript, PHP, Python. , , , , :
import hashlib
import hmac
from math import ceil
hash_len = 32
def hmac_sha256(key, data):
return hmac.new(key, data, hashlib.sha256).digest()
def hkdf(length: int, ikm, salt: bytes = b"", CTXinfo: bytes = b"") -> bytes:
# - , , ,
# hash_len:
if len(salt) == 0:
salt = bytes([0] * hash_len)
# :
# -:
prk = hmac_sha256(salt, ikm)
k_i = b"0" # - 0
dkm = b"" # Derived Keying Material
t = ceil(length / hash_len)
# : - K(i),
# . ,
# K(i) K(i-1):
for i in range(t):
k_i = hmac_sha256(prk, k_i + CTXinfo + bytes([1 + i]))
dkm += k_i
# hash_len, length :
return dkm[:length]
:
>>> output = hkdf(100, b"input_key", b"add_some_salt")
>>>
>>> print(''.join('{:02x}'.format(byte) for byte in output))
2bcd8350cc31b6945b23b2a47add4d5ec4b1bd9fad0387590bf4e9f4d34ea456e63267c765e7cd5451df1f6f18f41eaba20de594fd8c6a008120276438d18fc4122ec152fff03204c966261b60408a569b6b0e3527ae4a34570c62b2d060fd15f3176a36
>>>
>>> print(len(out))
100
, hkdf
output "input_key" "add_some_salt". , , , . . 100 , , !
:
IETF: https://tools.ietf.org/html/rfc5869
: https://eprint.iacr.org/2010/264
- KDF: https://www.coursera.org/lecture/crypto/key-derivation-A1ETP
[1] https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf, 9.
[2] https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-108.pdf, 16-19;
[3] https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57pt1r5.pdf, 108-109;
[4] KDFを使用するための一般的なガイドライン:https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Cr2.pdfを、頁17、22。