はじめに
今回はPythonを使って、AESで暗号化・復号を行います。
AESキーは、任意のパスフレーズをもとに生成します。
パスフレーズで暗号・復号を行うことにより、実戦的に使えると思います。
是非、参考にしてみてください。
Evernoteのテキスト暗号化
Evernoteにはテキスト暗号化機能があり、AESで暗号化を行っています。
その仕組みや実際のソースコードについては、以下の記事で解説していますので参考にしてみてください。
VS Codeインストール
Pythonで実装を行うにあたって、VS Codeのインストール方法は、以下の記事にまとめましたのでご覧ください。
VS Codeのオススメ設定や拡張機能などは、以下の記事にまとめました。
暗号化の仕組み
今回はAESで暗号化します。
Advanced Encryption Standard (AES) は、アメリカが2001年に標準暗号として定めた共通鍵暗号アルゴリズムである。アメリカ国立標準技術研究所(NIST)が公募し、Rijndael(ラインダール)がAESとして採用された。
https://ja.wikipedia.org/wiki/Advanced_Encryption_Standard
Evernoteの仕組みも同じですが、今回は以下のように暗号化・復号を行う実装をします。
また暗号化を行う際に、毎回同じ値にならないように対応します。
(ソルト・初期ベクトル)
実装
PyCryptodome
Pythonで暗号・復号しますが、ライブラリにPyCryptodomeを使用します。
pipコマンドでインストールします。
pip install pycryptodome
暗号化
ソルトと初期ベクトルをランダムに生成します。
from Crypto.Random import get_random_bytes
salt = get_random_bytes(16)
iv = get_random_bytes(16)
PBKDF2を使用して、AESキーを生成します。
passPhrase = "password123"
...
# AESキーの生成(128bit、5万回)
key = pbkdf2_hmac('sha256', bytes(passPhrase, encoding='utf-8'), salt, 50000, int(128 / 8))
生成したAESキーを使い、AES(128bit)で暗号化します。
# 暗号
aes = AES.new(key, AES.MODE_CBC, iv)
data = Padding.pad(targetText.encode('utf-8'), AES.block_size, 'pkcs7')
encrypted = aes.encrypt(data)
print(encrypted)
暗号化されたテキストは以下のように表示されました。
b'_[\x87\x89\xfd(\xb4\xe5q\x10@\x18\xa8\x9fU\xd7\xb4\x89 \xffVVFN\xed\xf9\x7f+Fc\x16\x17'
復号
今度は復号を行います。
復号するためには、暗号化する際に使用した以下の情報が必要です。
AESキーの生成は暗号化と同じで、パスフレーズをもとに行います。
passPhrase = "password123"
...
# AESキーの生成(128bit、5万回)
key = pbkdf2_hmac('sha256', bytes(passPhrase, encoding='utf-8'), salt, 50000, int(128 / 8))
AESキーと初期ベクトルを使い、復号できます。
# 復号
aes = AES.new(key, AES.MODE_CBC, iv)
plaintext = aes.decrypt(encrypted)
print(plaintext.decode(encoding='utf-8'))
全容
暗号と復号の処理を分けて実装しました。
ポイントなのは、暗号化に使用した情報をもとに復号する必要があります。
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from Crypto.Util import Padding
from hashlib import pbkdf2_hmac
# 暗号
def encrypt(text, passPhrase):
salt = get_random_bytes(16)
iv = get_random_bytes(16)
# AESキーの生成(128bit、5万回)
key = pbkdf2_hmac('sha256', bytes(passPhrase, encoding='utf-8'), salt, 50000, int(128 / 8))
# 暗号
aes = AES.new(key, AES.MODE_CBC, iv)
data = Padding.pad(text.encode('utf-8'), AES.block_size, 'pkcs7')
encrypted = aes.encrypt(data)
return {
'salt': salt,
'iv': iv,
'encrypted': encrypted
}
# 復号
def decrypt(encryptedData, passPhrase):
# AESキーの生成(128bit、5万回)
key = pbkdf2_hmac('sha256', bytes(passPhrase, encoding='utf-8'), encryptedData['salt'], 50000, int(128 / 8))
# 復号
aes = AES.new(key, AES.MODE_CBC, encryptedData['iv'])
plaintext = aes.decrypt(encryptedData['encrypted'])
return plaintext.decode(encoding='utf-8')
targetText = "暗号化したいテキスト"
passPhrase = "password123"
# 暗号化
encryptedData = encrypt(targetText, passPhrase)
# 復号
decrypted = decrypt(encryptedData, passPhrase)
print(decrypted)
TXT-Crypter
今回解説した仕組みと同じですが、暗号・復号を簡単に行うことができるサービスを作成しました。
Notionを使ってパスワード管理を行う例は、以下の記事を参考にしてください。
さいごに
今回はPythonを使って、AESで暗号化・復号を行いました。
暗号・復号の仕組みについて参考にしてみてください。
コメント