web-dev-qa-db-ja.com

Python3およびhmac。バイナリではない文字列を処理する方法

Python2のスクリプトがあり、それがうまく機能していました。

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

データはjson.dumpsの出力でした。

ここで、Python 3で同じ種類のコードを実行しようとすると、次のようになります。

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'

キーを次のようにバイトに変換するようなことをしようとすると:

bytes('key')

私は得る

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

Python 3.のエンコーディングを理解するのにまだ苦労しています。

32

バイトリテラルを使用できます:b'key'

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

それに加えて、dataもバイトであることを確認してください。たとえば、ファイルから読み取る場合、ファイルを開くときにbinaryモード(rb)を使用する必要があります。

31
falsetru

古い質問を復活させるのではなく、私はこの答えに欠けていると感じたものを追加したかったのですが、他の場所の適切な説明/例を見つけるのに苦労しました:

OP Aquiles Carattinoは、文字列をバイトに変換する試みにかなり近かったが、2番目の引数、バイトに変換される文字列のエンコードが欠落していた。

誰かが静的割り当て以外の方法(構成ファイルやDBからの読み取りなど)で文字列をバイトに変換したい場合、次のように動作します。

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