36

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

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Oana Andone
  • 661
  • 2
  • 7
  • 13

2 Answers2

50

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)
Tim Tisdall
  • 9,914
  • 3
  • 52
  • 82
nunodsousa
  • 2,635
  • 4
  • 27
  • 49
  • 31
    Why use latin-1? – Ahmed Mar 03 '21 at 18:52
  • 3
    `signature = hmac.new(bytes(API_SECRET , 'utf-8'), msg = bytes(message , 'utf-8'), digestmod = hashlib.sha256).hexdigest().upper()` – Mohsenasm Dec 22 '21 at 09:07
  • @Ahmed 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](https://www.rfc-editor.org/rfc/rfc5987). 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. – Philip Couling Sep 20 '22 at 22:11
  • 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? – ntg Oct 21 '22 at 18:15
  • `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 string – bn_ln Dec 13 '22 at 00:36
33

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
Rz Mk
  • 1,072
  • 10
  • 15