【问题标题】:Inconsistency in HMAC signature generation in Python 3?Python 3 中的 HMAC 签名生成不一致?
【发布时间】:2015-06-10 16:41:40
【问题描述】:

在 python 终端中运行 create_api_signature() 方法总是返回相同的值,而在测试中运行时返回不同的值。

import hashlib
import hmac
import json

import unittest


def create_api_signature(_method, _url, _body, _timestamp, _secret_key):
    unicode_signature = _method.upper() + _url + json.dumps(_body) + str(_timestamp)

    s = hmac.new(_secret_key.encode(), unicode_signature.encode(), hashlib.sha256).hexdigest()

    return s


class MyTestCase(unittest.TestCase):
    def test_create_signature(self):
        method = 'post'
        url = 'https://api.alpha.example.com/v1/tiers'
        body = {
            "mail": "test@gmail.com",
            "mot_de_passe": "MyComplexPassword",
        }
        timestamp = 1433948791
        secret_key = 'SECRET_KEY'

        signature = create_api_signature(method, url, body, timestamp, secret_key)
        expected_signature = '136b629ac9744258cf558c2d541d563cc3ce647d91ead707ae4d42d49ade50c7'

        self.assertEqual(expected_signature, signature)


if __name__ == '__main__':
    unittest.main()

错误

Failure
Expected :'136b629ac9744258cf558c2d541d563cc3ce647d91ead707ae4d42d49ade50c7'
Actual   :'88a138592ea7eae50040655387a878d15fd4ab4ade5d7d769a36bf9300cb3f9e'
 <Click to see difference>

Traceback (most recent call last):
  File "/home/elopez/projects/portal/tests/test_services.py", line 98, in test_create_signature
    self.assertEqual(expected_signature, signature)
AssertionError: '136b629ac9744258cf558c2d541d563cc3ce647d91ead707ae4d42d49ade50c7' != '88a138592ea7eae50040655387a878d15fd4ab4ade5d7d769a36bf9300cb3f9e'
- 136b629ac9744258cf558c2d541d563cc3ce647d91ead707ae4d42d49ade50c7
+ 88a138592ea7eae50040655387a878d15fd4ab4ade5d7d769a36bf9300cb3f9e

【问题讨论】:

    标签: python-3.x hmac python-unittest hashlib


    【解决方案1】:

    我去了#python的IRC,得到了cdunklau下面的回答

    cdunklau:运行几次你就会明白为什么了

    PYTHONHASHSEED=random python3.2 -c "import json; print(json.dumps({'mail': 'value', 'mot_de_passe': 'othervalue'}))"

    cdunklau:你取决于字典的顺序

    可变性

    $ for i in {1..20}; do PYTHONHASHSEED=random python3.4 -c "import json; print(json.dumps({'mail': 'value', 'mot_de_passe': 'othervalue'}))"; done
    

    给出以下结果(注意 JSON 数据并不总是以相同的顺序):

    {"mail": "value", "mot_de_passe": "othervalue"}
    {"mot_de_passe": "othervalue", "mail": "value"}
    {"mail": "value", "mot_de_passe": "othervalue"}
    {"mot_de_passe": "othervalue", "mail": "value"}
    {"mail": "value", "mot_de_passe": "othervalue"}
    {"mot_de_passe": "othervalue", "mail": "value"}
    {"mot_de_passe": "othervalue", "mail": "value"}
    …
    

    解决方案

    改变了:

     body = {
             "mail": "test@gmail.com",
             "mot_de_passe": "MyComplexPassword",
     }
    

    序列化为二进制字符串的字典

     body = b'{"mail": "test@gmail.com", "mot_de_passe": "MyComplexPassword"}'
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-08
      • 1970-01-01
      • 1970-01-01
      • 2021-05-04
      • 2017-05-20
      • 1970-01-01
      相关资源
      最近更新 更多