48774


あるデータとパスワードを暗号化するプログラムを、pycryptoを使用して作っていたところ、以下のようなエラーが出ました。  

[code]

    File "C:\Users\******\Desktop\Python36\Python教科書\crypto-test.py", line 51, in <module>
        enc = encrypt(password, message)
      File "C:\Users\******\Desktop\Python36\Python教科書\crypto-test.py", line 30, in encrypt
        aes = AES.new(password, mode, iv)
      File "C:\Users\******\Desktop\Python36\lib\site-packages\Crypto\Cipher\AES.py", line 206, in new
        return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs)
      File "C:\Users\******\Desktop\Python36\lib\site-packages\Crypto\Cipher\__init__.py", line 79, in _create_cipher
        return modes[mode](factory, **kwargs)
      File "C:\Users\******\Desktop\Python36\lib\site-packages\Crypto\Cipher\_mode_cbc.py", line 253, in _create_cbc_cipher
        return CbcMode(cipher_state, iv)
      File "C:\Users\******\Desktop\Python36\lib\site-packages\Crypto\Cipher\_mode_cbc.py", line 96, in __init__
        c_uint8_ptr(iv),
      File "C:\Users\******\Desktop\Python36\lib\site-packages\Crypto\Util\_raw_api.py", line 196, in c_uint8_ptr
        raise TypeError("Object type %s cannot be passed to C code" % type(data))
    TypeError: Object type <class 'str'> cannot be passed to C code
    
[/code]

これはC言語かpycryptoに関することが原因なのでしょうか。ancondaをインストール済みです。

元のプログラムはこちらです。

[code]

    from Crypto.Cipher import AES
    import base64
    
    
    # 暗号化したいデータとパスワードを指定
    
    message = "自分がしてほしいと思うことをヒトのもするように。"
    password = "xxxxxxxxxx"     # 適当なパスワードを設定
    iv = "L3f4mlTJtCIPV9af"     # 初期化ベクトル(16文字で適当な値を設定)
    mode = AES.MODE_CBC     # 暗号化モードを指定
    
    
    # 特定の長さの倍数にするため空白でデータを埋める関数
    
    def mkpad(s, size):
        s = s.encode("utf-8")       # UTF-8文字列をバイト列に変換する
        pad = b' ' * (size - len(s) % size)     # 特定の長さの倍数にするための空白を生成
        return s + pad
    
    
    # 暗号化する
    
    def encrypt(password, data):
        # 特定の長さに調節する
        password = mkpad(password, 16)      # 16の倍数にそろえる
        data = mkpad(data, 16)      # バイト列に変換し16の倍数に揃える
        password = password[:16]        # ちょうど16文字に揃える
    
        # 暗号化
        aes = AES.new(password, mode, iv)
        data_cipher = aes.encrypt(data)
        return base64.b64encode(data_cipher).decode("utf-8")
    
    
    # 複合化する
    
    def decrypt(password, encdata):
        # パスワードの文字数を調整
        password = mkpad(password, 16)      # 16の倍数に揃える
        password = password[:16]        # ちょうど16文字に揃える
    
        # 複合化
        aes = AES.new(password, mode, iv)
        encdata = base64.b64decode(encdata)     # 暗号化データをBASE64でデコードしてバイト列に
        data = aes.decrypt(encdata)     # 複合化
        return data.decode("utf-8")
    
    
    # 暗号化する
    enc = encrypt(password, message)
    
    # 複合化する
    dec = decrypt(password, enc)
    
    
    # 結果を表示する
    
    print("暗号化", enc)
    print("複合化", dec)
    
[/code]

何かいい解決策があれば教えていただきたいです。お願いします。


CC BY-SA 4.0
2018-09-27T07:59:00.177
48764
2022-01-30T16:47:31.613
2022-01-30T16:47:31.613
3060
27172
question
python python3 pycrypto
pycryptoを使ったデータの暗号化に失敗する


質問文に書かれているエラーログは、PyCrypto のものではなく PyCryptodome のものに見えます。PyCryptodome
で動かすのであれば、そのための変更が必要です。

[質問者さんによる前回の質問](https://ja.stackoverflow.com/q/48749/19110)に書かれている通り現在
PyCrypto は非推奨であり、PyCryptodome への移行が推奨されています。どちらで書いても `import`
文は一緒になるため同じように使えそうですが、いくつか違いがあります。

API レベルの主な変更点は、PyCryptodome のドキュメント ["Compatibility with
PyCrypto"](https://pycryptodome.readthedocs.io/en/latest/src/vs_pycrypto.html)
に書かれています。また、[Changelog](https://pycryptodome.readthedocs.io/en/latest/src/changelog.html)
に書かれている変更点も別に注意が必要です。

更にこれ以外にも細かい変更点があるようです。たとえば metropolis
さんが[コメントでご指摘なさっている](https://ja.stackoverflow.com/questions/48764/pycrypto%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%9F%E3%83%87%E3%83%BC%E3%82%BF%E3%81%AE%E6%9A%97%E5%8F%B7%E5%8C%96%E3%81%AB%E5%A4%B1%E6%95%97%E3%81%99%E3%82%8B#comment50687_48764)ように、`Crypto.Cipher.AES.new()`
の引数 `iv` の受け付けるものが ["byte
string"](https://www.dlitz.net/software/pycrypto/api/current/Crypto.Cipher.AES-
module.html) から ["bytes, bytearray,
memoryview"](https://pycryptodome.readthedocs.io/en/latest/src/cipher/aes.html#Crypto.Cipher.AES.new)
に変わっています。今回のエラーはこの違いに由来するもので、`iv` に string を渡すと質問文に書かれたエラーが出ます。bytes
にすればよいので、たとえば

[code]

    iv = "L3f4mlTJtCIPV9af".encode('utf-8')
    
[/code]

とすればエラーを回避できます。


CC BY-SA 4.0
2018-09-27T17:11:18.740
48774
2018-09-27T17:11:18.740
19110
48764
answer