Skip to content

HMAC-MD5 (HMAC with MD5)

HMAC-MD5 is a message authentication code built from HMAC (Keyed-Hash Message Authentication Code) using MD5. It is not encryption; it produces a tag from a key and message to detect tampering. Treat the spelling variant “HMCA-MD5” as referring to HMAC-MD5.

MD5 has a 64-byte block size.

  1. Normalize the key
    • If the key is longer than 64 bytes: K = MD5(K)
    • If the key is shorter than 64 bytes: K = K || 0x00... (zero-pad to 64 bytes)
  2. Prepare 64 bytes of ipad = 0x36 and 64 bytes of opad = 0x5c
  3. Inner hash: MD5((K ⊕ ipad) || message)
  4. Outer hash: MD5((K ⊕ opad) || inner)

The formula is: HMAC(K, m) = MD5((K ⊕ opad) || MD5((K ⊕ ipad) || m))

  • NTLMv2 Hash: HMAC-MD5(key=NTHash, msg=Uppercase(Username) + Domain) Username / Domain are UTF-16LE.
  • NTProofStr: HMAC-MD5(key=NTLMv2 Hash, msg=ServerChallenge + Blob)
  • NTLMv2 Response: NTProofStr || Blob
  • HMAC does not rely on MD5’s collision resistance, so it is more secure than plain MD5.
  • Even so, HMAC-MD5 is for legacy use; choose a stronger construction such as HMAC-SHA-256 for new designs.
[dependencies]
hmac = "0.12"
md-5 = "0.10"
hex = "0.4"
use hmac::{Hmac, Mac};
use md5::Md5;
type HmacMd5 = Hmac<Md5>;
pub fn hmac_md5(key: &[u8], message: &[u8]) -> [u8; 16] {
let mut mac = HmacMd5::new_from_slice(key).expect("HMAC accepts any key size");
mac.update(message);
let result = mac.finalize().into_bytes();
let mut out = [0u8; 16];
out.copy_from_slice(&result);
out
}
fn main() {
let tag = hmac_md5(b"key", b"message");
println!("HMAC-MD5: {}", hex::encode(tag));
}