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 hexVerifying 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
- Cryptographic Hashing with MessageDigest
- AES Symmetric Encryption
- HMAC-SHA256 for Message Integrity
- JWT: Structure, Creation, and Verification