I searched around and couldn´t find an answer for this. I noticed I can generate message digests using, let´s say blake2b algorithm using hashlib library or hmac library, which uses the digestmod indicated by hashlib. So:
plainMsg = "this is a plaintext message"
hashlib_hashed = hashlib.blake2b(key=b'super secret key')
hashlib_hashed.update(plainMsg.encode())
hmac_hashed = hmac.new(b'super secret key', digestmod=hashlib.blake2b)
hmac_hashed.update(plainMsg.encode())
print(hashlib_hashed.hexdigest())
print(hmac_hashed.hexdigest())
In my mind they should generate the same message digests as I´m using the same algorithm, same key and the same plaintext. But they generate two different digests:
ec0d0ab13d7e7f3b62d742aa92078a4a14346ee6ee352e27c8814e4bf6361556fdc3d301e100b5a2c90c5596c4b2bb72c887c6b6aa92fb41752f6b52105ce13b
b632045e745550e5b9da6d411c013c978cb8120847260eb8fda9c8885368a5eaba80cd74ad95a51b1a4bde1f47cccb5a2e4591e9935126f673479c7474c2be97
I initially though it would have to do with salt, as I didn´t use one with hashlib.blake2b(), so I guess it´s empty since salt=b''. But using hmac I didn´t find how to set up a salt. So, can anyone explain?
The HMAC algorithm is more than just "hash key followed by message"; the key is padded to match the algorithm's block size, each byte is then xor-ed with a fixed "ipad" (0x36), the hash is computed from that value followed by the text. Then the original padded key is xor-ed with a fixed "opad" (0x5C) and the hash is again computed from that new value followed by the hash from the previous step.
Point is, it's not as straightforward as you think it is. You can look at the contents of the
hmac.HMACclass to see the additional rigmarole Python does to follow the HMAC RFC.