如何使用 PyCrypto 解密使用 OpenSSL 加密的内容?
我有几个使用 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。这是使用上述数据的 exmaple 脚本:
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 显示的前半部分,所以我似乎走在正确的轨道上,但有两个主要问题:
- 为什么 OpenSSL 的
key
和iv
值是 PyCrypto(大概还有 AES256)允许的两倍? - 如何生成正确的值?我使用的技术取自博客,但如果 IV 始终与块大小(16 字节)匹配,则 MD5 将永远无法工作。即使我能弄清楚密钥的另一半来自哪里,PyCrypto 也会因为太长而拒绝它。
我意识到我还需要删除填充,但为了简洁起见,我省略了它。
I have several strings that were encrypted using OpenSSL. For instance:
$ echo "original string" | openssl aes-256-cbc -p -a -pass pass:secret
salt=B898FE40EC8155FD
key=4899E518743EB0584B0811AE559ED8AD9F0B5FA31B0B998FEB8453B8E3A7B36C
iv =EFA6105F30F6C462B3D135725A6E1618
U2FsdGVkX1+4mP5A7IFV/VcgRs4ci/yupMErHjf5bkT5XrcowXK7z3VyyV1l2jvy
I would like to decrypt these things using Python. I'm attempting to use PyCrypto. Here's an exmaple script using the above data:
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'
Here's the output:
salt: B898FE40EC8155FD
expected: B898FE40EC8155FD
key: 4899E518743EB0584B0811AE559ED8AD
expected: 4899E518743EB0584B0811AE559ED8AD9F0B5FA31B0B998FEB8453B8E3A7B36C
iv: 17988376b72f4a81
expected: EFA6105F30F6C462B3D135725A6E1618
decryption failed
You can see that the salt matches, and the key matches the first half of what OpenSSL shows, so I seem to be on the right track, but there are two main questions:
- Why are the values for
key
andiv
from OpenSSL twice as long as PyCrypto (and presumably AES256) allows? - How do I generate the correct values? The technique I'm using was taken from a blog, but if the IV is always supposed to match the block size (16 bytes), MD5 will never work. And even if I could figure out where the other half of the key comes from, PyCrypto would refuse it for being too long.
I realize I'll need to remove the padding as well, but I left that out for brevity.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您遇到三个问题:
以下代码应该是正确的:
You have three problems:
The following code should be correct: