Pour les algorithmes de chiffrement modernes, l'un des facteurs affectant la force cryptographique est la longueur de la clé. Selon la norme NIST , la force cryptographique des algorithmes doit être d'au moins 112 bits. Pour les algorithmes symétriques, cela signifie que la longueur de clé minimale doit être de 224 bits, pour ceux asymétriques basés sur la théorie des nombres (par exemple, résoudre le problème de factorisation pour l' algorithme RSA ), la longueur fiable minimale est de 2048 bits [1]. La cryptographie sur des courbes elliptiques n'économise pas l'utilisation de grandes touches.
Mais que faire si les clés existantes ne sont pas assez longues pour être utilisées en toute sécurité dans nos algorithmes choisis? Ou avons-nous besoin de plus de clés que nous n'en avons? C'est là que KDF (Key Derivation Function) vient à la rescousse - il s'agit d'une fonction qui génère une ou plusieurs clés secrètes cryptographiquement fortes basées sur une valeur secrète donnée (dans la littérature appelée clé principale, et parfois clé principale) à l'aide d'une fonction pseudo-aléatoire. Et ce qui est particulièrement important, il vous permet de définir la longueur de la clé générée à la suite de votre travail, et sa force sera la même que celle d'une clé aléatoire de même longueur [2], [3].
KDF . , - HKDF, , Python'.
1. KDF
, KDF , "--" (- - extract-and-expand):
"" . - "" , . ;
, , "" . .
.
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.
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] Directives générales pour l'utilisation de KDF: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Cr2.pdf , pp. 17, 22