TomRed.net

  • Increase font size
  • Default font size
  • Decrease font size
Subscribe Bookmark and Share
Home Tutorials JavaScript Java Generate HMac - MD5 - SHA1

Java Generate HMac - MD5 - SHA1

User Rating: / 1
PoorBest 

In my most recent work I have been tasked with managing payment gateways.  I have noticed that in each case we require a HMAC (Hash-based Message Authentication Code).  I also noted that in most cases I was given a string key.  I found it initially difficult to get these elements to work and so I thought that I would outline how to do it here.  This tutorial use JCE (Java Cryptography Extension).

What is HMAC?

A HMAC is just a code used to verify the messages Authenticity and its Data Integrity.  Imagine someone was to intercept a HTTP Post and alter the values.  This could be used to cheat in a game or to alter the amount of money being paid (or other nefarious schemes).  On the server-side we don't have to accept that the submitted information is valid and authentic.  We take the information before it is submitted and process it, creating a Message Authentication Code.  This code uses a key that is unique to the end user and known to the receiver.  If the message is altered after it has been submitted, then the MAC will not match the value generated on the receivers side.  The use of the unique key demonstrates Authenticity, the MAC itself signifies the Data Integrity.  If the MACs do not match then either the data has been tampered with or it is not from the user it says its from. 

How to Generate HMAC using Java.

I have outlined the code below.  In its present form it is simply a util class.  You will note that I have two methods.  The first generates the HMAC and the second returns the HEX representation. 

	package net.tomred.utils;
		import java.security.Key; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec;
		public class SecurityHelper{

		public String getHmacMD5(String privateKey, String input, String algorithm) throws Exception{
			byte[] keyBytes = privateKey.getBytes();
			Key key = new SecretKeySpec(keyBytes, 0, keyBytes.length, algorithm); 
			Mac mac = Mac.getInstance(algorithm);
			mac.init(key); 
			return byteArrayToHex(mac.doFinal(input.getBytes()));
		}

		protected String byteArrayToHex(byte [] a) {
			int hn, ln, cx;
			String hexDigitChars = "0123456789abcdef";
			StringBuffer buf = new StringBuffer(a.length * 2);
			for(cx = 0; cx < a.length; cx++) {
				hn = ((int)(a[cx]) & 0x00ff) / 16;
				ln = ((int)(a[cx]) & 0x000f);
				buf.append(hexDigitChars.charAt(hn));
				buf.append(hexDigitChars.charAt(ln));
			}
			return buf.toString();
		}
	}

Now let me explain what I have done here.  Skipping the Java package, import and class definitions;  I declare a method which takes three strings privateKey, input and algorithm.  The private key is a pre-shared key that is unique to you (usually) in this example I am assuming that we have a key saved as a string somewhere that we are passing to the method.  I will cover generating you own key later on.  The string input in the text that you want to be HMAC-ed.  Finally the algorithm is the cryptographic hash function you want to use, these include MD5, SHA1 & HAVAL etc. 

To start we convert our privateKey string into a byte array using getBytes()We then instanciate an instance of SecretKeySpec passing it the following parameters:

  • your privateKey byte array
  • value of the starting position of your key (offset)
  • the length of the key,
  • the algorithm to use

the key will be created using the bytes between keyBytes[offset] and keyBytes[offset+length-1] using the algorithm passed.  The resulting output of this is a java.security Key object.  Now we create the javax.crypto Mac object and pass it the algorithm to use.  We initialise the Mac object with the java.security Key and we are ready to MAC attack some strings.

To do the HMAC we simply use the mac.doFinal() method and pass it a byte array representation of the input parameter (input.getBytes()).  The mac.doFinal method returns a byte array.  In my example above I have taken this HMAC byte array and converted it to a HEX string.  I have done this as it is a human readable version of the HMAC (and is in my experience the most common expectation of the use a HMAC).  If you don't need this then you can simply use the byte array generated by the doFinal method.

How to generate our own key.

It might be the case that you wish to generate your own key, this can easily achieve this using the following method.  The only warning is to make sure that you record this key otherwise you will not be able to validate the HMAC.

	KeyGenerator keyGen = KeyGenerator.getInstance(algorithm); // you can use "HmacMD5","HmacSHA1" etc
	SecretKey secretKey = keyGen.generateKey();

You can then use this key in the same way as in the example above.

Added Security

To increase security you can generate your key from a key string but only use a portion of the string in which case if you key is made public the exact portion of it will still not be know.  Also the longer the key the better as it gives you more portions to use.  You can use different parts of the string to generate the key by using the key offset and len parameters.

I have also seen a number of implementation that BASE64 encode the output instead of using  HEX.  This can be achieved as follows:

	import sun.misc.BASE64Encoder;
...
return new BASE64Encoder().encode(mac.doFinal(input.getBytes()));