我写这个问答是因为我很挣扎(可能是因为缺乏经验),在使用node或python加密/解密事物的许多不同方式中迷失了方向。
我想也许我的案子将来能帮助到人们。
我需要做的:
- 从表单中获取数据,使用Crypto(node-js)对其进行加密
- 在Python中传递加密数据,并使用PyCrypto对其进行解密
我选择使用AES加密。
以下是我开始的方式(我不会经历我尝试过的一切):
-
我遵循了本页末尾的示例
在我的案例中:
(这可能是javascript和coffeescript之间非常糟糕的混合)
crypto = require "crypto" [...] key = "mykeywhatever" cipher = crypto.createCipher('aes192', key) cipher.update('string i want to encode', 'binary', 'hex') encoded_string = cipher.final('hex') [...]
这对我的字符串进行编码非常有效。
-
然后,我编写了python脚本来解密这个字符串,使用PyCrypto的github页面上的自述文件:
from Crypto.Cipher import AES [...] my_string = data_coming_from_rabbitmq obj = AES.new('mykeywhatever', AES.MODE_CBC) obj.decrypt(ciphertext) [...]
这显然不起作用:在自述中有一个IV,但既然我在节点脚本中没有给出,为什么我要在python中给出呢?
经过更多的谷歌搜索,我了解到节点的Crypto使用OpenSSL,而PyCrypto显然没有。所以我查了一下,发现了那些页面:
- 如何使用PyCrypto解密使用OpenSSL加密的内容
- AES在PyCrypto&Node.JS加密
- 还有更多
所以事情变得复杂了,没有人做同样的事情来解密数据,我迷路了,请求帮助。
答案是我和我的同事想出的(嗯,主要是我的同事)。
所以我们从"如何解密…OpenSSL"的答案开始。
-
我们需要修改加密脚本,它给出:
crypto = require "crypto" [...] var iv = new Buffer('asdfasdfasdfasdf') var key = new Buffer('asdfasdfasdfasdfasdfasdfasdfasdf') var cipher = crypto.createCipheriv('aes-256-cbc', key, iv); cipher.update(new Buffer("mystring")); var enc = cipher.final('base64'); [...]
iv需要16字节长,密钥为32字节。我们将
createCipher
更改为createCipheriv
。 -
回到python解密脚本:
这个过程只是简单地阅读PyCrypto的文档,并与我们开始的代码进行比较。
然后我们决定只坚持API,从头开始。它给出了:
from base64 import b64decode from Crypto.Cipher import AES [...] iv = 'asdfasdfasdfasdf' key = 'asdfasdfasdfasdfasdfasdfasdfasdf' encoded = b64decode('my_encrypted_string') dec = AES.new(key=key, mode=AES.MODE_CBC, IV=iv) value = dec.decrypt(encoded)
就这么简单。。。希望它能帮助你们中的一些人!
更新:
正如英仙座在回答的评论中所写的那样,IV必须是随机的,并且对于每个消息都不同。
您正在构建的系统可能不安全
除了存储之外,您基本上不想只加密数据,也不想对其进行身份验证。在这种情况下,身份验证意味着只有知道密钥的人才能生成有效消息。一种广泛使用的身份验证方案是HMAC。
如果您不验证您的消息,任何人都可以将数据输入您的服务。攻击者可能无法完全控制解密后的结果,但他/她可能仍然非常危险。例如,如果您使用CBC(您这样做)和最常见的填充方案(AES是一种分组密码,只能加密128位的数据块),并且攻击者可以区分填充错误和任何其他错误,则所有消息都可以被攻击者解密。这被称为填充预言机攻击,太常见了。
为了防止此类攻击,您可以使用身份验证加密方案,例如GCM块密码模式。
此外,您还必须防范重播攻击。考虑一个银行应用程序,您传输的数据是银行转账单。除非有任何TAN,攻击者可能会记录以前的交易,并一次又一次地将此交易重播给您的服务,从而转移客户最初想要的金额的倍数。
您从中获取数据的表单是否通过HTTPS传输?如果不是:密钥会被攻击者窃听吗?用户怎么知道他是从你而不是其他人那里得到表单的(SSL/TLS既是关于身份验证的,也是关于机密性的)。
我可能忘记了CBC加密提供的其他一些攻击向量。
备选方案
防范这些攻击的最简单方法可能是通过HTTPS传输表单数据。SSL/TLS旨在防止所有上述攻击,客户端和服务器端的实现需要很长时间才能成熟。