ColdFusion 10 Beta - Generating Hash-Based Message Authentication Codes With Hmac()

Posted February 27, 2012 at 9:14 AM by Ben Nadel

Tags: ColdFusion

We are entering the age of APIs - Application Programming Interface(s). Many of our applications now interface with 3rd party APIs like Twilio, Twitter, EmailYak, FullContact, Face.com, and Facebook. The list goes on and on. The available functionality is simply mind-blowing; unfortunately, when we interact with 3rd party services, we do open ourselves up to another attack surface. Luckily, we can use shared private keys as a way to create Hash-based Message Authentication Codes - or, HMAC values - in order to authenticate the senders and recipients of messages. This approach used to be a rather trying feature to implement; with ColdFusion 10, however, generating HMAC values is now incredibly simple.

I don't fully understand the mechanics of generating a Hash-based Message Authentication Code. I can tell you that it works by creating a message digest with the aide of a given secure hashing algorithm. EmailYak uses the MD5 hashing algorithm; Pusher uses the Sha-256 hashing algorithm; and Twilio uses the Sha-1 hashing algorithm. In Java (and therefore in ColdFusion), the application of the given hashing algorithm is encapsulated within the classes javax.crypto.spec.SecretKeySpec and javax.crypto.Mac. And still, creating hash-based message authentication codes requires a lot of work.

In ColdFusion 10, we now have the function hmac(). hmac() fully encapsulates the selection and application of the hashing algorithm, the creation of the message digest, and the conversion of the digest into HEX format. In other words, hmac() took a complex algorithm and turned into a single function call.

To see the huge difference this has made, take a look at the following code. In this demo, I'll create an MD5-based message authentication code (HMAC) using both a custom-built, user defined ColdFusion function and the new hmac() function. The difference will become obvious.

  • <cfscript>
  •  
  •  
  • // I take an API key and a content value and generate a hashed-
  • // message authenticate code using MD5 so as to be able to
  • // authenticate that the message is from a trusted source.
  • function md5Digest( content, apiKey ){
  •  
  • // We need to hash the content using the MD5 algorithm. Let's
  • // define a key specification for the HmacMD5 alrorithm using
  • // our API key.
  • var secretKeySpec = createObject( "java", "javax.crypto.spec.SecretKeySpec" ).init(
  • toBinary( toBase64( apiKey ) ),
  • javaCast( "string", "HmacMD5" )
  • );
  •  
  • // Now, let's create our MAC (Message Authentication Code)
  • // generator to hash the actual email post content.
  • var mac = createObject( "java", "javax.crypto.Mac" ).getInstance(
  • javaCast( "string", "HmacMD5" )
  • );
  •  
  • // Initialize the MAC using our secret key.
  • mac.init( secretKeySpec );
  •  
  • // Hash the content of the message - returnes byte array.
  • var hashedBytes = mac.doFinal(
  • toBinary( toBase64( content ) )
  • );
  •  
  • // Now that we have our hashed bytes, we need to encode them
  • // as a Hexadecimal string. Create a buffer to hold the hex
  • // values as we encode each byte.
  • var hexBuffer = [];
  •  
  • // Loop over the bytes to encode them individually as HEX.
  • for (var byte in hashedBytes){
  •  
  • // Get the hex value for this byte. When converting the
  • // byte, only use the right-most 8 bits - the sign of
  • // the byte can create oddities otherwise.
  • var hexValue = formatBaseN( bitAnd( 255, byte ), 16 );
  •  
  • // When appending the HEX value, ensure that the leading
  • // zero has not been trimmed during the conversion.
  • arrayAppend(
  • hexBuffer,
  • right( "0#hexValue#", 2 )
  • );
  •  
  • }
  •  
  • // Flatten and return the Hex buffer.
  • return(
  • ucase( arrayToList( hexBuffer, "" ) )
  • );
  •  
  • }
  •  
  •  
  • // ------------------------------------------------------ //
  • // ------------------------------------------------------ //
  •  
  •  
  • // Set up our security key and our message to authenticate.
  • apiKey = "icanhazsecyouritea";
  • message = "The content to be authenticed using message digest!";
  •  
  •  
  • // Get HMAC (hashed-message authentication code) using the manual
  • // algorithm and hex conversion.
  • writeOutput(
  • md5Digest( message, apiKey )
  • );
  •  
  • writeOutput( "<br />" );
  •  
  • // Use new built-in Hmac() method.
  • writeOutput(
  • hmac( message, apiKey, "HmacMD5" )
  • );
  •  
  •  
  • </cfscript>

As you can see, the 50-line user-defined function is replaced with a single call to hmac(). And, when we run the above code, we can see that the two approaches generate the same hash-based message authentication code (HMAC):

