web-dev-qa-db-fra.com

Python3 et hmac. Comment gérer une chaîne qui n'est pas binaire

J'avais un script en Python2 qui fonctionnait très bien.

def _generate_signature(data):
   return hmac.new('key', data, hashlib.sha256).hexdigest()

Où les données étaient la sortie de json.dumps.

Maintenant, si j'essaie d'exécuter le même type de code dans Python 3, j'obtiens ce qui suit:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.4/hmac.py", line 144, in new
    return HMAC(key, msg, digestmod)
  File "/usr/lib/python3.4/hmac.py", line 42, in __init__
    raise TypeError("key: expected bytes or bytearray, but got %r" %type(key).__name__)
TypeError: key: expected bytes or bytearray, but got 'str'

Si j'essaye quelque chose comme transformer la clé en octets comme ceci:

bytes('key')

Je reçois

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: string argument without an encoding

J'ai encore du mal à comprendre les encodages dans Python 3.

32
Aquiles Carattino

Vous pouvez utiliser des octets littéraux: b'key'

def _generate_signature(data):
    return hmac.new(b'key', data, hashlib.sha256).hexdigest()

En plus de cela, assurez-vous que data est également en octets. Par exemple, s'il est lu à partir d'un fichier, vous devez utiliser le mode binary (rb) lors de l'ouverture du fichier.

31
falsetru

Pour ne pas ressusciter une vieille question, mais je voulais ajouter quelque chose qui me semble manquer dans cette réponse, à laquelle j'ai eu du mal à trouver une explication/un exemple approprié ailleurs:

OP Aquiles Carattino était assez proche de sa tentative de conversion de la chaîne en octets, mais manquait le deuxième argument, le codage de la chaîne à convertir en octets.

Si quelqu'un souhaite convertir une chaîne en octets par un autre moyen que l'affectation statique (comme la lecture d'un fichier de configuration ou d'une base de données), ce qui suit devrait fonctionner:

import hmac, hashlib

def _generate_signature(data):
  key = 'key' # Defined as a simple string.
  key_bytes= bytes(key , 'latin-1')
  data_bytes = bytes(data, 'latin-1') # Assumes `data` is also a string.
  return hmac.new(key_bytes, data_bytes , hashlib.sha256).hexdigest()

print(
  _generate_signature('this is my string of data')
)
22
Joshua Burns