Python encoded message with HMAC-SHA256
Asked Answered
C

2

38

I try to encoded message with HMAC-SHA256 in Python according to [instructions][1]

import hmac
import hashlib

nonce = 1234
customer_id = 123232
api_key = 2342342348273482374343434
API_SECRET = 892374928347928347283473

message = nonce + customer_id + api_key
signature = hmac.new(
    API_SECRET,
    msg=message,
    digestmod=hashlib.sha256
).hexdigest().upper()

but I get this

Traceback (most recent call last): File "gen.py", line 13, in digestmod=hashlib.sha256 File "/usr/lib/python2.7/hmac.py", line 136, in new return HMAC(key, msg, digestmod) File "/usr/lib/python2.7/hmac.py", line 71, in init if len(key) > blocksize: TypeError: object of type 'long' has no len()

Does anyone have any idea why crashes? [1]: https://www.bitstamp.net/api/#account-balance

Corny answered 30/6, 2016 at 21:34 Comment(0)
P
34

You're using numbers where the api expects a string/bytes.

# python 2
import hmac
import hashlib

nonce = 1234
customer_id = 123232
api_key = 2342342348273482374343434
API_SECRET = 892374928347928347283473

message = '{} {} {}'.format(nonce, customer_id, api_key)
signature = hmac.new(
    str(API_SECRET),
    msg=message,
    digestmod=hashlib.sha256
).hexdigest().upper()

print signature
Puritanical answered 30/6, 2016 at 21:45 Comment(0)
F
53

If you want to execute in python3 you should do the following:

#python 3
import hmac
import hashlib

nonce = 1
customer_id = 123456
API_SECRET = 'thekey'
api_key = 'thapikey'

message = '{} {} {}'.format(nonce, customer_id, api_key)

signature = hmac.new(
    bytes(API_SECRET, 'latin-1'), 
    msg=bytes(message, 'latin-1'), 
    digestmod=hashlib.sha256
).hexdigest().upper()
print(signature)
Fatwitted answered 26/10, 2017 at 13:45 Comment(6)
Why use latin-1?Dolerite
signature = hmac.new(bytes(API_SECRET , 'utf-8'), msg = bytes(message , 'utf-8'), digestmod = hashlib.sha256).hexdigest().upper()Diann
@Dolerite Very commonly HMAC is used to sign HTTP requests. The exact "message" it signs is often a composition of the HTTP headers and a hex-encoded hash of the message body. HTTP headers are almost exclusively ISO-8859-1 (latin 1) see here. So in 99% of cases where people want this example they will want to encode with latin 1. Both sender and recipient need to know what encoding to expect. If you want this for something other than HTTP latin 1 might not be correct.Kaif
It is probable that using a constant nonce makes no sense and may leave you open to attacks? Or not? Why is the nonce constant?Carvel
signature = hmac.new(key=bytes(str(API_SECRET), 'utf-8'), msg=bytes(message, 'utf-8'), digestmod=hashlib.sha256).hexdigest().upper() incase API_SECRET isn't a stringFoot
@Foot Why rely on some random string conversion for API_SECRET? Why not just ensure it is in the right format. I don't want to call str(None) or something like that.Reheat
P
34

You're using numbers where the api expects a string/bytes.

# python 2
import hmac
import hashlib

nonce = 1234
customer_id = 123232
api_key = 2342342348273482374343434
API_SECRET = 892374928347928347283473

message = '{} {} {}'.format(nonce, customer_id, api_key)
signature = hmac.new(
    str(API_SECRET),
    msg=message,
    digestmod=hashlib.sha256
).hexdigest().upper()

print signature
Puritanical answered 30/6, 2016 at 21:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.