Модуль hma c .new (). Digest () порта от Python 2.7 до 3.7. - PullRequest
0 голосов
/ 03 мая 2020

Я боролся с этим часами. У меня есть следующий производственный код (проанализирован для простоты), который прекрасно работает в Python 2.7:

import hashlib
import hmac

string1 = 'firststring'
string2 = 'secondstring'

digest = hmac.new(key=string1, msg=string2, digestmod=hashlib.sha256).digest()

print('hmac_digest = ' + digest) # digest is a string

Выходные данные выглядят так:

hmac_digest = �!�Ni��I.u�����x�l*>a?. �

Но когда Я запускаю это с Python3 .7, я получаю следующую ошибку:

Traceback (most recent call last):
  File "/home/xxxx/work/py23.py", line 7, in <module>
    digest = hmac.new(key=string1, msg=string2, digestmod=hashlib.sha256).digest()
  File "/usr/lib/python3.7/hmac.py", line 153, in new
    return HMAC(key, msg, digestmod)
  File "/usr/lib/python3.7/hmac.py", line 49, in __init__
    raise TypeError("key: expected bytes or bytearray, but got %r" % type(key).__name__)
TypeError: key: expected bytes or bytearray, but got 'str'

Process finished with exit code 1

После долгих исследований я понял, что hma c изменилось в 3.4 и выше. Поэтому я переделал свой код следующим образом:

import hashlib
import hmac
import base64

string1 = 'firststring'
string2 = 'secondstring'

digest = hmac.new(key=string1.encode('utf-8'), msg=string2.encode('utf-8'), digestmod=hashlib.sha256).digest()
digest = base64.encodebytes(digest).decode('utf-8') # need to convert to string

print('hmac_digest = ' + digest)

Но вывод, который я получаю, совершенно другой!

hmac_digest = 5CEZhgMDTmmFxkkudbGPxaLSytl4+gdsKj4PYT8uAJk=

Как правильно перенести этот код на python3 .7 так Я получаю точно такой же вывод, как 2.7?

Заранее спасибо!

Ответы [ 2 ]

0 голосов
/ 03 мая 2020

Спасибо Джо sh Ли за его ответ в UnicodeDecodeError, недопустимый байт продолжения

Его предложение об использовании 'latin-1' для декодирования выходных данных дайджеста решило проблему для меня !

Вот как теперь мой код выглядит в Python 3.7 и дает мне тот же вывод, что и мой код в Python 2.7:

import hashlib
import hmac

string1 = 'firststring'.encode('utf-8') # can use 'latin-1'
string2 = 'secondstring'.encode('utf-8') # can use 'latin-1' 

digest = hmac.new(key=string1, msg=string2, digestmod=hashlib.sha256).digest()

print('hmac_digest = ' + digest.decode('latin-1')) # Use only 'latin-1' to decode because 'utf-8' or 'ascii' will throw a UnicodeDecodeError
0 голосов
/ 03 мая 2020

Проблема, с которой вы столкнулись, заключается в том, что в Python 2 строки по сути являются просто байтами, в то время как в Python 3 строки являются строками Unicode, а для необработанных байтов существует новый тип данных bytes. Вы можете прочитать больше о проблемах, связанных с Python 3 руководством по портированию (и в других местах).

Минимальный набор изменений для обеспечения работы вашего кода, вероятно, выглядит примерно так:

import hashlib
import hmac

string1 = 'firststring'.encode('utf-8')
string2 = 'secondstring'.encode('utf-8')

digest = hmac.new(key=string1, msg=string2, digestmod=hashlib.sha256).digest()

print('hmac_digest = ' + repr(digest)) # digest is a string

Будет выведено:

hmac_digest = b'\xe4!\x19\x86\x03\x03Ni\x85\xc6I.u\xb1\x8f\xc5\xa2\xd2\xca\xd9x\xfa\x07l*>\x0fa?.\x00\x99'

Мы распечатываем repr() hma c, потому что это просто набор байтов. Если вы действительно хотите распечатать это, вы обычно конвертируете его в шестнадцатеричную строку:

digest = hmac.new(key=string1, msg=string2, digestmod=hashlib.sha256).hexdigest()

, что приведет к:

hmac_digest = 'e421198603034e6985c6492e75b18fc5a2d2cad978fa076c2a3e0f613f2e0099'
...