Search code examples
javascriptpythonhmac

Reproducing an hmac operation in python from the javascript reference case


I have a fragment of javascript that operates properly:

let seed = '319aa8124bbcddac2bae8438cfd5e658aeca56d524736739622dfb0a09942b22';
let salt = '0000000000000000004d6ec16dafe9d8370958664c1dc422f452892264c59526';
// 1. HMAC_SHA256(message=seed, key=salt)  
const hmac = CryptoJS.HmacSHA256(CryptoJS.enc.Hex.parse(seed), salt);
let foo = hmac.toString(CryptoJS.enc.Hex);
console.log("foo", hmac.toString(CryptoJS.enc.Hex));  //foo fe6a57f08b9970b7cd497e627afac956203a8ef829d2d97c7967775c1c0b6f6a

I try to reproduce it in python:

seed = "319aa8124bbcddac2bae8438cfd5e658aeca56d524736739622dfb0a09942b22"
salt = "0000000000000000004d6ec16dafe9d8370958664c1dc422f452892264c59526"
hm = hmac.new(str.encode(seed), b'', hashlib.sha256)
hm.update(salt.encode("utf-8"))
h = hm.hexdigest()
print(h)   # returns 01703d8db07432ca416151099533b60baea7a6450fc5b88788c7ca9af921b4a1

but the result is incorrect.

I think the step I'm missing is the CryptoJS.enc.Hex.parse(seed) operation that occurs in the javascript. I don't understand what that is doing to the seed value. I try to console.log() that value but it returns a complicated object that I don't comprehend.

So my questions are:

  1. what is that function doing to the the seed
  2. how to do the equivalent in python.

Solution

  • These algorithms work on raw bytes. Your seed is representing those bytes in hexadecimal, i.e. 31 is one byte, 9a is another. CryptoJS.enc.Hex.parse parses the hexadecimal to bytes. The equivalent in Python is with codecs.decode("...", "hex").

    The salt also looks like hexadecimal but your JS doesn't parse it as such, so I've just treated it as UTF8 in the python as well.

    import hmac
    import hashlib
    import codecs
    
    seed = codecs.decode(b"319aa8124bbcddac2bae8438cfd5e658aeca56d524736739622dfb0a09942b22", "hex")
    salt = u"0000000000000000004d6ec16dafe9d8370958664c1dc422f452892264c59526".encode("utf8")
    hm = hmac.new(salt, seed, hashlib.sha256)
    h = hm.hexdigest()
    print(h)   # returns fe6a57f08b9970b7cd497e627afac956203a8ef829d2d97c7967775c1c0b6f6a