HMAC
Documentation |
#include <cryptopp/hmac.h>
|
HMAC is a hash-based MAC algorithm specified in FIPS 198. A HMAC is the hash equivalent of a CMAC. HMACs can be used when a hash function is more readily available than a block cipher.
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.
Sample Programs
There are two sample programs below. The first sample program below demonstrates a HMAC with SHA256 using filters (see pipelining). The second sample program uses HashTransformation
member functions.
Pipelines
AutoSeededRandomPool prng; SecByteBlock key(16); prng.GenerateBlock(key, key.size()); string plain = "HMAC Test"; string mac, encoded; /*********************************\ \*********************************/ // Pretty print key encoded.clear(); StringSource ss1(key, key.size(), true, new HexEncoder( new StringSink(encoded) ) // HexEncoder ); // StringSource cout << "key: " << encoded << endl; cout << "plain text: " << plain << endl; /*********************************\ \*********************************/ try { HMAC< SHA256 > hmac(key, key.size()); StringSource ss2(plain, true, new HashFilter(hmac, new StringSink(mac) ) // HashFilter ); // StringSource } catch(const CryptoPP::Exception& e) { cerr << e.what() << endl; exit(1); } /*********************************\ \*********************************/ // Pretty print encoded.clear(); StringSource ss3(mac, true, new HexEncoder( new StringSink(encoded) ) // HexEncoder ); // StringSource cout << "hmac: " << encoded << endl;
A typical output is shown below. Note that each run will produce different results because the key is randomly generated.
$ ./Driver.exe key: 11A47EC4465DD95FCD393075E7D3C4EB plain text: HMAC Test hmac: 24DA0BDE78E7E277B42188165595CCEB0DDF303B9EF93534B04C6433DD57EF78
To verify a HMAC on a message, use a HashVerificationFilter.
try { HMAC< SHA256 > hmac(key, key.size()); const int flags = HashVerificationFilter::THROW_EXCEPTION | HashVerificationFilter::HASH_AT_END; StringSource(plain + mac, true, new HashVerificationFilter(hmac, NULL, flags) ); // StringSource cout << "Verified message" << endl; } catch(const CryptoPP::Exception& e) { cerr << e.what() << endl; ... }
We can tamper with a message as follows, which will cause the HashVerificationFilter
to throw the exception, HashVerificationFilter: message hash or MAC not valid:
HMAC< SHA256 > hmac(key, key.size()); // Tamper with message plain[0] ^= 0x01; // Tamper with MAC mac[0] ^= 0x01; StringSource(plain + mac, true, new HashVerificationFilter(hmac, NULL, THROW_EXCEPTION | HASH_AT_END) ); // StringSource
Switching to another hash, such as Whirlpool, is a simple as the following:
HMAC< Whirlpool > hmac(key, key.size()); StringSource(plain, true, new HashFilter(hmac, new StringSink(mac) ) // HashFilter ); // StringSource
HashTransformation
Below is an example of using HashTransformation
member functions to calculate a HMAC. Internally, pipelines do this for you.
#include "cryptlib.h" #include "files.h" #include "hex.h" #include "sha.h" #include "hmac.h" using namespace CryptoPP; #include <string> #include <iostream> int main(int argc, char* argv[]) { const byte m[] = { 0x5,0x8,0xC,0xE,0x1,0xE,0x6,0x0,0x1,0x1, 0x1,0x1,0x1,0x1,0x1,0x1,0x6,0x4,0x6,0x1, 0x7,0x4,0x6,0x1,0x0,0x0,0x0,0x0 }; const byte k[] = { 0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1, 0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1, 0x1,0x1 }; HexEncoder hex(new FileSink(std::cout)); HMAC<SHA1> hmac(k, sizeof(k)); hmac.Update(m, sizeof(m)); byte d[HMAC<SHA1>::DIGESTSIZE]; hmac.Final(d); std::cout << "Message: "; hex.Put(m, sizeof(m)); hex.MessageEnd(); std::cout << std::endl; std::cout << "Digest: "; hex.Put(d, sizeof(d)); hex.MessageEnd(); std::cout << std::endl; return 0; }
The program produces the expected output:
$ ./test.exe Message: 05080C0E010E06000101010101010101060406010704060100000000 Digest: 0EA5E034142BDECC5D3AEC9DE727EE836BF95E1D
Downloads
HMAC-SHA-Filter.zip - Demonstrates a SHA256 based HMAC with filters