OpenSSL を使用して暗号化された文字列がいくつかあります。例えば:
$ echo "original string" | openssl aes-256-cbc -p -a -pass pass:secret
salt=B898FE40EC8155FD
key=4899E518743EB0584B0811AE559ED8AD9F0B5FA31B0B998FEB8453B8E3A7B36C
iv =EFA6105F30F6C462B3D135725A6E1618
U2FsdGVkX1+4mP5A7IFV/VcgRs4ci/yupMErHjf5bkT5XrcowXK7z3VyyV1l2jvy
Pythonを使用してこれらのものを解読したいと思います。PyCrypto を使用しようとしています。上記のデータを使用したスクリプトの例を次に示します。
from base64 import b64decode, b64encode
from hashlib import md5
from Crypto.Cipher import AES
secret = 'secret'
encoded = 'U2FsdGVkX1+4mP5A7IFV/VcgRs4ci/yupMErHjf5bkT5XrcowXK7z3VyyV1l2jvy'
encrypted = b64decode(encoded)
salt = encrypted[8:16]
data = encrypted[16:]
key = md5(secret + salt).hexdigest()
iv = md5(key + secret + salt).hexdigest()[0:16] # which 16 bytes?
dec = AES.new(key, AES.MODE_CBC, iv)
clear = dec.decrypt(data)
try:
salt_hex = ''.join(["%X" % ord(c) for c in salt])
print 'salt: %s' % salt_hex
print 'expected: %s' % 'B898FE40EC8155FD'
print 'key: %s' % key.upper()
print 'expected: %s' % '4899E518743EB0584B0811AE559ED8AD9F0B5FA31B0B998FEB8453B8E3A7B36C'
print 'iv: %s' % iv
print 'expected: %s' % 'EFA6105F30F6C462B3D135725A6E1618'
print 'result: %s' % clear
except UnicodeDecodeError:
print 'decryption failed'
出力は次のとおりです。
salt: B898FE40EC8155FD
expected: B898FE40EC8155FD
key: 4899E518743EB0584B0811AE559ED8AD
expected: 4899E518743EB0584B0811AE559ED8AD9F0B5FA31B0B998FEB8453B8E3A7B36C
iv: 17988376b72f4a81
expected: EFA6105F30F6C462B3D135725A6E1618
decryption failed
ソルトが一致し、キーが OpenSSL が示す前半部分と一致していることがわかります。したがって、正しい方向に進んでいるように見えますが、主な質問が 2 つあります。
- OpenSSLの値
key
とiv
OpenSSL の値が PyCrypto (およびおそらく AES256) の 2 倍の長さなのはなぜですか? - 正しい値を生成するにはどうすればよいですか? 私が使用している手法はブログから引用したものですが、IV が常にブロック サイズ (16 バイト) と一致することになっている場合、MD5 は機能しません。そして、キーの残りの半分がどこから来ているかを突き止められたとしても、PyCrypto は長すぎるという理由でそれを拒否します。
パディングも削除する必要があることはわかっていますが、簡潔にするために省略しました。