密码不是密钥。Openssl使用^{}从密码和salt中创建一个适当的密钥(如果需要,可以使用IV)。在
正如jameskpolk在一篇评论中提到的,您可以使用-p(或-p)选项告诉Openssl打印密钥(以十六进制表示),然后可以传递给它密码密码. 或者,您可以在Python中实现EVP_BytesToKey,如下所示。这是EVP_BytesToKey的简化版本,不使用salt,count参数的默认值为1。在
正如EVP_BytesToKey文档的状态一样,这是一个相当弱的密码派生函数。正如hashlib docs所提到的,现代密码派生通常会执行数十万次哈希运算,从而使密码哈希攻击非常缓慢。在
我们还需要一个函数来从解密的数据字节中删除PKCS7 padding。下面的unpad函数只是假设填充数据是有效的。在实际软件中,unpad函数必须验证填充的数据是否有效,以防止基于填充的攻击。我的unpad函数还假定数据已编码为UTF-8字节,并将未添加的数据解码为文本。在from __future__ import print_function
from Crypto.Cipher import AES
from base64 import b64decode
from hashlib import md5
def evp_simple(data):
out = ''
while len(out) < 32:
out += md5(out + data).digest()
return out[:32]
def unpad(s):
offset = ord(s[-1])
return s[:-offset].decode('utf-8')
iv = 'a2a8a78be66075c94ca5be53c8865251'.decode('hex')
passwd = '00112233445566778899aabbccddeeff'
key = evp_simple(passwd)
print('key', key.encode('hex'))
aes = AES.new(key, AES.MODE_CBC, IV=iv)
data = b64decode('pt7DqtAwtTjPbTlzVApucQ==')
raw = aes.decrypt(data)
print(repr(raw), len(raw))
plain = unpad(raw)
print(repr(plain), len(plain))
输出
^{pr2}$
这些代码不能在python3上运行,所以这里有一个python3版本。在from Crypto.Cipher import AES
from base64 import b64decode
from hashlib import md5
def evp_simple(data):
out = b''
while len(out) < 32:
out += md5(out + data).digest()
return out[:32]
def unpad(s):
offset = s[-1]
return s[:-offset].decode('utf-8')
iv = bytes.fromhex('a2a8a78be66075c94ca5be53c8865251')
passwd = b'00112233445566778899aabbccddeeff'
key = evp_simple(passwd)
aes = AES.new(key, AES.MODE_CBC, IV=iv)
data = b64decode('pt7DqtAwtTjPbTlzVApucQ==')
raw = aes.decrypt(data)
print(repr(raw), len(raw))
plain = unpad(raw)
print(repr(plain), len(plain))
输出b'hello world\n\x04\x04\x04\x04' 16
'hello world\n' 12