31

I'm trying to apply HMAC-SHA256 for generate a key for an Rest API.

I'm doing something like this:

def generateTransactionHash(stringToHash)
  key = '123'
  data = 'stringToHash'
  digest = OpenSSL::Digest.new('sha256')

  hmac = OpenSSL::HMAC.digest(digest, key, data)
  puts hmac
end

The output of this is always this: (if I put '12345' as parameter or 'HUSYED815X', I do get the same)

ۯw/{o���p�T����:��a�h��E|q

The API is not working because of this... Can some one help me with that?

Eduardo Pedroso
  • 839
  • 3
  • 12
  • 30

4 Answers4

54

According to the documentation OpenSSL::HMAC.digest

Returns the authentication code an instance represents as a binary string.

If you have a problem using that maybe you need a hex encoded form provided by OpenSSL::HMAC.hexdigest

Example

key = 'key'
data = 'The quick brown fox jumps over the lazy dog'
digest = OpenSSL::Digest.new('sha256')

OpenSSL::HMAC.digest(digest, key, data)
#=> "\xF7\xBC\x83\xF40S\x84$\xB12\x98\xE6\xAAo\xB1C\xEFMY\xA1IF\x17Y\x97G\x9D\xBC-\x1A<\xD8"

OpenSSL::HMAC.hexdigest(digest, key, data)
#=> "f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8"
Mike Szyndel
  • 10,461
  • 10
  • 47
  • 63
  • In this case to make it HMAC SHA256 you need to put `digest = OpenSSL::Digest.new('sha256')` in the lower comment: https://stackoverflow.com/a/42832500/4706812 – cmunozgar Jun 27 '19 at 10:20
  • Updated the answer @cmunozgar, not sure why I put sha1 in there in the first place – Mike Szyndel Jul 30 '19 at 16:01
  • No need to create a digest instance, just put a string represents the algorithm and it works like a charm `OpenSSL::HMAC.hexdigest('sha256', key, data)` since ruby 2.5 https://ruby-doc.org/stdlib-2.5.1/libdoc/openssl/rdoc/OpenSSL/HMAC.html#method-i-digest – Dat Le Tien Jun 01 '22 at 11:02
20

Try This:

hmac = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), key, data)
digitalextremist
  • 5,952
  • 3
  • 43
  • 62
Vish
  • 317
  • 3
  • 8
0
   def make_payment(user)
    @key= SecureRandom.hex(10)
    #puts @key
    @secret_key = @key
    puts " this is the  public key #{@secret_key}"
    @access_key= generate_key
    puts " this is the access key #{@access_key}"
    @name= @user.name
    puts "#{@name}"
    @time= Time.now.in_time_zone("Nairobi")
    puts "This is the time request sent #{@time}"
    @server_key = SecureRandom.base64
    puts "This is the server key #{@server_key}"
    @data = 'This request is being made from Learnida for users to make a payment'
    @digest = OpenSSL::Digest.new('sha256')
    uri = URI.parse("https://learnida.com")

    @hmac = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), @secret_key, @access_key)
     puts "This is the HMAC #{@hmac}"
    req = Net::HTTP::Get.new(uri)
    req['Authorization'] = "TM-HMAC-SHA256 key=#{@access_key} ts=#{@time} sign=#{@hmac}"
    res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
    @hmacdigest= OpenSSL::HMAC.digest(@digest, @server_key, @data)
    puts" This is the HMAC:SHA-256:   #{@hmacdigest}" 
    #puts res.body
    #=> "\xF7\xBC\x83\xF40S\x84$\xB12\x98\xE6\xAAo\xB1C\xEFMY\xA1IF\x17Y\x97G\x9D\xBC-\x1A<\xD8"
    @sslkey= OpenSSL::HMAC.hexdigest(@digest, @server_key, @data)
    puts @sslkey
-1

In my case (Ticketmatic) I had to create the HMAC like above and add an Authorization header to the request with the HMAC in it.

hmac = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), secret_key, access_key + name + time)
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "TM-HMAC-SHA256 key=#{access_key} ts=#{time} sign=#{hmac}"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }

You can find a full gist here

And a blogpost with more explantion here