PythonのCryptoでの暗号化時のエラー、cannot be passed to C codeを解決する方法
結論
・原因
AES.new()
に渡す引数が文字列だったこと
・解決策
AES.new()
に引数を渡す際に、encode()
でバイト型に変換する
動画
環境
・Python 3.9
・PyCryptodome 3.12.0
・VSCode 1.63.2
発生した問題
PyCryptodomeモジュールを使用して暗号化しようとしたら、AES.new()
の時点で以下のエラーが発生しました。
Object type <class 'str'> cannot be passed to C code
エラーが発生したコードは以下の通りです。
import string
import random
from Crypto.Cipher import AES
key = ''.join(
random.choice(string.ascii_letters) for _ in range(AES.block_size)
)
iv = ''.join(
random.choice(string.ascii_letters) for _ in range(AES.block_size)
)
plaintext = "Hello World"
cipher = AES.new(key, AES.MODE_CBC, iv) #ここでエラー
padding_length = AES.block_size - len(plaintext) % AES.block_size
plaintext += chr(padding_length) * padding_length
cipher_text = cipher.encrypt(plaintext.encode())
print(cipher_text)
解決策
AES.new(key, AES.MODE_CBC, iv)
のkey
とiv
をencode()
でバイト型に変換します。
import string
import random
from Crypto.Cipher import AES
key = ''.join(
random.choice(string.ascii_letters) for _ in range(AES.block_size)
)
key = key.encode() #ここで変換
iv = ''.join(
random.choice(string.ascii_letters) for _ in range(AES.block_size)
)
iv = iv.encode() #ここで変換
plaintext = "Hello World"
cipher = AES.new(key, AES.MODE_CBC, iv)
padding_length = AES.block_size - len(plaintext) % AES.block_size
plaintext += chr(padding_length) * padding_length
cipher_text = cipher.encrypt(plaintext.encode())
print(cipher_text)
実行結果
b'l\x99ZU~"\xeb\x05\x945\xee\x9a9\xd2\xce\xc1
エラーについてちょっと調べたみた
どうやら以前までのPyCryptoモジュールでは文字列でもよかったようなのですが、現在は非推奨となっているようです。
現在はPyCryptodomeモジュールが推奨されており、こちらでは文字列ではエラーになるため、バイト型への変換が必要なようです。
pycryptoを使ったデータの暗号化に失敗する
以下はpycrypto 2.6.1のドキュメントに記載されているサンプルですが、AES.new()
に文字列を渡しています。
>>> from Crypto.Cipher import AES
>>> obj = AES.new('This is a key123', AES.MODE_CBC, 'This is an IV456')
>>> message = "The answer is no"
>>> ciphertext = obj.encrypt(message)
>>> ciphertext
'\xd6\x83\x8dd!VT\x92\xaa`A\x05\xe0\x9b\x8b\xf1'
一方、PyCryptodomeモジュールの公式ドキュメントには、以下のように、key
とiv
はbytes
型と記載があります。
Parameters:
key (bytes) – the cryptographic key
mode – the constant Crypto.Cipher.<algorithm>.MODE_CBC
iv (bytes) – the Initialization Vector. A piece of data unpredictable to adversaries. It is as long as the block size (e.g. 16 bytes for AES). If not present, the library creates a random IV value.
推奨モジュールが変わったことで、引数の型も変わっていたことが原因でした。
まとめ
今回は、PythonのCryptoでの暗号化時のエラー、cannot be passed to C code
を解決する方法を紹介しました。
AES.new()
に渡す引数の型が、文字列だったことが原因だったため、バイト型に変換することで解決しました。
どなたかの参考になれば幸いです。
Discussion