51A2E5E7AA08926C53AAC45356ABA0C9
51A2E5E7AA08926C53AAC45356ABA0C9

The new hmac() function is so much easier!

As dealing with 3rd-party APIs becomes commonplace, message authentication becomes a fact of life. Not only do we have to authenticate where incoming messages came from, 3rd-party APIs are requiring that we authenticate who we are (when we send messages out). Many sites are using hash-based message authentication codes (HMAC) as a way to perform this security check; while this was possible before ColdFusion 10, the new beta makes this security handshake incredibly simple.


You Might Also Be Interested In:



Reader Comments

Mar 13, 2012 at 9:44 AM // reply »
158 Comments

Sixteen days have passed and no one has made your day yet? This is a good post! How can I have been the one to make your day? Seriously?!


Mar 13, 2012 at 10:50 AM // reply »
11,246 Comments

@Randall,

I guess not many people were as excited about the new hmac() method as me :D I appreciate you making my day!


Mar 28, 2012 at 7:23 PM // reply »
6 Comments

This is awesome! CF10 is going to rock


Apr 9, 2012 at 1:42 PM // reply »
46 Comments

I was reading the CF10 docs and for "algorithm" & "Encoding" it doesn't offer a list of allowable options.
http://help.adobe.com/en_US/ColdFusion/10.0/CFMLRef/WS932f2e4c7c04df8f744b691e1353e37d519-8000.html

Any idea regarding all of the algorithms & encoding that Hmac() supports? (Will this be further documented?)

On another note (hash related) I recently read an article recommending the use of bcrypt or BKDF2 "exclusively" to hash anything that needs to be secured:
http://www.codinghorror.com/blog/2012/04/speed-hashing.html

Here's an article on how to integrate bcrypt w/ColdFusion:
http://blog.mxunit.org/2011/02/hashing-passwords-with-bcrypt-in.html

bcrypt looks pretty nice & I was wondering if any additional security-related features, like bcrypt, may make it into CF10?


Apr 9, 2012 at 3:19 PM // reply »
11,246 Comments

@James,

I know there are licensing issues between some of the various encryption algorithms. There are some that can only be accessed via Enterprise licensing. If you look up the documentation for the encrypt() function, you can see the licensing differences in algorithm support between Standard and Enterprise.

I don't know if that applies to this particular function, or what sub-set of algorithms this supports.

I can say that in my [limited] experience, all the hashing algorithms I've come across when dealing with 3rd party APIs was MD5, Sha-1, and Sha-256.

I don't know too much about bcrypt. Honest, I don't know too much about advanced security and cryptography. I'll have to check out Marc's article on the matter, thanks!


Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 24, 2013 at 5:39 PM
Ask Ben: Manually Enforcing Basic HTTP Authorization In ColdFusion
@Adam Oops! My mistake! I hadn't gotten that far in my testing - I'm still baby stepping my way through the process. ... read »
May 24, 2013 at 5:13 PM
Ask Ben: Manually Enforcing Basic HTTP Authorization In ColdFusion
Hi Jason, Thanks for checking up on that, but I still stand firm on my position. :) There are actually two listLast()'s in use, and you're right that the one using a space as a delimiter is fine. ... read »
May 24, 2013 at 4:45 PM
Ask Ben: Manually Enforcing Basic HTTP Authorization In ColdFusion
@Ben I have been lurking your site for quite some time, and haven't stepped up to comment until today. Thanks for all the great info - keep it up! @Adam I believe you are mistaken... as the commen ... read »
May 24, 2013 at 11:21 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@WebManWalking, Ha ha, let's us never speak of justifying "##" notation again :P ... read »
May 24, 2013 at 11:18 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Ben, Ah, so it was indeed how I vaguely remembered it to be: A direct assignment value = users.id[ i ] causes value to retain the sticky datatype of the query column. Although unnecessary in ... read »
May 24, 2013 at 9:11 AM
Preventing Links In Standalone iPhone Applications From Opening In Mobile Safari
@Brandon, Hi, No, I haven't been able to do that. I have just kept it as it is. ... read »
May 23, 2013 at 9:52 PM
Preventing Links In Standalone iPhone Applications From Opening In Mobile Safari
@Muhmmadibn Did you figure out a solution to launching PDFs? I am running into the same issues myself. There is no way to close the PDF or go back once you launch it. Thanks in advance! ... read »
May 23, 2013 at 6:06 PM
The Girl Who Broke My Heart, And Made Me A Better Person
Good day,ladies and gentle men, my name is Dr AMADI the great spell caster in Africa, i have help so many people for different kind of problems,who say there is no solution to problems on earth, that ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools