1

I'm trying to mimic is this PHP functionality

<?php
    base64_encode( hash_hmac( 'SHA256', $a, $b, true) );
?>

is there a difference between the "HmacSHA256" and "sha256"?

This works - but doesn't give me the same result:

<cfscript>
    toBase64( hmac( a, b, 'HmacSHA256', 'us-ascii' ) );
</cfscript>

this tells me "sha256" is unavail (because Im not using enterprise)

<cfscript>
    toBase64( hmac( a, b, 'SHA256', 'us-ascii' ) );
</cfscript>

Any way I can do this without enterprise? isn't there a java lib i can tie into for encoding?

thanks

Machavity
  • 30,841
  • 27
  • 92
  • 100
j-p
  • 3,698
  • 9
  • 50
  • 93

3 Answers3

3

The CF documentation for hmac is sorely lacking useful details. The reason your code does not work is that hmac() returns a hexadecimal string. Whereas the PHP call to hash-hmac returns binary. As a result, your CF script is base64 encoding a completely different value. That is why the two results do not match.

You need to decode the hex string into binary first. Then encode the binary as base64 and the results will match:

resultAsHex = hmac("Well done is better than well said.", "key", "HmacSHA256");
finalValue = binaryEncode( binaryDecode(resultAsHex, "hex"), "base64" );
writeDump( finalValue );

As an aside, toBase64() is deprecated. The docs recommend using binaryEncode for new applications.

Leigh
  • 28,765
  • 10
  • 55
  • 103
  • Yes leigh - you are absolutely correct. and that was part of our solution. - maybe you can answer this.... toBase64( toBinary( hmac( a, b, 'HmacSHA256', 'us-ascii' ) ) ); would SEEM to convert the return from hmac to binary - shouldn't that be the same result??? it doesn't work out that way. - and thank you for the imput. – j-p Nov 18 '14 at 03:46
  • Nope :) *How* you decode a string makes a big difference. `toBinary()` expects the input to be base64 encoded. You are passing in hex. It will not cause an error. However, the *decoded* value will be wrong. That is why you get a different result. BTW, `toBase64` is deprecated. For new apps, use `binaryEncode` instead. – Leigh Nov 18 '14 at 04:35
  • THANK YOU!!! I was having the same issue working with an example written in C# – Giancarlo Gomez Oct 23 '20 at 19:32
2

This is a generic version of something I've used recently. Haven't tested this exact code, but give it a shot. I store the encrypted value of SECRET_KEY in the database in order to keep it out of the application code.

<cffunction name="HmacSHA256" access="public" output="false" returntype="string" hint="Generates HmacSHA256 string.">
    <cfargument name="message" type="string" required="true" hint="form data" />
    <cfset var HMAC_SHA256 = "HmacSHA256" />
    <cfset var SECRET_KEY = "{YOUR_SECRET_KEY}" />

    <cfset var secretKeySpec = createObject("java", "javax.crypto.spec.SecretKeySpec").init( SECRET_KEY.getBytes("UTF-8"), HMAC_SHA256 ) />
    <cfset var mac = createObject("java", "javax.crypto.Mac").getInstance(HMAC_SHA256) />
    <cfset mac.init( secretKeySpec ) />
    <cfset var rawHmac = mac.doFinal( arguments.message.getBytes("UTF-8") ) />
    <cfset var encoder = createObject("java", "sun.misc.BASE64Encoder") />
    <cfreturn encoder.encodeBuffer(rawHmac).replace("\n", "").replace("\r", "") />
</cffunction>
Leigh
  • 28,765
  • 10
  • 55
  • 103
Adrian J. Moreno
  • 14,350
  • 1
  • 37
  • 44
  • ya - this concept works. we found a cfc (it may have been crypto.cfc, not sure where it came from.) it's using the same concepts, but it has the steps abstracted to allow for different encodings. thx... – j-p Nov 17 '14 at 18:15
0

It looks like you might have to install libraries to get sha256

ColdFusion 10 introduced the hmac() function for generating secure, hashed message authentication codes (HMAC). This function makes dealing with 3rd-Party APIs much easier. Before ColdFusion 10, however, you would need to dip down into the Java layer to access the security libraries. This ColdFusion component - Crypto.cfc - attempts to make access to such libraries easier and more concise.

Machavity
  • 30,841
  • 27
  • 92
  • 100