โ† Back to Blog

How to Generate HMAC

2026-04-14 ยท 5 min read

What Is HMAC?

HMAC (Hash-based Message Authentication Code) is an authentication method that combines cryptographic hash functions with a secret key. Unlike plain hashing, HMAC requires a shared secret key โ€” only those who know the key can generate or verify the HMAC. HMAC simultaneously provides two guarantees: message integrity (data hasn't been modified) and message authenticity (data genuinely came from the key holder).

/* HMAC formula */
HMAC(key, message) = Hash(
  (key XOR opad) ||
  Hash((key XOR ipad) || message)
)

/* Where:
   opad = 0x5c repeated
   ipad = 0x36 repeated
   || = concatenation */

Key Difference Between HMAC and Plain Hash

Plain hashing (like SHA256) is publicly computable โ€” anyone can calculate the hash of any data. This means an attacker can modify data and recalculate the hash to forge an integrity proof. HMAC solves this: without the key, a correct HMAC cannot be computed. Even if an attacker knows the data and the HMAC algorithm, they cannot forge the HMAC without the key.

Implementing HMAC-SHA256 in Various Languages

// JavaScript (Node.js)
const crypto = require('crypto');

function generateHmac(secret, message) {
  return crypto
    .createHmac('sha256', secret)
    .update(message)
    .digest('hex');
}

const signature = generateHmac('my-secret-key', 'Hello World');
// Output: 'f59c9c0b1234567...' (64-char hex)

// Verify
function verifyHmac(secret, message, receivedHmac) {
  const expected = generateHmac(secret, message);
  // Use timingSafeEqual to prevent timing attacks!
  return crypto.timingSafeEqual(
    Buffer.from(expected, 'hex'),
    Buffer.from(receivedHmac, 'hex')
  );
}
# Python
import hmac, hashlib

def generate_hmac(secret: str, message: str) -> str:
    key = secret.encode('utf-8')
    msg = message.encode('utf-8')
    return hmac.new(key, msg, hashlib.sha256).hexdigest()

def verify_hmac(secret: str, message: str, received: str) -> bool:
    expected = generate_hmac(secret, message)
    # Use compare_digest to prevent timing attacks!
    return hmac.compare_digest(expected, received)

signature = generate_hmac('my-secret-key', 'Hello World')

HMAC in API Request Signing

API signing is one of the most common HMAC use cases. Here's a typical HMAC-based API signing workflow (simplified reference to AWS Signature Version 4):

// API signing example
function signRequest(secretKey, method, path, body, timestamp) {
  // 1. Create string to sign
  const bodyHash = crypto.createHash('sha256')
    .update(body).digest('hex');

  const stringToSign = [
    method.toUpperCase(),
    path,
    timestamp,
    bodyHash
  ].join('\n');

  // 2. Generate HMAC signature
  const signature = crypto
    .createHmac('sha256', secretKey)
    .update(stringToSign)
    .digest('hex');

  return signature;
}

// Server verification
const expectedSig = signRequest(serverSecret, method, path, body, timestamp);
if (crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expectedSig))) {
  // Request is authentic
}

HMAC-SHA256 in JWT (HS256)

JWT's HS256 algorithm is HMAC-SHA256. JWT's structure is header.payload.signature, where signature is the Base64URL-encoded HMAC-SHA256 result of header.payload using the secret key. The server holding the key can verify whether the JWT has been tampered with; clients cannot forge valid JWTs (unless they know the key).

// JWT HS256 signature (simplified)
const header  = Base64URL(JSON.stringify({ alg: "HS256", typ: "JWT" }));
const payload = Base64URL(JSON.stringify({ sub: "user123", exp: 1720000000 }));
const sigInput = `${header}.${payload}`;

const signature = Base64URL(
  crypto.createHmac('sha256', jwtSecret).update(sigInput).digest()
);

const jwt = `${header}.${payload}.${signature}`;

HMAC vs Digital Signatures (RSA/ECDSA)

HMAC and digital signatures (like RSA-SHA256, ECDSA) both ensure message authenticity, but with a key difference: HMAC uses a symmetric key (same key for generating and verifying, shared by both parties) โ€” suitable only for mutually trusted scenarios. Digital signatures use asymmetric keys (private key signs, public key verifies) โ€” anyone with the public key can verify the signature, but only the private key holder can generate it โ€” suitable for publicly verifiable scenarios (like software package signing, certificates).

HMAC Security Best Practices

Try the free tool now

Use Free Tool โ†’