使用 AES-256 加密,如 OpenSSL 和 PyCrypto

Pet*_*tru 1 python encryption cryptography pycrypto

我正在尝试使用 AES-256 和带有 base64 的 Python 加密时间戳。使用以下命令生成输出的 OpenSSL 等效项:

openssl enc -aes256 -pass pass:'1Lw2*kx18#AvNuij*iRL1nY1UA_#k8$+' -nosalt -base64 <<< "1489355323"
Run Code Online (Sandbox Code Playgroud)

我的python代码如下所示:

import time
from base64 import b64encode
from Crypto.Cipher import AES

key = '1Lw2*kx18#AvNuij*iRL1nY1UA_#k8$+'
timestamp = "1489355323"

BS = 16
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)
iv = "\x00" * 16

aes = AES.new(key, AES.MODE_CBC, iv)
ciphertext = aes.encrypt( pad( timestamp ) )

print b64encode(ciphertext)
Run Code Online (Sandbox Code Playgroud)

目前输出不同,我需要获得与 OpenSSL 命令相同的输出。知道我做错了什么吗?

mat*_*att 5

OpenSSLenc命令使用的密钥和 iv 是由EVP_BytesToKey函数从密码派生的。您将需要重现该函数以使您的代码以相同的方式运行。

在 Python 中,它可能看起来像:

from hashlib import md5

# ...

last = ''
bytes = ''

# 32 byte key (256 bits) + 16 byte IV = 48 bytes needed
while len(bytes) < 48:
    last = md5(last + password).digest()
    bytes += last

key = bytes[0:32]
iv = bytes[32:48]

# ...

aes = AES.new(key, AES.MODE_CBC, iv)
ciphertext = aes.encrypt( pad( timestamp ) )
Run Code Online (Sandbox Code Playgroud)

不再真正推荐这种方案,但该enc命令仍然使用它。我相信 OpenSSL 正在考虑在未来提供更新的密钥派生函数。

您还需要注意换行符。here 字符串 ( <<<)在字符串的末尾添加一个换行符,您需要将其添加到要加密的字符串中以获得相同的结果:

timestamp = "1489355323\n"
Run Code Online (Sandbox Code Playgroud)

  • +1另外请注意,您可以将“-P”选项添加到“openssl enc”以查看它为特定命令派生的密钥和IV。 (2认同)