我对HMAC有轻微问题。运行这段代码时:
signature = hmac.new(
key=secret_key,
msg=string_to_sign,
digestmod=sha1,
)
我收到一个奇怪的错误:
File "/usr/local/Cellar/python/2.7.6/Frameworks/Python.framework/Versions/2.7/lib/python2.7/hmac.py", line 133, in new
return HMAC(key, msg, digestmod)
File "/usr/local/Cellar/python/2.7.6/Frameworks/Python.framework/Versions/2.7/lib/python2.7/hmac.py", line 72, in __init__
self.outer.update(key.translate(trans_5C))
TypeError: character mapping must return integer, None or unicode
当我打印string_to_sign时,它是一个正确的字符串,如下所示:
GET
\n
\n
application/json
\n
\n
\n
错误是什么意思?是因为新线?
答案 0 :(得分:37)
如我所知,我会将此作为答案发布。 您遇到的错误是Python的HMAC的功能。它不接受unicode。 此功能描述为here。
HMAC是一个在字节级工作的函数。出于这个原因,在Python 3中它只接受bytes
。在Python 2中,我们没有bytes
,因此它只接受str
。
答案 1 :(得分:15)
确保"键"和" msg"是一个字符串。如:
s = hmac.new(str(secretkey),str(message),digestmod = hashlib.sha1).hexdigest()
答案 2 :(得分:1)
由于我不想在我们的API文档中写入您应该在比较摘要之前将有效负载转换为ASCII或删除Unicode字符,我使用了以下解决方案:
import hmac
import hashlib
def sign_request(self, secret, data):
return hmac.new(
key=bytearray(secret, 'utf-8'),
msg=bytearray(data, 'utf-8'),
digestmod=hashlib.sha256
).hexdigest()
bytearray
使用utf-8
编码将我的unicode字符串转换为字节。key
和msg
是字节参数(如hmac
库所期待的那样。)答案 3 :(得分:1)
在python 2中
如果您将其编码为:
from __future__ import unicode_literals
import base64
import hashlib
import hmac
import time
def gen_signature(key, strsome, expires=0):
expires = int(time.time()) + 600 if expires == 0 else expires
_2_signature = '%s\n%s\n' % (expires, strsome)
# hmac.new(key, msg, digestmod) bytearray(secret, 'utf-8')
signature = base64.b64encode(hmac.new(key, _2_signature, hashlib.sha1).digest())
return signature
gen_signature('xxxxxxx', 'strsome')
您收到的错误就像您提供的错误一样。
但是,如果您使用bytearray(key, 'utf-8')
代替原始密钥变量并使用bytearray(_2_signature, 'utf-8')
代替_2_signature变量,那么它应该可以正常工作。
例如:
def gen_signature(key, strsome, expires=0):
expires = int(time.time()) + 600 if expires == 0 else expires
_2_signature = '%s\n%s\n' % (expires, strsome)
# hmac.new(key, msg, digestmod) bytearray(secret, 'utf-8')
signature = base64.b64encode(hmac.new(bytearray(key, 'utf-8'), bytearray(_2_signature, 'utf-8'), hashlib.sha1).digest())
return signature
gen_signature('xxxxxxx', 'strsome')