【问题标题】:Python HMAC: TypeError: character mapping must return integer, None or unicodePython HMAC:TypeError:字符映射必须返回整数、无或 unicode
【发布时间】:2013-12-31 00:21:54
【问题描述】:

我在使用 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

错误是什么意思?是因为换行吗?

【问题讨论】:

  • 看看here.
  • @Faust 谢谢。您可以将其发布为答案吗?我使用 django.utils.encoding.smart_bytes 将 unicode 转换为字节字符串,然后它就可以工作了。

标签: python


【解决方案1】:

如被问及,我会将其发布为答案。 您遇到的错误是 Python 的 HMAC 的 feature。它不接受 unicode。 此功能描述为here

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      由于我不想在我们的 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 库所期望的那样)。

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-03-27
          • 2012-05-09
          • 2015-10-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-11-11
          • 2019-03-23
          相关资源
          最近更新 更多