HKDF
Documentation |
#include <cryptopp/hkdf.h>
|
HKDF is HMAC-based Extract-and-Expand key derivation function by Krawczyk and Eronen. HKDF is state of the art and used in protocols like IPsec. The Crypto++ implementation is from Cryptographic Extraction and Key Derivation: The HKDF Scheme and RFC 5869, HMAC-based Extract-and-Expand Key Derivation Function (HKDF).
HKDF provides the KeyDerivationFunction
interface rather than the MessageAuthenticationCode
interface. The KDF interface consists of a default constructor and a method DeriveKey
which derives a user key form the parameters.
All Crypto++ hashes derive from HashTransformation
. The base class provides functions like Update
, Final
and Verify
. You can swap-in any hash for any other hash in your program. You can also use ChannelSwitch
to send data to multiple hashes at the same time.
Constructor
HKDF provides a default constructor.
DeriveKey
unsigned int DeriveKey (byte *derived, size_t derivedLen, const byte *secret, size_t secretLen, const byte *salt, size_t saltLen, const byte *info, size_t infoLen) const
derived
is the buffer to receive the derived key. derivedLen
is the size of the buffer, in bytes.
secret
is private information to use during derivation. secretLen
is the size of the buffer, in bytes.
salt
is possibly public information to use during derivation. saltLen
is the size of the buffer, in bytes.
info
is additional, possibly public information to use during derivation. infoLen
is the size of the buffer, in bytes.
DeriveKey
returns the number of bytes returned in the derived
buffer.
salt
and info
are used to help distinguish one instance or run of the algorithm from another. The parameters can be NULL
.
Sample Program
The sample program below demonstrates a HKDF with SHA1.
$ cat test.cxx #include <iostream> #include <string> #include "cryptlib.h" #include "hkdf.h" #include "sha.h" #include "filters.h" #include "hex.h" int main(int argc, char* argv[]) { using namespace CryptoPP; byte password[] ="password"; size_t plen = strlen((const char*)password); byte salt[] = "salt"; size_t slen = strlen((const char*)salt); byte info[] = "HKDF key derivation"; size_t ilen = strlen((const char*)info); byte derived[SHA1::DIGESTSIZE]; HKDF<SHA1> hkdf; hkdf.DeriveKey(derived, sizeof(derived), password, plen, salt, slen, info, ilen); std::string result; HexEncoder encoder(new StringSink(result)); encoder.Put(derived, sizeof(derived)); encoder.MessageEnd(); std::cout << "Derived: " << result << std::endl; return 0; }
Running the program results in the following.
$ ./test.exe Derived: 9912F20853DFF1AFA944E9B88CA63C410CBB1938
You can swap-in any hash class that provides a blocksize. The code below uses BLAKE2b as the message digest. The BLAKE2b sample below requires Commit 758939ab2e1b.
$ cat test.cxx #include <iostream> #include <string> #include "cryptlib.h" #include "hkdf.h" #include "blake2.h" #include "filters.h" #include "hex.h" int main(int argc, char* argv[]) { using namespace CryptoPP; byte password[] ="password"; size_t plen = strlen((const char*)password); byte salt[] = "salt"; size_t slen = strlen((const char*)salt); byte info[] = "HKDF key derivation"; size_t ilen = strlen((const char*)info); byte derived[BLAKE2b::DIGESTSIZE]; HKDF<BLAKE2b> hkdf; hkdf.DeriveKey(derived, sizeof(derived), password, plen, salt, slen, info, ilen); std::string result; HexEncoder encoder(new StringSink(result)); encoder.Put(derived, sizeof(derived)); encoder.MessageEnd(); std::cout << "Derived: " << result << std::endl; return 0; }
Running the program results in the following.
$ ./test.exe Derived: 4FF891CB129EC9F2B4CF715897B3FC5A0F58C61EC2CD59D71C635C75810EC04763E8C36 BAC7462D58820734B8B09A4FCB956743CDD6FA6976B26B1A1C00E0786
Independent Keys
Deriving several security parameters from a common secret is a frequent operation. The property is called Key Independence and you should ensure your security parameters are independent. Key independence would be useful for deriving a cipher and mac key, a cipher key and iv, or multiple keys for Multiple Encryption.
The sample program below demonstrates a HKDF with SHA256. Notice two different labels are used. First, the label HKDF key derivation to derive the key; and second, the label HKDF iv derivation to derive the initialization vector. The version number for the algorithm is also used during derivation.
Using the version number during derivation is a good idea. It ensures different versions of your algorithm have distinct keys. Distinct keys for different versions of an algorithm would have avoided WinZip's vulnerability in Attacking and Repairing the WinZip Encryption Scheme.
$ cat test.cxx #include <iostream> #include <string> #include "cryptlib.h" #include "hkdf.h" #include "sha.h" #include "filters.h" #include "files.h" #include "aes.h" #include "modes.h" #include "hex.h" int main(int argc, char* argv[]) { using namespace CryptoPP; byte password[] ="password"; size_t plen = strlen((const char*)password); byte salt[] = "Version 1"; size_t slen = strlen((const char*)salt); byte info1[] = "HKDF key derivation"; size_t ilen1 = strlen((const char*)info1); byte info2[] = "HKDF iv derivation"; size_t ilen2 = strlen((const char*)info2); byte key[AES::DEFAULT_KEYLENGTH]; byte iv[AES::BLOCKSIZE]; HKDF<SHA256> hkdf; hkdf.DeriveKey(key, sizeof(key), password, plen, salt, slen, info1, ilen1); hkdf.DeriveKey(iv, sizeof(iv), password, plen, salt, slen, info2, ilen2); std::cout << "Key: "; StringSource(key, sizeof(key), true, new HexEncoder(new FileSink(std::cout))); std::cout << std::endl; std::cout << "IV: "; StringSource(iv, sizeof(iv), true, new HexEncoder(new FileSink(std::cout))); std::cout << std::endl; CBC_Mode<AES>::Encryption enc; enc.SetKeyWithIV(key, sizeof(key), iv, sizeof(iv)); // Use AES/CBC encryptor return 0; }
Running the program results in the following.
$ ./test.exe Key: 059C0BAB3BBC352D14570606438AF08E IV: EE744BF9F30D05046FBE25BF6C39E653
And when it comes time to release version 2 of your software, it will derive a different set of secrets:
$ ./test.exe Key: 964F3C02C9B891615EEB55F4A21F90DB IV: 22F722170B0CE4D49BB398CB9C249C1C
Downloads
No downloads.