4

I'm trying to implement authorization based on a hash-based message authentication code (HMAC)-encrypted authorization header. To do so I need to use the authorization header to verify the authenticity of the message content by recalculating the hash using the binary buffer of the authenticationToken.

There is a Node.js code that works just fine and recalculates the hash as it should:

const { Buffer } = require('buffer')
const crypto = require('crypto')

const verifyAuthorizationTokenHTTP = () => {
  const authenticationToken = 'string-token'
  const authenticationTokenBinary = Buffer.from(authenticationToken, 'base64')
  const authHeader = 'B4NmoAWcwqeLVx6ZlfAH26oHhFgpBaBfxmO0TXVsN7k='
  const request_body = 'plain_text_json_like_string'
  const hmac = crypto.createHmac('sha256', authenticationTokenBinary)
  hmac.update(request_body)
  const hashInBase64 = hmac.digest('base64')
  console.log(`result: ${hashInBase64 === authHeader}`)
  return hashInBase64 === authHeader
}

verifyAuthorizationTokenHTTP()

But thing is that I need to implement it in Python and I can't make it work:

import base64
import hmac


def verifyAuthorizationTokenHTTP():
    authenticationToken = 'string-token'
    authenticationToken_bytes = authenticationToken.encode('utf-8')
    authenticationToken_base64 = base64.b64encode(authenticationToken_bytes)
    authHeader = 'B4NmoAWcwqeLVx6ZlfAH26oHhFgpBaBfxmO0TXVsN7k='
    request_body = 'plain_text_json_like_string'
    h = hmac.new(key=authenticationToken_base64, msg=request_body.encode('utf-8'), digestmod="sha256")
    hashInBase64 = base64.b64encode(h.digest())

    print(authHeader == hashInBase64)


if __name__ == '__main__':
    verifyAuthorizationTokenHTTP()

I'm not sure that base64.b64encode() (or also base64.b64decode(), codecs.encode(), codecs.decode()) in Python is right equivalent of Buffer.from('string', 'base64') in Node.js

What am I doing wrong?

Solved:

The thing was that authenticationToken should be in base64 string but JS successfully eaten plain string instead of base64 encoded one.

So bytearray(base64.b64decode('base64_string')) in python is full equivalent of Buffer.from('base64_string', 'base64')

flintpnz
  • 41
  • 3

1 Answers1

0

Glad to see that you solved it by yourself. I'd like to add something here, too.

If it's not base64ed, say the following nodejs code

 echo "console.log(require('crypto').createHmac('sha256', 'nonbase64key').update('password').digest('hex'))" | node

it's equivalent in python is:

python3 -c 'import hashlib;import base64;import hmac;print(hmac.new(b"nonbase64key", "password".encode(), hashlib.sha256).hexdigest())'

And the equivalent shell command is:

echo -n "password" | openssl sha256 -hmac "nonbase64key"
Jeff Tian
  • 5,210
  • 3
  • 51
  • 71