How to Create Md5 Hash with Hmac Module in Ruby

How to create MD5 hash with HMAC module in Ruby?

The following gem should be installed: 'ruby-hmac'

$ irb
>> require 'hmac-md5'
=> true
>> HMAC::MD5.new("abc").digest
=> "\324\035\214\331\217\000\262\004\351\200\t\230\354\370B~"
>> HMAC::MD5.new("abc").hexdigest
=> "d41d8cd98f00b204e9800998ecf8427e"
>>

How does this PHP function should look in Ruby? HMAC MD5

There is no reason to write your own implementation of HMAC and many, many reasons not to. Just use the secure and well-tested implementation supplied by the OpenSSL module:

require "openssl"

key = "key"
data = "Hello"

digest = OpenSSL::Digest.new('md5')
hmac = OpenSSL::HMAC.hexdigest(digest, key, data)

That's literally all you need.

HMAC vs simple MD5 Hash

The Wikipedia article on HMAC gives a good explanation of this.

In the Security section of the same article it goes on to say:

HMACs are substantially less affected by collisions than their underlying hashing algorithms alone.

So adding an HMAC to an MD5 hash would make it substantially more difficult to break via a rainbow table.

Difference between OpenSSL::HMAC#hexdigest vs Digest::MD5#hexdigest in ruby?

The HMAC-MD5 of DATA and KEY is define as

MD5( (K xor pad1) + H ((K xor pad2) + DATA )

where pad1 and pad2 are two fixed constants. Some of the more obvious things you might do are cryptographically weak.

Digest::MD5.hexdigest(KEY + DATA)

is fatally flawed. Consider how MD5 works. It splits the input up into blocks of a certain size (512 bits for md5) and sets up some initial state h0, h1, h2, h3. It then does a bunch of transformations to mix the first block of data with that initial state to produce new values of h0, h1, h2, h3. The second block of data is then combined with those to produce a new set of h0,h1,h2,h3 and so on. The final value of the hash function is just the concatenation of h0,h1,h2,h3.

This means that if you give me Digest::MD5#hexdigest(KEY + DATA) then I can calculate what Digest::MD5#hexdigest(KEY + DATA + OTHER_DATA) is without knowing KEY at all. You can do the same thing with SHA1

If instead you did

Digest::MD5.hexdigest(DATA+KEY)

then any known collisions in MD5 are easily used to make messages with the same HMAC value.

Apparently

Digest::MD5.hexdigest(KEY+DATA+KEY)

may be flawed too, even if two different keys were used. HMAC was designed to mitigate all of these attacks.

Equivalent ruby code for PHP MD5 Key

You need to concatenate your post_data and secretkey values in the same way that you're doing using the . operator in PHP, so that you're only passing a single string to the MD5 digest function.

Digest::MD5.hexdigest(post_data + secretkey)

is the simplest method, though you could also use

Digest::MD5.hexdigest(post_data << secretkey) 

or

Digest::MD5.hexdigest("#{post_data}#{secretkey}")

HMAC (hash-based message authentication code, aka data signing) in Mathematica

Here's my implementation:

First some utility functions:

(* Pad the string s with x on the right/left so it has length n. *)
strpadr[s_, n_, x_] := StringJoin@PadRight[Characters[s], n, x]
strpadl[s_, n_, x_] := StringJoin@PadLeft[Characters[s], n, x]

(* hex representation; optionally pad to length n with zeros *)
hex[x_, n_:Null]:= If[n===Null, Identity, strpadl[#,n,"0"]&]@IntegerString[x,16]

(* parse hex representation (return an integer) *)
unhex[x_] := FromDigits[x, 16]

(* Concatenate all the arguments as strings (if they're not already). *)
cat = StringJoin @@ (ToString /@ {##}) &;

(* Takes a string like "xy" and returns the hex representation (also a string,
twice as long) of the bytes (ascii codes). *)
tobytes[s_] := cat @@ (hex[#, 2] & /@ ToCharacterCode[s])

(* Takes a length n string like "0a10" and returns a length n/2 string where in
this example the first character is whatever has ascii code 10 ("a" in hex)
and the second is whatever has ascii code 16 ("10" in hex). *)
frombytes[hs_] := FromCharacterCode[unhex /@ cat@@@Partition[Characters[hs], 2]]

(* Bitwise-xor of two integers given in hex. *)
hexbitxor[a_String, b_String] := hex@BitXor[unhex@a, unhex@b]

(* Repeat the string s, n times. *)
strrpt[s_, n_] := cat @@ ConstantArray[s, n]

(* Byte length of a hex string is half the string length. *)
bytelen[s_] := Ceiling[StringLength[s]/2]

Implementing the basic hash functions in Mathematica is not quite trivial. See this question:
Cryptographic hash (sha1 or md5) of data given as a string in Mathematica.

(* FileHash is the only way to hash data given as a string in Mma. *)
hash[s_String, h_:"SHA"] := Module[{stream = StringToStream[s], result},
result = FileHash[stream, h];
Close[stream];
hex@result];
sha1[s_] := hash[s]
md5[s_] := hash[s, "MD5"]

Finally, here's the hmac function:

(* Return the hmac digest using hash function h for string s with key k. *)
hmac[s_, k_, h_:sha1] := Module[{b, key, ipad, opad},
b = 64; (* block size for both md5 and sha1 *)
key = tobytes[k];
key = If[bytelen[key] > b, h[frombytes@key], key];
key = strpadr[key, 2 b, "0"];
ipad = hexbitxor[strrpt["36", b], key];
opad = hexbitxor[strrpt["5c", b], key];
h[frombytes[opad <> h[frombytes[ipad <> tobytes@s]]]]]

I confirmed that this matches all the examples provided in RFC 2104. For example:

hmac["what do ya want for nothing?", "Jefe", md5]

returns

"750c783e6ab0b503eaa86e310a5db738"

C++ - HMAC MD5 is not equals with online generator

You are incorrectly assuming that the web site is converting the data from a hex string to bytes when it's not.

This simple example results in the same output as the web site:

bool test_gen_md5_hmac()
{
std::string k = "320E6FADB2738DA273A41E14F85027E1";
std::string d = "35413B1DD9AB9FA0F1395759BD72451C";
unsigned char hash[16];
unsigned int len = 16;
HMAC(EVP_md5(), k.c_str(), k.size(), (unsigned char*)d.c_str(), d.size(), hash, &len);
char* rv = OPENSSL_buf2hexstr(hash, 16);
std::string rv_str(rv);
OPENSSL_free(rv);
return rv_str == "BB:4C:6D:FF:8A:4F:70:6B:0A:52:06:92:2D:38:A1:91";
}

Getting Ruby code to work, creating SHA1 hash from given string and key

You need to install the ruby-hmac module. See this blog post for a gentle introduction.



Related Topics



Leave a reply



Submit