0Pricing
Java Academy · Lesson

HMAC-SHA256 for Message Integrity

Create and verify HMAC-SHA256 signatures to ensure API payload integrity.

HMAC-SHA256 for Message Integrity is a free Java Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Java Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

What Is HMAC?

HMAC (Hash-based Message Authentication Code) combines a cryptographic hash function with a secret key to produce a MAC. It proves both that the data has not been tampered with AND that the sender knows the secret key.

HMAC vs Plain Hash

A plain SHA-256 hash can be computed by anyone. HMAC requires the secret key — only parties that know the key can create or verify a valid HMAC. Plain hashes provide integrity but not authentication.

Computing HMAC-SHA256 in Java

Use Mac.getInstance("HmacSHA256"), initialize with a SecretKeySpec, and call doFinal(data).

byte[] keyBytes = "my-secret-key".getBytes(StandardCharsets.UTF_8);
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "HmacSHA256");
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(keySpec);
byte[] hmac = mac.doFinal("payload data".getBytes(StandardCharsets.UTF_8));
String hmacHex = HexFormat.of().formatHex(hmac);
System.out.println(hmacHex); // 64-char hex

Verifying an HMAC

Recompute the HMAC on the received data with the shared key. Use constant-time comparison (MessageDigest.isEqual) to prevent timing attacks.

byte[] expectedHmac = computeHmac(key, receivedPayload);
byte[] actualHmac    = HexFormat.of().parseHex(receivedHmacHex);
boolean valid = MessageDigest.isEqual(expectedHmac, actualHmac);
if (!valid) throw new SecurityException("HMAC verification failed — data tampered!");

Generating a Secure Key

HMAC keys should be random bytes, not passwords. Use KeyGenerator or SecureRandom to generate a 256-bit key.

KeyGenerator kg = KeyGenerator.getInstance("HmacSHA256");
kg.init(256);
SecretKey key = kg.generateKey();
String b64Key = Base64.getEncoder().encodeToString(key.getEncoded());

HMAC for API Request Signing

Compute HMAC over the HTTP method, path, timestamp, and body. Include the HMAC in the X-Signature header. The server recomputes and compares to verify the request has not been tampered with.

String payload = method + "\n" + path + "\n" + timestamp + "\n" + body;
byte[] hmac = computeHmac(apiSecretKey, payload);
request.header("X-Signature", "hmac-sha256=" + HexFormat.of().formatHex(hmac));
request.header("X-Timestamp", timestamp);

Replay Attack Prevention

An attacker can replay a valid signed request. Include a timestamp in the signed payload and reject requests older than a few minutes.

long timestamp = Long.parseLong(request.getHeader("X-Timestamp"));
if (Math.abs(System.currentTimeMillis() / 1000 - timestamp) > 300) {
    throw new SecurityException("Request too old — possible replay attack");
}

HMAC for Webhook Verification

GitHub, Stripe, and many services sign webhooks with HMAC. Verify the X-Hub-Signature-256 header to ensure the webhook came from the service and was not modified.

// GitHub webhook verification:
String received = request.getHeader("X-Hub-Signature-256").replace("sha256=","");
byte[] expected = computeHmac(webhookSecret, request.getBody());
boolean valid = MessageDigest.isEqual(expected, HexFormat.of().parseHex(received));

HMAC in JWT

HS256 (HMAC-SHA256) is a common JWT signature algorithm. The header+payload is signed with a shared secret. Both issuer and verifier must know the secret — suitable for microservices on the same trust boundary.

HMAC Key Rotation

Rotate HMAC keys periodically. During rotation, accept both old and new key HMACs for a short overlap period, then retire the old key.

When to Use HMAC vs Digital Signatures

HMAC: symmetric — both sides share the secret, fast, for internal APIs and webhook verification. Digital signatures (RSA/ECDSA): asymmetric — only the signer has the private key, verifiable by anyone with the public key, for JWTs in distributed systems.

Quick Check

Why must HMAC comparison use constant-time equality?

Recap

HMAC-SHA256 provides authenticated integrity — proves data origin and non-tampering. Use Mac.getInstance("HmacSHA256"). Always use constant-time comparison. Include timestamps to prevent replay attacks. Use for API signing, webhook verification, and HS256 JWTs.

Frequently asked questions

Is the “HMAC-SHA256 for Message Integrity” lesson free?

Yes — the full text of “HMAC-SHA256 for Message Integrity” is free to read here on the web, and the Java Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Java Academy course, upgrade to CoddyKit PRO.

What will I learn in “HMAC-SHA256 for Message Integrity”?

Create and verify HMAC-SHA256 signatures to ensure API payload integrity. You practise Java Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Java Academy?

No prior experience is required. Java Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “HMAC-SHA256 for Message Integrity” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Java Academy lesson?

Yes. Every Java Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Cryptographic Hashing with MessageDigest
  2. AES Symmetric Encryption
  3. HMAC-SHA256 for Message Integrity
  4. JWT: Structure, Creation, and Verification
← Back to Java Academy