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

时间:2022-02-13 20:24:27

I am having a slight problem with HMAC. When running this piece of code:

我对HMAC有轻微的问题。运行这段代码时:

signature = hmac.new(
    key=secret_key,
    msg=string_to_sign,
    digestmod=sha1,
)

I get a strange error:

我收到一个奇怪的错误:

  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

When I print string_to_sign, it is a proper string like this:

当我打印string_to_sign时,它是一个正确的字符串,如下所示:

GET
\n
\n
application/json
\n
\n
\n

What does the error mean? Is it because of new lines?

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

4 个解决方案

#1


32  

As asked I'll post this as an answer. The error that you faced is a feature of Python's HMAC. It does not accept unicode. This feature is described here.

如我所知,我会将此作为答案发布。您遇到的错误是Python HMAC的一个特性。它不接受unicode。此功能在此处描述。

HMAC is a function which works at byte level. For this reason in Python 3 it accepts only bytes. In Python 2 we don't have bytes so it accepts only str.

HMAC是一个在字节级工作的函数。出于这个原因,在Python 3中它只接受字节。在Python 2中,我们没有字节,所以它只接受str。

#2


12  

Ensure that "key" and "msg" is a string.such as:

确保“key”和“msg”是一个字符串。如:

s = hmac.new(str(secretkey), str(message), digestmod=hashlib.sha1).hexdigest()

s = hmac.new(str(secretkey),str(message),digestmod = hashlib.sha1).hexdigest()

#3


1  

Since I didn't want to write in our API docs that you should convert the payload to ASCII or drop Unicode characters before comparing digests, I've used the following solution:

由于我不想在我们的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 turns my unicode string into bytes using the utf-8 encoding.
  • bytearray使用utf-8编码将我的unicode字符串转换为字节。
  • key and msg are bytes parameters (like hmac library is expecting).
  • key和msg是字节参数(就像hmac库所期望的那样)。

#4


1  

In python 2

在python 2中

If you code it as:

如果您将其编码为:

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')

you get an error like the one you provided. However, if you use bytearray(key, 'utf-8') in place of the raw key variable and bytearray(_2_signature, 'utf-8') in place place of the _2_signature variable, it should work properly.

你得到的错误就像你提供的那样。但是,如果使用bytearray(key,'utf-8')代替原始键变量和bytearray(_2_signature,'utf-8')代替_2_signature变量,它应该可以正常工作。

For example:

例如:

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')

#1


32  

As asked I'll post this as an answer. The error that you faced is a feature of Python's HMAC. It does not accept unicode. This feature is described here.

如我所知,我会将此作为答案发布。您遇到的错误是Python HMAC的一个特性。它不接受unicode。此功能在此处描述。

HMAC is a function which works at byte level. For this reason in Python 3 it accepts only bytes. In Python 2 we don't have bytes so it accepts only str.

HMAC是一个在字节级工作的函数。出于这个原因,在Python 3中它只接受字节。在Python 2中,我们没有字节,所以它只接受str。

#2


12  

Ensure that "key" and "msg" is a string.such as:

确保“key”和“msg”是一个字符串。如:

s = hmac.new(str(secretkey), str(message), digestmod=hashlib.sha1).hexdigest()

s = hmac.new(str(secretkey),str(message),digestmod = hashlib.sha1).hexdigest()

#3


1  

Since I didn't want to write in our API docs that you should convert the payload to ASCII or drop Unicode characters before comparing digests, I've used the following solution:

由于我不想在我们的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 turns my unicode string into bytes using the utf-8 encoding.
  • bytearray使用utf-8编码将我的unicode字符串转换为字节。
  • key and msg are bytes parameters (like hmac library is expecting).
  • key和msg是字节参数(就像hmac库所期望的那样)。

#4


1  

In python 2

在python 2中

If you code it as:

如果您将其编码为:

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')

you get an error like the one you provided. However, if you use bytearray(key, 'utf-8') in place of the raw key variable and bytearray(_2_signature, 'utf-8') in place place of the _2_signature variable, it should work properly.

你得到的错误就像你提供的那样。但是,如果使用bytearray(key,'utf-8')代替原始键变量和bytearray(_2_signature,'utf-8')代替_2_signature变量,它应该可以正常工作。

For example:

例如:

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')