openssl-aes-128-ecb加密不';t match python Crypto.Cipher AES加密

openssl-aes-128-ecb加密不';t match python Crypto.Cipher AES加密,python,encryption,openssl,cryptography,Python,Encryption,Openssl,Cryptography,我正在尝试使用密码为“黄色潜水艇”的AES-128加密16字节的字符串“黎明攻击!!” 在python中: from Crypto.Cipher import AES from base64 import b64encode plaintext = 'Attack at dawn!!' obj = AES.new("yellow submarine", AES.MODE_ECB) ciphertext = obj.encrypt(plaintext) print(b64encode(ciph

我正在尝试使用密码为“黄色潜水艇”的AES-128加密16字节的字符串“黎明攻击!!”

在python中:

from Crypto.Cipher import AES
from base64 import b64encode

plaintext = 'Attack at dawn!!'
obj = AES.new("yellow submarine", AES.MODE_ECB)
ciphertext = obj.encrypt(plaintext)

print(b64encode(ciphertext).decode())
这使得密文为“kBKTLPWpU7Dpf/TiGo6p3w==”

现在在终端中使用openssl。plain.txt是一个文本文件,包含字符串“拂晓时攻击!!”:

openssl enc -aes-128-ecb -nosalt -nopad -pass pass:"yellow submarine" -in plain.txt -out cipher.txt -a
这将返回“X+fHjd97VRZLbH+BCgu6Xw==”作为密文

为什么它们不一样


我试过阅读文档或示例,但在互联网上没有发现任何有用的东西。我已尝试更改openssl命令中的选项。我不知道如何处理这个问题

在python中,使用Crypto.Cipher中的AES进行加密。Cipher接受一个密钥(16字节的字符串)和一个明文(16字节),并输出一个密文(16字节)

要使用OpenSSL实现同样的功能,首先需要使用
-nosalt
-nopad
禁用satting和padding,以确保它接受16字节的输入并返回16字节的输出。提供密码会导致OpenSSL派生自己的密钥。要覆盖此选项,请使用
-K
选项(其中键需要以十六进制表示)。或者,输入密码并指定
-p
将使OpenSSL吐出它使用的密钥

  • 使用“黄色潜水艇”键:
蟒蛇

from Crypto.Cipher import AES
from base64 import b64encode

plaintext = 'Attack at dawn!!'
obj = AES.new("yellow submarine", AES.MODE_ECB)
ciphertext = obj.encrypt(plaintext)

print(b64encode(ciphertext).decode())
openssl

enc -aes-128-ecb openssl enc -aes-128-ecb -nosalt -nopad -K 79656c6c6f77207375626d6172696e65 -in plain.txt -out cipher.txt -a
这为两种方法提供了“kBKTLPWpU7Dpf/TiGo6p3w==”

  • 使用OpenSSL密码“黄色潜水艇”:

    openssl enc-aes-128-ecb-nosalt-nopad-p-pass:“黄色潜艇”-in plain.txt-out cipher.txt-a

这会将钥匙输出为“A35EC217E15C1DD2582201A184814897C”。要将其用于Crypto.Cipher,我们首先需要将其转换为十六进制

from Crypto.Cipher import AES
from base64 import b64encode

hex_key = 'A35EC217E15C1DD258201A184814897C'
key = bytes.fromhex(hex_key)

plaintext = 'Attack at dawn!!'
obj = AES.new(key, AES.MODE_ECB)
ciphertext = obj.encrypt(plaintext)

print(b64encode(ciphertext).decode())
这两种方法都给出了“X+fHjd97VRZLbH+BCgu6Xw==”

  • 回答最后一个问题:您应该更仔细地阅读OpenSSL enc手册,并发现了
    -p
    -p
    -k
    选项

为什么它们应该相同?openssl使用专有的密钥派生算法将密码转换为密钥和IV,pycrypto还做了其他事情。如果使用
-P
选项,您可以看到衍生密钥和IV是什么。在你的pycrypto代码中使用它们。天真的,我认为密码和密钥是一样的。很明显,我没有仔细阅读手册,因为正如你所说的
-P
会吐出实际的钥匙(如果模式使用,则会吐出IV)。还有
-K
,可以直接使用钥匙。@JamesKPolk谢谢!这解决了我的困惑。