元セブ島在住のエンジニアの僕「Tommy」が、プログラミング・英語・セブ事情を発信するブログ

Tommy's blog

【Python】AES形式で暗号化と復号化する【→セキュリティ強化】

9月 11, 2019

プログラム女子
Pythonの処理で、パスワードなどを扱いたいんだけど、パスワードをそのまま扱うのってセキュリティ上どうなのかな...
その場合は、パスワードを暗号化して処理する方法もあるよ。ここでは、AESを使った暗号化と、暗号化をもとに戻す復号化の方法について説明するね。
Tommy

この記事で分かること

  • AES形式で変数を暗号化する方法が分かる
  • AES形式で変数を復号化する方法が分かる

Pythonを使ったAES形式で暗号化と復号化する概要

この記事では、Pythonを使った暗号化と復号化の方法を説明します。暗号化とは、あるデータの内容を他人にわからないようにする処理のことです。対して、復号化とは、暗号化されたデータを元に(平文に)戻すことを言います。

これによって、パスワードなどAESを使った暗号化を行い保存しておき、処理内でパスワードを使用する際には復号化してパスワードをしようするといった使い方ができるようになります。

Pythonを使ったAES形式で暗号化と復号化する前提の環境

AES形式で暗号化と復号化する前提の環境は、下の記事で説明している私の環境と同じ環境で確認しています。

また、レンタルサーバなどのLinuxサーバを使っている場合は、下の記事でプログラミングする環境の作り方を説明しています。もし、まだプログラムする環境ができていない方は、先にこちらの記事を読んで、プログラミングできる環境をつくることをおすすめします。

Pythonを使ったAES形式で暗号化と復号化するサンプルプログラム

ここでは、AES形式の暗号化と復号化を行うサンプルプログラムを作成する手順を説明します。このサンプルプログラムは、具体的に次のような順番でそれぞれの関数の定義と定義した関数の実行によって動作します。

  1. ライブラリのインポート
  2. AESを作成する関数の定義
  3. 暗号化する関数の定義
  4. 復号化する関数の定義
  5. 定義した関数の実行

1.ライブラリのインポート

まず初めに、各種ライブラリをインポートします。AESを用いた暗号化・復号化に必要なCryptoライブラリを各種モジュールをインポートしています。

from Crypto.Cipher import AES
from Crypto.Hash import SHA256
from Crypto import Random

  1. ライブラリ「Crypto.Cipher」からモジュール「AES」をインポートする。
  2. ライブラリ「Crypto.Hash」からモジュール「SHA256」をインポートする。
  3. ライブラリ「Crypto」からモジュール「Random」をインポートする。

2.AESを作成する関数の定義

次に、暗号化(AES)オブジェクトを作成する手順を説明します。関数「AES.new」に引数としては、次の3つのパラメータを入力しています。

  • key(暗号化鍵)
  • AES.MODE_CFB(暗号化アルゴリズム)
  • iv(初期化ベクタ)

暗号化鍵には、パスワードをSHA256でハッシュした値(256bit)を鍵として利用しています。また、アルゴリズムを指定する引数としてAES.MODE_CFBを指定しています。初期化ベクタは、乱数生成におけるシード値のようなものです。

def create_aes(password, iv):
	sha = SHA256.new()
	sha.update(password.encode())
	key = sha.digest()
	return AES.new(key, AES.MODE_CFB, iv)

  1. 関数「create_aes」を定義宣言する。
  2. 変数「sha」を関数「SHA256.new」で生成されるオブジェクト(インスタンス)で初期化する。
  3. 関数「sha.update」でbytes-like オブジェクトに変換する。
  4. 変数「key」を関数「sha.digest」から出力される暗号化鍵で初期化する。
  5. 関数「AES.new」で生成されるオブジェクト(インスタンス)を関数「create_aes」の戻り値として返却する。

3.暗号化する関数の定義

次に、暗号化する関数を定義し、暗号化の手順を説明します。暗号化は、関数「Random.new」によって生成された初期化ベクタ「iv」を生成する作業と、初期化ベクタ「iv」を使ってAESを作る作業、AESオブジェクトの関数「encrypt」を呼び出す作業の3つの作業によって暗号化を行います。

def encrypt(decrypted_data, password):
	iv = Random.new().read(AES.block_size)
	return iv + create_aes(password, iv).encrypt(decrypted_data)

  1. 関数「encrypt」を定義宣言する。
  2. 変数「iv」を関数「Random.new」によって生成される初期化ベクトルで初期化する。
  3. 変数「iv」と関数「create_aes」からの戻り値を関数「encrypt」の戻り値として返却する。

4.復号化する関数の定義

次に、復号化する関数を定義し、復号化の手順を説明します。入力された暗号化されたデータが入った変数「encrypted_data」から、初期化ベクタ「iv」と本文のデータ「cipher」に分離します。得られた初期化ベクタ「iv」と本文のデータ「cipher」と復号化の為にパスワード「password」を使って関数「decrypt」を呼び出すことによって復号化を行います。

def decrypt(encrypted_data, password):
	iv, cipher = encrypted_data[:AES.block_size], encrypted_data[AES.block_size:]
	return create_aes(password, iv).decrypt(cipher)

  1. 関数「decrypt」を定義宣言する。
  2. 関数「decrypt」の引数で指定された変数「encrypted_data」のAES.block_size番目まで配列と、AES.block_sizeからの配列を分離して変数「iv」と「cipher」の戻り値で初期化する。
  3. 関数「create_aes」の戻り値を関数「decrypt」の戻り値として返却する。

5.定義した関数の実行

最後に、例として暗号化鍵の元になるパスワード「password」と、暗号化対象の文字列「s_strings」を題材として、上記で定義した3つの関数の呼び出しを行い、暗号化と復号化の処理を行う例をプログラムしています。

if __name__ == '__main__':

	password = "tommy1"
	s_strings = "secret tommy's sentence."

	enc = encrypt(s_strings, password)
	print(enc)

	dec = decrypt(enc, password)
	print(dec)

  1. 変数「password」を文字列「tommy1」で初期化する。
  2. 変数「s_strings」を文字列「secret tommy's sentence.」で初期化する。
  3. 引数に変数「s_strings」と「password」を指定して呼び出した関数「encrypt」からの戻り値で変数「enc」を初期化する。
  4. 変数「enc」の内容を表示する。
  5. 引数に変数「enc」と「password」を指定して呼び出した関数「decrypt」からの戻り値で変数「dec」を初期化する。
  6. 変数「dec」の内容を表示する。

Pythonで業務効率化するその他の方法

この記事では、Pythonを使った暗号化と復号化の方法を説明しました。暗号化と復号化以外にも、Pythonには、業務効率化できる手段がたくさんあります。

下記の記事に、普段オフィス環境で使われるツールを使って業務効率化できる方法をまとめていますので、ぜひ合わせて読んで取り組んでみてください。