You need to sign in to do that
Don't have an account?
@altius_rup
Crypto SHA512 HMAC with binary hex key - Apex equivalent of PHP/Java example
Hi,
I'm trying to reproduce in APEX this PHP example :
<?php
$key ="0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF";
$binkey = pack("H*", $key);
echo strtoupper(hash_hmac('sha512',"ABC", $binkey));
?>
or this Java example :
privateString generateHMAC(String datas )
{
// final Charset asciiCs = Charset.forName( "utf-8" );
Mac mac;
String result ="";
try
{
finalSecretKeySpec secretKey = newSecretKeySpec( DatatypeConverter.parseHexBinary(CONSTANTS.KEY),"HmacSHA512");
mac =Mac.getInstance("HmacSHA512");
mac.init( secretKey );
finalbyte[] macData = mac.doFinal( datas.getBytes());
byte[] hex =newHex().encode( macData );
result =newString( hex,"ISO-8859-1");
}
return result.toUpperCase();
}
This is my APEX code :
private String hmacFunction(String str, String k) { Blob mac = Crypto.generateMac('hmacSHA512', Blob.valueOf(str), Blob.valueOf(k)); return EncodingUtil.convertToHex(mac).toUpperCase(); }
This is no good, for the moment : encrypted strings match between Java and PHP, not with APEX.
The result for ABC should be :
100A6A016A4B21AE120851D51C93B293D95B7D8A44B16ACBEFC2D1C9DF02B6F54FA3C2D6802E52FED5DF8652DDD244788A204682D2D1CE861FDA4E67F2792643
Obviously, the difficulty lies in the pack('H*, key) conversion which seems to be different from the Blob.valueOf(key) call.
Can anyone help ?
Rup
The problem is that Blob.valueOf(key) does not do the hex decode - it just gives you the ascii bytes of the input. Unfortunately there is not (yet) an EncodingUtil.convertFromHex(), so the only way to create a binary key from string input is base64.
I generated the correct base64 encoding with php:
And this Apex gives the correct result:
Output:
Cheers,
Pat
All Answers
The problem is that Blob.valueOf(key) does not do the hex decode - it just gives you the ascii bytes of the input. Unfortunately there is not (yet) an EncodingUtil.convertFromHex(), so the only way to create a binary key from string input is base64.
I generated the correct base64 encoding with php:
And this Apex gives the correct result:
Output:
Cheers,
Pat
Wow, thanks for your reactivity !
But how did you produce the base64key ?
Rup
Pat,
Sorry for the stupid question. It should have been :
How can I create that base64key in APEX, or any other way (call out to a webservice) ?
Rup
It has been a while but you can convert from hex to integer array, then integer array to string. I wrote a function that does it. I shared it previously here and there is also a multi-byte version on there as well from another guy. I also have a multi-byte utility function and can send if necessary, but his looks right. The function you want to see use with it is String.fromCharArray(List<Integer>)
http://boards.developerforce.com/t5/Apex-Code-Development/Method-to-convert-Hex-to-String-or-blob/m-p/482297#M88828
Hi Richard,
Does that hex->string method work for arbitrary hex-encoded binary input? It seems like it would fail for certain input, since not all binary input are valid multibyte strings.
Cheers,
Pat
Hi Pat,
From what I've seen/tested it does work even for odd binary characters, but of course would be unreadable. I used this method to write my own AES encryption utility (ported Bouncy Castle) prior to there being encryption in Apex.
Although for arbitrary keys like this I'd just use the standard hex to integer that I posted on that post instead of the multibyte.
Awesome - I can abandon the String hexToBase64(String hexInput) method I was considering writing! :-)
Hmm - I wrote a quick test routine:
But the last assert fails:
The output is as expected until input 80, for which the output is c280 :-/
Am I missing something?
You're right, as soon as it crosses the 127 border it goes into multibyte territory and falls apart. Hmm... I'm gonna take another stab from another angle.
Okay, here is another approach. Its the best I could think of given the multibyte quandary.
I compared against Pat's Base64 value using an assertion and it works as expected. Can you two confirm on your end?
And ironically enough I missed your message about writing a function just like this Pat. :)
Good to know my thought process was along the same lines. Hope this helps.
Richard,
I tested your code on the few examples I have, and it's OK for me.
Thanks both for helping me solve this problem I have been trying to understand for the last 3 weeks !
BR,
Rup
Output:
Cheer,
Kevan Moothien