HMAC authenticates bytes using a secret key shared by the signer and verifier.
Java HmacSHA256 verification: reject a changed message
Verify the exact serialized message
The verifier must calculate the MAC over the same byte sequence the signer used. Reformatting a timestamp or changing whitespace before verification changes the message. This fixture generates a process-local key, signs one dispatch record, then shows that a changed record does not match.
The key exists only for this run. Production key creation, storage, access control, rotation, and version tags need a separate design. A digest alone cannot provide this origin check; SHA-256 byte hashing covers the distinction.
Frame multiple fields
Concatenating variable-length fields without boundaries can make different records produce identical MAC input bytes. Field framing gives a small counterexample. Keep the algorithm identifier and key version with stored tags so verification can select the right key after rotation.
Working program
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
public class DispatchRecordMac {
static byte[] tag(SecretKey key, String record) throws Exception {
Mac signer = Mac.getInstance("HmacSHA256");
signer.init(key);
return signer.doFinal(record.getBytes(StandardCharsets.UTF_8));
}
public static void main(String[] args) throws Exception {
KeyGenerator generator = KeyGenerator.getInstance("HmacSHA256");
SecretKey key = generator.generateKey();
byte[] storedTag = tag(key, "dispatch=R-47");
System.out.println("accepted=" + MessageDigest.isEqual(storedTag, tag(key, "dispatch=R-47")));
System.out.println("tampered=" + MessageDigest.isEqual(storedTag, tag(key, "dispatch=R-48")));
}
}Output
accepted=true
tampered=falseCost and ownership
MAC computation processes O(n) message bytes and returns a fixed-size tag; the example allocates text bytes and tag arrays. Verification cost is small compared with key lifecycle risk. Do not log the key or treat a test-generated ephemeral key as persistent configuration.
Common Mistakes
- Do not compare a tag over one serialization with a different serialization.
- Do not hard-code a production HMAC key in source.
- Do not confuse HMAC with encryption; the message remains readable.
Read next
hmac field framing, Java SHA-256: hash declared bytes, not an implicit string encoding, secure random token encoding, Java HTTPS project: a trusted local certificate and a rejected hostname.
Continue with: Java ZIP CRC32: detect corruption without claiming authenticity.
