HMAC: Keyed-Hashing for Message Authentication
About Me
{
"employer": "@razorpay",
"work": [
"security",
"devops",
"architecture"
],
"contact": "me@captnemo.in",
"geek": [
"crypto",
"ux",
"speedcubes"
],
"twitter": "@captn3m0"
}
Format
- What problem does it solve?
- How does it solve it?
- Cover the RFC
- When to use it?
Pre-requisite:
- Some idea of Hashing
- Bits and Bytes
MAC
Message Authentication Code
M
M
M
M
M
M
M
K
M
K
M
Merkle–Damgård construction
Merkle–Damgård construction
M
K
M
K
M
M
K
M
K
M
16
100
28
M
K
M
K
M
16
100
28
10
HMAC Goals
- Be Fast
- Use existing hash functions
- Simple Key handling
- Easy to use
Terms
-
H = Hash Function
-
K = Authentication Key
-
B = Byte-Length (H)
-
L = Byte-Length (H(x))
Key Shortening
if(K > L)
{
K = H(key)
}
if (K < L)
{
K = RPAD(K, 0x00)
}
Padding
ipad = 0x36 * B
opad = 0x5C * B
// repeated B times
RFC 2104
H(K⊕opad, H(K⊕ipad, text))
H(K⊕opad, H(K⊕ipad, text))
/* if key is longer than 64 bytes reset it to key=MD5(key) */
if (key_len > 64) {
// key = MD5(key)
MD5_CTX tctx;
MD5Init(&tctx);
MD5Update(&tctx, key, key_len);
MD5Final(tk, &tctx);
key = tk;
key_len = 16;
}
H(K⊕opad, H(K⊕ipad, text))
/*
* the HMAC_MD5 transform looks like:
*
* MD5(K XOR opad, MD5(K XOR ipad, text))
*
* where K is an n byte key
* ipad is the byte 0x36 repeated 64 times
* opad is the byte 0x5c repeated 64 times
* and text is the data being protected
*/
/* start out by storing key in pads */
bzero( k_ipad, sizeof k_ipad);
bzero( k_opad, sizeof k_opad);
bcopy( key, k_ipad, key_len);
bcopy( key, k_opad, key_len);
H(K⊕opad, H(K⊕ipad, text))
/*
* the HMAC_MD5 transform looks like:
*
* MD5(K XOR opad, MD5(K XOR ipad, text))
*
* where K is an n byte key
* ipad is the byte 0x36 repeated 64 times
* opad is the byte 0x5c repeated 64 times
* and text is the data being protected
*/
/* start out by storing key in pads */
bzero( k_ipad, sizeof k_ipad);
bzero( k_opad, sizeof k_opad);
bcopy( key, k_ipad, key_len);
bcopy( key, k_opad, key_len);
/* XOR key with ipad and opad values */
for (i=0; i<64; i++) {
k_ipad[i] ^= 0x36;
k_opad[i] ^= 0x5c;
}
H(K⊕opad, H(K⊕ipad, text))
/* XOR key with ipad and opad values */
for (i=0; i<64; i++) {
k_ipad[i] ^= 0x36;
k_opad[i] ^= 0x5c;
}
/*
* perform inner MD5
*/
MD5Init(&context); /* init context for 1st
* pass */
MD5Update(&context, k_ipad, 64) /* start with inner pad */
MD5Update(&context, text, text_len); /* then text of datagram */
MD5Final(digest, &context); /* finish up 1st pass */
H(K⊕opad, H(K⊕ipad, text))
/* XOR key with ipad and opad values */
for (i=0; i<64; i++) {
k_ipad[i] ^= 0x36;
k_opad[i] ^= 0x5c;
}
/*
* perform inner MD5
*/
MD5Init(&context); /* init context for 1st
* pass */
MD5Update(&context, k_ipad, 64) /* start with inner pad */
MD5Update(&context, text, text_len); /* then text of datagram */
MD5Final(digest, &context); /* finish up 1st pass */
/*
* perform outer MD5
*/
MD5Init(&context); /* init context for 2nd
* pass */
MD5Update(&context, k_opad, 64); /* start with outer pad */
MD5Update(&context, digest, 16); /* then results of 1st
* hash */
MD5Final(digest, &context); /* finish up 2nd pass */
H(K⊕opad, H(K⊕ipad, text))
/* XOR key with ipad and opad values */
for (i=0; i<64; i++) {
k_ipad[i] ^= 0x36;
k_opad[i] ^= 0x5c;
}
/*
* perform inner MD5
*/
MD5Init(&context); /* init context for 1st
* pass */
MD5Update(&context, k_ipad, 64) /* start with inner pad */
MD5Update(&context, text, text_len); /* then text of datagram */
MD5Final(digest, &context); /* finish up 1st pass */
/*
* perform outer MD5
*/
MD5Init(&context); /* init context for 2nd
* pass */
MD5Update(&context, k_opad, 64); /* start with outer pad */
MD5Update(&context, digest, 16); /* then results of 1st
* hash */
MD5Final(digest, &context); /* finish up 2nd pass */
H(K⊕opad, H(K⊕ipad, text))
/*
* Function: hmac_md5
*/
void
hmac_md5(text, text_len, key, key_len, digest)
unsigned char* text; /* pointer to data stream */
int text_len; /* length of data stream */
unsigned char* key; /* pointer to authentication key */
int key_len; /* length of authentication key */
caddr_t digest; /* caller digest to be filled in */
{
MD5_CTX context;
//...
MD5Final(digest, &context);
}
RFC 2104
- Truncated HMAC
- Test Vectors for HMAC-MD5
- Security Guarantees
- RFC 6151- Updated Security Considerations for MD5 and HMAC-MD5
- RFC 4635 - HMAC SHA TSIG Algorithm Identifiers
- RFC 4868 - Using HMAC-SHA-256, HMAC-SHA-384, and HMAC-SHA-512 with IPsec
- RFC 2202 - Test Cases for HMAC-MD5 and HMAC-SHA-1
- RFC 4231 - Identifiers and Test Vectors for HMAC-SHA-224, HMAC-SHA-256, HMAC-SHA-384, and HMAC-SHA-512
key = "Jefe"
data = "what do ya want for nothing?"
data_len = 28 bytes
digest = 0x750c783e6ab0b503eaa86e310a5db738
key_len = 4
HMAC - RFC2104
By Nemo
HMAC - RFC2104
Slides for a talk on HMAC (RFC 2104) at the RFCs we Love meetup
- 3,742