BiTree
  • Search For Lessons
  • Curriculum
  • Pricing
  • For Educators
  • Become a Tutor
  • About
  • Contact
Log InGet Started

Questions, concerns, bug reports, or suggestions? We read every message, write to us at [email protected].

More ways to reach us →
BiTree

Live coding lessons for aspiring developers and security professionals.

[email protected]

(201) 785-7951

Mon–Fri, 9 AM–5 PM EST

Learn

  • Search For Lessons
  • Curriculum
  • Pricing

Company

  • About
  • For Educators & Schools
  • Become a Tutor
  • Contact Us

Legal

  • Terms of Service
  • Privacy Policy
© 2026 BiTree. All rights reserved.
Curriculum/Cybersecurity/Cryptography/Hash Functions and HMAC
40 minIntermediate

Hash Functions and HMAC

After this lesson, you will be able to: Explain cryptographic hash functions, collision and pre-image resistance, length-extension attacks, and why HMAC is the right way to authenticate with a secret.

Hash functions turn any input into a fixed-size fingerprint and are the workhorse of integrity, passwords, and signatures. This lesson covers SHA-256 and SHA-3, the security properties that make a hash cryptographic, length-extension attacks, and why you use HMAC instead of just hashing data with a secret.

Prerequisites:What Cryptography Protects (intro)

What a cryptographic hash is

A hash function maps any input to a fixed-size output (SHA-256 produces 256 bits) deterministically and one-way: you cannot reverse the output back to the input. The same input always gives the same hash; a tiny change gives a completely different hash. SHA-256 (from the SHA-2 family) is the current workhorse; SHA-3 is a newer, differently-constructed standard. MD5 and SHA-1 are broken and must not be used for security.

The security properties

Three properties make a hash cryptographic. Pre-image resistance: given a hash, you cannot find an input that produces it. Second pre-image resistance: given an input, you cannot find a different input with the same hash. Collision resistance: you cannot find any two inputs with the same hash. MD5 and SHA-1 fell to collision attacks (researchers produced two different files with the same hash), which is why they are retired for signatures and certificates.

Length-extension attacks and why HMAC exists

A natural but wrong way to authenticate a message with a secret is hash(secret + message). Many hash constructions (including SHA-256's Merkle-Damgard design) are vulnerable to length-extension: an attacker who knows the hash and message length can append data and compute a valid hash for the extended message without knowing the secret. HMAC (Hash-based Message Authentication Code) is the correct construction: it nests the key into the hashing in a way that resists length extension. Always use HMAC to authenticate with a shared secret, never a naive concatenation.

HMAC done right

Authenticate a message with a shared secret using HMAC-SHA256.

python
import crypto from "crypto";
const secret = process.env.HMAC_SECRET!;
const message = "transfer:100:to:bob";
// CORRECT: HMAC resists length-extension
const mac = crypto.createHmac("sha256", secret).update(message).digest("hex");
// Verify with a constant-time comparison to avoid timing attacks
function verify(message: string, tag: string) {
const expected = crypto.createHmac("sha256", secret).update(message).digest();
return crypto.timingSafeEqual(Buffer.from(tag, "hex"), expected);
}

💡 Hashing for passwords is different

Cryptographic hashes like SHA-256 are designed to be fast, which is exactly wrong for passwords. Password hashing needs a slow, salted, memory-hard function (bcrypt, scrypt, or Argon2id) so attackers cannot try billions of guesses per second. Never store passwords with plain SHA-256. This is also covered in the Web Dev secure-auth lesson and the Application Security cryptographic-failures lesson.

Quick Check

Why use HMAC instead of hash(secret + message) to authenticate a message?

Pick one.

Common mistakes only experienced engineers catch

Using MD5 or SHA-1 for anything security-relevant. Using hash(secret + message) instead of HMAC. Using a fast hash for passwords. Comparing MACs with == (timing attack); use a constant-time compare. Treating a hash as encryption (it is one-way, not reversible). Forgetting that a hash alone provides integrity only if the hash itself is protected (otherwise an attacker changes both).

Sign in and purchase access to unlock this lesson.

Sign in to purchase
←Asymmetric Encryption: RSA and ECC
Back to Cryptography
Key Exchange and Digital Signatures→