LoginSignup
14
17

More than 5 years have passed since last update.

【Python】pycryptoで投げるたけでAES暗号化復号してくれる関数作った。

Last updated at Posted at 2017-05-29

できること

・平文・パスワード・ベクトルを引数に入れて実行するとbase64形式で暗号化されたデータを返す。
・同様に平文をbase64形式で暗号化されたデータに差し替えて実行すると平文を返す。

AES暗号化の条件

鍵は16バイト,24バイト,32バイトのうちのいずれかの長さにしなければならない。
平文は16バイトの倍数の長さにしなければならない。
ivを使用して、推測されにくくする。
ivに関しては一つのアプリケーションに対して同一のものを使うのが適切かと思います。

コピペして使っても大丈夫だとは思うが、AESの理解が完全ではないため正しいコードかは保証できない。
脆弱性があるならコメントでご指摘をお願いします。

インストールは

$ pip install pycrypto

暗号化

get_encrypt_data.py

from Crypto.Cipher import AES
import hashlib
import base64

def get_encrypt_data(raw_data, key, iv):
    raw_data_base64 = base64.b64encode(raw_data)
    # 16byte
    if len(raw_data_base64) % 16 != 0:
        raw_data_base64_16byte = raw_data_base64
        for i in range(16 - (len(raw_data_base64) % 16)):
            raw_data_base64_16byte += "_"
    else:
        raw_data_base64_16byte = raw_data_base64
    secret_key = hashlib.sha256(key).digest()
    iv = hashlib.md5(iv).digest()
    crypto = AES.new(secret_key, AES.MODE_CBC, iv)
    cipher_data = crypto.encrypt(raw_data_base64_16byte)
    cipher_data_base64 = base64.b64encode(cipher_data)
    return cipher_data_base64

引数に平文データ。鍵。ベクトル。
まず最初にbase64に変える(2バイト文字でも画像でもokにするため)
次に暗号化文は16ビットの倍数にしなければならないため、
基本的にbase64で使用しない"_"をケツに補完して16ビットの倍数に直す。
16バイトの倍数ならそのまま
鍵をsha256で32ビット長に変える。
ベクトルをMD5で16ビット長に変える。
暗号化して、送信しやすいようにbase64に変換してし返す。

復号

get_decrypt_data.py

from Crypto.Cipher import AES
import hashlib
import base64

def get_decrypt_data(cipher_data_base64, key, iv):
    cipher_data = base64.b64decode(cipher_data_base64)
    secret_key = hashlib.sha256(key).digest()
    iv = hashlib.md5(iv).digest()
    crypto = AES.new(secret_key, AES.MODE_CBC, iv)
    raw_data_base64_16byte = crypto.decrypt(cipher_data)
    raw_data_base64 = raw_data_base64_16byte.split("_")[0]
    raw_data = base64.b64decode(raw_data_base64)
    return raw_data

引数にbase64に変換された暗号データ。鍵。ベクトル。
まず最初にbase64に変換された暗号データを暗号データに直す。
次に鍵をsha256で32ビットに変える。
復号して、split("_")[0]で有効なbase64だけを取り出して変換後リターンで返す。

実行結果

main.py
if __name__ == "__main__":
    message = "114514"
    password = "This is password"
    iv = "hoge"
    encrypt_data = get_encrypt_data(message, password, iv)
    print encrypt_data
    decrypt_data = get_decrypt_data(encrypt_data, password, iv)
    print decrypt_data
cmd.sh
$ r64FMFs04APfNQo2d6uFpQ==
$ 114514
14
17
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
17