Node.js中的AES加密与Python中的预期解密匹配

Node.js中的AES加密与Python中的预期解密匹配,python,node.js,encryption,aes,Python,Node.js,Encryption,Aes,我有以下用于解密的Python脚本: from Crypto.Cipher import AES shared_secret = raw_input('Enter crypted_shared_secret: ').strip() cipher = AES.new(shared_secret.decode('base64'), AES.MODE_ECB) blob = raw_input('Enter crypted_blob: ').strip() plain = cipher.decry

我有以下用于解密的Python脚本:

from Crypto.Cipher import AES

shared_secret = raw_input('Enter crypted_shared_secret: ').strip()
cipher = AES.new(shared_secret.decode('base64'), AES.MODE_ECB)

blob = raw_input('Enter crypted_blob: ').strip()
plain = cipher.decrypt(blob.decode('base64'))

print(plain)
我正在尝试使用该脚本,使用Node生成将生成原始
blob
的值。以下是我的尝试:

const Crypto = require('crypto');

var shared_secret = Crypto.randomBytes(32);
var cipher = Crypto.createCipher('aes-256-ecb', shared_secret);
crypted_blob = cipher.update(blob, 'utf8', 'base64') + cipher.final('base64');

我只能修改Node.js脚本,但我不确定它出了什么问题。

只有在使用共享密钥进行加密后,才需要将其编码到Base64:

var shared_secret = Crypto.randomBytes(32);
var cipher = Crypto.createCipheriv('aes-256-ecb', shared_secret, "");
crypted_blob = cipher.update(blob, 'utf8', 'base64') + cipher.final('base64');
// send `shared_secret.toString('base64')`
其他问题:

  • crypto.createCipher
    假定共享密钥是密码而不是密钥,这就是为什么它将使用错误的密钥派生(与OpenSSL兼容)
  • js的加密模块自动应用PKCS#7填充(与PKCS#5填充相同),但PyCrypto本身不应用任何填充。因此,您要么需要在Python中使用相同的unpadding,要么可以使用
    Cipher.setAutoPadding(false)禁用node.js中的填充,但您必须提供块大小的倍数(AES为16字节)的明文

安全考虑:

  • 切勿使用。它是确定性的,因此在语义上不安全。您至少应该使用随机模式,如或。最好是对密文进行身份验证,这样就不可能进行类似的攻击。这可以通过诸如GCM或EAX之类的经过身份验证的模式来实现,也可以通过一个方案来实现

只有在使用共享密钥进行加密后,才需要将其编码到Base64:

var shared_secret = Crypto.randomBytes(32);
var cipher = Crypto.createCipheriv('aes-256-ecb', shared_secret, "");
crypted_blob = cipher.update(blob, 'utf8', 'base64') + cipher.final('base64');
// send `shared_secret.toString('base64')`
其他问题:

  • crypto.createCipher
    假定共享密钥是密码而不是密钥,这就是为什么它将使用错误的密钥派生(与OpenSSL兼容)
  • js的加密模块自动应用PKCS#7填充(与PKCS#5填充相同),但PyCrypto本身不应用任何填充。因此,您要么需要在Python中使用相同的unpadding,要么可以使用
    Cipher.setAutoPadding(false)禁用node.js中的填充,但您必须提供块大小的倍数(AES为16字节)的明文

安全考虑:

  • 切勿使用。它是确定性的,因此在语义上不安全。您至少应该使用随机模式,如或。最好是对密文进行身份验证,这样就不可能进行类似的攻击。这可以通过诸如GCM或EAX之类的经过身份验证的模式来实现,也可以通过一个方案来实现

我还是无法让它工作。我已经削减了RSA代码,这是工作,AES的一部分,似乎不工作。如果我打开node,从
blob='Hello world'
开始,然后运行4行代码,我会得到例如
fh1hdhhh49ugiwzhnctg5dw==
as
crypted_blob
。然后我可以运行
shared\u secret.toString('base64')
并获得例如
bUQXpYLhZnR+9vKTU8txkRo7O6j7nrks1MJnxI/YIGo=
。然后我打开Python,将后者输入为
shared_secret
,将前者输入为
blob
,但我仍然得到一个加扰字符串(错误的解密)。是的,我没有注意到您在node.js中使用了错误的方法。看到我的编辑了,成功了!将研究用CBC取代ECB,谢谢提示!我还是不能让它工作。我已经削减了RSA代码,这是工作,AES的一部分,似乎不工作。如果我打开node,从
blob='Hello world'
开始,然后运行4行代码,我会得到例如
fh1hdhhh49ugiwzhnctg5dw==
as
crypted_blob
。然后我可以运行
shared\u secret.toString('base64')
并获得例如
bUQXpYLhZnR+9vKTU8txkRo7O6j7nrks1MJnxI/YIGo=
。然后我打开Python,将后者输入为
shared_secret
,将前者输入为
blob
,但我仍然得到一个加扰字符串(错误的解密)。是的,我没有注意到您在node.js中使用了错误的方法。看到我的编辑了,成功了!将研究用CBC取代ECB,谢谢提示!