import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import static java.nio.charset.StandardCharsets.UTF_8;
public class HmacUtils {
String generateHmac256(String message, byte[] key) throws InvalidKeyException, NoSuchAlgorithmException {
byte[] bytes = hmac("HmacSHA256", key, message.getBytes());
return bytesToHex(bytes); (1)
}
byte[] hmac(String algorithm, byte[] key, byte[] message) throws NoSuchAlgorithmException, InvalidKeyException {
Mac mac = Mac.getInstance(algorithm);
mac.init(new SecretKeySpec(key, algorithm));
return mac.doFinal(message);
}
String bytesToHex(byte[] bytes) { (2)
final char[] hexArray = "0123456789abcdef".toCharArray();
char[] hexChars = new char[bytes.length * 2];
for (int j = 0, v; j < bytes.length; j++) {
v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException {
String valueToDigest = "The quick brown fox jumps over the lazy dog";
byte[] key = "secret".getBytes();
HmacUtils hm = new HmacUtils();
String messageDigest = hm.generateHmac256(valueToDigest, key);
System.out.println(messageDigest);
}
}
HmacSHA256 Signature in Java
Upasana | July 25, 2020 | 4 min read | 952 views
In this tutorial we will learn how to generate Hmac256 signature in Java using standard library, Google Guava and Apache commons codec library.
MAC is a Message Authentication Code algorithm, which provides a way to check integrity of information transmitted over or stored in an unreliable medium. Typically, message authentication codes are used between two parties that share a secret key in order to validate information transmitted between these parties.
A MAC mechanism that is based on cryptographic hash functions is referred to as HMAC. HMAC can be used with any cryptographic hash function, e.g., SHA256 or SHA384, in combination with a secret shared key. HMAC is specified in RFC 2104.
Most commonly used HMAC implementations are:
-
HmacMD5
-
HmacSHA1
-
HmacSHA256
Now we will create HmacSHA256 signature using 3 different libraries - Java Standard Library, Google Guava and Apache Commons Codec.
1. Using JDK Standard Library
Java/Android has everything in cryptography libraries that is required to generate a Hmac256.
1 | Default return type for Mac function is byte array, so we need to convert it to Hex format. |
2 | Our custom method to convert a byte array to hex, optionally we can use Apache Commons Codec’s Hex utility to convert byte array to hex in single line. |
Converting byte[] to hex
There are so many libraries in Java ecosystem that can convert a byte array to hex encoded string:
a) Apache Commons Codec
You can use org.apache.commons.codec.binary.Hex
class to convert given byte array to Hex encoded string using single line code:
import org.apache.commons.codec.binary.Hex;
...
String hexHmac = Hex.encodeHexString(bytes);
b) Spring Security
If you are using Spring Security in your project, you can use org.springframework.security.crypto.codec.Hex
utility to encode and decode byte array into string and vice versa.
import org.springframework.security.crypto.codec.Hex;
...
String hexValue = new String(Hex.encode(bytes));
c) Google Guava
Google Guava provides BaseEncoding
for handlign encoding and decoding to Base16 format.
import com.google.common.io.BaseEncoding;
...
String hexValue = BaseEncoding.base16().lowerCase().encode(bytes); (1)
1 | Default is Upper case hex caharacters. |
d) Bouncy Castle
If you are already using Bouncy Castle security framework, then you can use this Hex util:
import org.bouncycastle.util.encoders.Hex;
...
String hexValue = Hex.toHexString(bytes);
You can also follow this stackoverflow discussion.
2. Using Google Guava
Google Guava library provides static hashing related utilities in class com.google.common.hash.Hashing
.
dependencies {
// https://mvnrepository.com/artifact/com.google.guava/guava
compile group: 'com.google.guava', name: 'guava', version: '29.0-jre'
}
import com.google.common.hash.Hashing;
public class HMacTest {
public void hmac256() {
String valueToDigest = "The quick brown fox jumps over the lazy dog";
byte[] key = "secret".getBytes();
String gHmac = Hashing.hmacSha256(key)
.newHasher() (1)
.putString(valueToDigest, UTF_8)
.hash()
.toString(); (2)
System.out.println(gHmac);
}
}
1 | A hasher can be used only once and must be created for next Hmac256 calculation. |
2 | This will convert the byte array to hex encoded string |
54cd5b827c0ec938fa072a29b177469c843317b095591dc846767aa338bac600
3. Apache Commons Codec
Apache Commons Codec provides a utility class for Hmac operations.
org.apache.commons.codec.digest.HmacUtils
dependencies {
// https://mvnrepository.com/artifact/commons-codec/commons-codec
compile group: 'commons-codec', name: 'commons-codec', version: '1.14'
}
import org.apache.commons.codec.digest.HmacAlgorithms;
import org.apache.commons.codec.digest.HmacUtils;
public class HMacTest {
public void hmac256() {
String valueToDigest = "The quick brown fox jumps over the lazy dog";
byte[] key = "secret".getBytes();
HmacUtils hm256 = new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key);
//hm256 object can be used again and again
String hmac = hm256.hmacHex(valueToDigest);
System.out.println(hmac);
}
}
54cd5b827c0ec938fa072a29b177469c843317b095591dc846767aa338bac600
Similarly, you can compute Hmac256 for the entire file.
String hexPom = hm256.hmacHex(new File("pom.xml"));
Top articles in this category:
- Allow insecure SSL in Java 11 HttpClient
- Secure OTP generation in Java
- What is left shift right shift and unsigned rght shift operator in Java
- Discuss internals of a ConcurrentHashmap (CHM) in Java
- Is Java Pure Object Oriented Language?
- Design an Immutable class that has an java.util.Date member
- What will happen if we don't synchronize getters/accessors of a shared mutable object in multi-threaded applications