base64
Base 64 のエンコードとデコードは、標準モジュールを介して簡単に処理できます。
CBC モードでの AES-256 復号化と暗号化は、PyCrypto と M2Crypto の両方でサポートされています。
唯一の非標準 (そして最も困難な) 部分は、IV とパスワードからのキーの導出です。OpenSSL は、この man ページで説明されている独自のEVP_BytesToKey
機能を介してこれを行います。
同等の Python は次のとおりです。
def EVP_BytesToKey(password, salt, key_len, iv_len):
"""
Derive the key and the IV from the given password and salt.
"""
from hashlib import md5
dtot = md5(password + salt).digest()
d = [ dtot ]
while len(dtot)<(iv_len+key_len):
d.append( md5(d[-1] + password + salt).digest() )
dtot += d[-1]
return dtot[:key_len], dtot[key_len:key_len+iv_len]
key_len
は 32 で、iv_len
AES-256 の場合は 16 です。この関数は、ペイロードの復号化に使用できるキーと IV を返します。
OpenSSL は、暗号化されたペイロードの最初の 8 バイトにソルトを入れて期待します。
最後に、CBC モードの AES は、16 バイト境界に整列されたデータでのみ機能します。使用されるデフォルトのパディングは PKCS#7 です。
したがって、暗号化の手順は次のとおりです。
- ソルトとして 8 バイトのランダム データを生成します。
- 手順 1 のソルトを使用して、パスワードから AES キーと IV を取得します。
- 入力データを PKCS#7 でパディングします。
- 手順 2 のキーと IV を使用して、CBC モードで AES-256 を使用してパディングを暗号化します。
- Base64 でエンコードし、ステップ 1 のソルトを出力します。
- Base64 でエンコードし、手順 4 の暗号化されたデータを出力します。
復号化からの手順は逆です。
- 入力データを Base64 からバイナリ文字列にデコードします。
- デコードされたデータの最初の 8 バイトをソルトとして扱います。
- 手順 1 のソルトを使用して、パスワードから AES キーと IV を取得します。
- ステップ 3 の AES キーと IV を使用して、残りのデコードされたデータを復号化します。
- 結果から PKCS#7 パディングを確認して削除します。