How to Generate a HMAC Signature in Java
Hashed Based Message Authentication Code (HMAC) is a cryptography procedure that generates a code from a given data or String using a secret-key and a hash function like SHA256. The resulting code is called a Message Authentication Code (MAC) or signature.
HMAC does not involve encryption/decryption, as long as the same secret-key is used to sign the same message, the generated signature will always be the same.
This means we can validate the authenticity of HTTP requests, WebSocket messages, events etc. by counter-signing the incoming data and comparing the signatures.
2. Generating a Signature
We only need two components to generate an HMAC signature: a secret-key and the data to hash.
The secret-key can be a simple String of alphanumeric characters. The longer the number of characters, the better. The APIs we will use are already part of the JDK, so we don’t need to install additional libraries or dependencies.
We converted the final signature bytes to base64 format for easy processing across different systems.
message can be JSON, XML or a simple String data; it really doesn’t matter.
Let’s see a typical usage of the function above in a unit test.
3. Security Applications
3.1 Request Forgery Protection
By nature of the HMAC mechanism we can use it to protect against request forgery. How? The request Sender and Receiver would have shared the secret-key via a secure channel in a one-time process, and subsequent communications will follow this pattern:
- The Sender intend to send a
- The Sender will generate a HMAC signature of the message using the shared secret-key
- The Sender will send both the resulting signature and the plain
- The Receiver, upon receiving the message, will also generate its own signature for the received plain
Hello Worldmessage with its own copy of the shared secret-key
- The Receiver will now compare the received signature with its own generated signature
- If the signature is exactly the same, then the Receiver will process the message. Otherwise, will reject the message
If at any point the message is modified by bad actors between the Sender and the Receiver, the message will have different signatures and become invalid.
3.2 Replay Attack Protection
We can enhance this protocol by adding one more ingredient - the current unix
Both the Sender and the Receiver will agree on a duration for which a request can be considered valid.
For example, any request older than 10 seconds will be deemed stale and won’t be processed.
- The Sender will sign
Hello World+ current unix
timestampin milliseconds with the shared secret-key
- The Sender will send
signatureto the Receiver
- The Receiver will compute the time difference between the received
timestampand its own current unix
- If the time difference is more than the agreed upon limit, the request will be rejected as stale
- The Receiver, upon validating the
timestamp, will then proceed to sign the message
Hello World+ received
timestampand compare the
signatureas usual to determine the message authenticity
This protocol will prevent a middleman from replaying old requests or modifying the requests in-flight. These techniques are usually used to secure API endpoints like web callbacks or internal APIs.
HMAC has multiple practical applications, simple to use and highly compatible across different programming languages. These attributes make it suitable for system security and more.
SHA256, it is also possible to use
SHA3-512 etc. The strength of HMAC is related to the
length of the secret-key and the hash function used. It is advisable to use longer secret-key and secure hash functions like
The complete source code is on GitHub.