2

I'm trying to get the HMAC SHA256 value(str_signature), I followed the Ruby code from this post, although his example was converting code from Java(with a Hex key).

C#

string strRawSignature = "200123123891:12|11231231|GET|just%20test%20value"

// Convert signature to byte array in order to compute the hash
byte[] bSignature = Encoding.UTF8.GetBytes(strRawSignature);

// Convert ApiKey to byte array - for initializing HMACSHA256
byte[] bSecretKey = Convert.FromBase64String(strApiKey);

string strSignature = "";
using (HMACSHA256 hmac = new HMACSHA256(bSecretKey))
{
    // Compute signature hash
    byte[] bSignatureHash = hmac.ComputeHash(bSignature);

    // Convert signature hash to Base64String for transmission
    str_signature = Convert.ToBase64String(bSignatureHash);
}

Ruby

require "openssl"
require "base64"

digest = OpenSSL::Digest.new('sha256')
key = [ 'xiIm9FuYhetyijXA2QL58TRlvhuSJ73FtdxiSNU2uHE=' ]

#this is just a dummy signature to show what the possible values are
signature = "200123123891:12|11231231|GET|just%20test%20value"

hmac = OpenSSL::HMAC.digest(digest, key.pack("m*"), signature)
str_signature = Base64.urlsafe_encode64(hmac)
example result: "B0NgX1hhW-rsnadD2_FF-grcw9pWghwMWgG47mU4J94="

Update:

  1. Changed the pack method to output base64 strings.

  2. Edited variable names for concistency

References:

  1. Used hexdigest, has a different ouput string length.
  2. This example uses the digest method, although I'm not sure what value the key parameter has, hopefully it's a base 64 encoded string.
  3. This uses hexdigest again. I am pretty sure that digest is the method to go vs hexdigest, since hexdigest ouput has a longer string compared to the sample HMAC value I have from C# script.
Community
  • 1
  • 1
olleh
  • 1,248
  • 5
  • 16
  • 43
  • You are trying to convert the key as hexadecimal, but your key is not hexadecimal (contains other characters than 0-9 and A-F).... – Marco Sandrini Aug 20 '15 at 06:10
  • Are you trying to find how to match `hmac_string` in Ruby with `strSignature` from the C#? It is not clear, because you have used very different variable names in each piece of code (and confusing ones which include the word 'signature' for what appears to be the message), and you do not show what value of `strRawSignature` is the starting point in C#. Please also show initial value of `strApiKey` from C# – Neil Slater Aug 20 '15 at 06:38
  • @MarcoSandrini - thanks for pointing that out! I should switch key.pack to key.pack("m*") instead (base 64), but still, it generates a different result from the required string. – olleh Aug 20 '15 at 07:40
  • I tried to reproduce your code, but I get a different result `LgWgbV0hrs4tiE5LmffDMyTfG-_xjjexbcCIqF5PJnU=` Please make sure that the key and the data you are using in the C# match exactly the one you are using in the Ruby one, and that the expected result is also updated. – Marco Sandrini Aug 20 '15 at 08:48
  • @MarcoSandrini my bad, the example results are based from a different input data. I didn't post the actual data cause of it's confidentiality(parameters), I'll update this post later by posting the actual result for both of the scripts. – olleh Aug 20 '15 at 08:54
  • One more thing: `pack("m*")` encodes to Base64, you should change the code so that the digest is created using `hmac = OpenSSL::HMAC.digest(digest, Base64.decode64(base64key), signature)` – Marco Sandrini Aug 20 '15 at 09:04
  • @MarcoSandrini currently my key is a base64 encoded string. Should I convert this key string to let's say decode it base 64 or leave it as is? I know that I should use digest method instead of hexdigest cause the sample hmac value has the same length with the digest method ouput. expected output is a 44 length base 64 encoded string. – olleh Aug 24 '15 at 08:27
  • Given the C# code `byte[] bSecretKey = Convert.FromBase64String(strApiKey);` it does appear that you should decode the Base64 encoded string. And you are absolutely right in using digest and not hexdigest. The key in your new example is simply the string "key", so it is not base64 encoded. – Marco Sandrini Aug 24 '15 at 08:45
  • I finally got it. @MarcoSandrini basically, I don't have to create a sha256 digest object. just place the string as parameter instead. http://www.jokecamp.com/blog/examples-of-creating-base64-hashes-using-hmac-sha256-in-different-languages/#ruby – olleh Aug 24 '15 at 08:50
  • Passing a `Digest` object or a string defining the digest object to be created is equivalent. If you got your code to work, it is because you are now passing the right key to the digest function. – Marco Sandrini Aug 24 '15 at 08:59

1 Answers1

2

Finally got the monkey of my back!

I don't really need to create a sha256 digest object after all, I just had to put the 'sha256' parameter.

require 'openssl'
require "base64"
#API_KEY = base64 encoded string
key = Base64.decode64(API_KEY)
hash  = OpenSSL::HMAC.digest('sha256', key, "Message")
puts Base64.encode64(hash)

thanks to this link

olleh
  • 1,248
  • 5
  • 16
  • 43