Python HMAC:TypeError:字符映射必须返回整数,None或unicode

时间:2013-12-31 00:21:55

标签: python

我对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

错误是什么意思?是因为新线?

4 个答案:

答案 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字符串转换为字节。
  • keymsg是字节参数(如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')