AES - 使用Pycrypto(python)加密加密(node-js)/解密

时间:2013-08-14 16:04:34

标签: python node.js cryptography pycrypto

我正在写这个问题+答案因为我经常挣扎(可能是因为缺乏经验),迷失了许多不同的加密/解密节点或python的方法。

我想也许我的案子可以帮助将来的人。

我需要做什么:

  • 从表单中获取数据,使用Crypto(node-js)加密它们
  • 将加密数据传递给Python并使用PyCrypto解密。

我选择使用AES加密。

这是我开始的方式(我不会完成我尝试过的所有事情):

  • 我按照this page

    末尾的示例进行操作

    在我的案例中给出了:

    (这可能是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')
    [...]
    

    这对我的字符串进行编码非常合适。

  • 然后我使用PyCrypto's github's page上的自述文件写了我的python脚本来解密这个字符串:

    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显然没有。所以我调查了那些并找到了那些页面:

所以事情变得复杂,没有人做同样的事情来解密数据,我迷路了,并寻求帮助。

答案就是我的同事和我想出来的(好吧,主要是我的corworker)。

2 个答案:

答案 0 :(得分:15)

所以我们从“如何解密... 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的文档,并比较with the code we started from

    然后我们决定只是stick to the 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必须是随机的和不同的

答案 1 :(得分:8)

您正在构建的系统可能不安全

除了存储,您基本上不想只加密您的数据,还要验证它。此上下文中的身份验证意味着有效消息只能由知道密钥的人生成。广泛使用的身份验证方案是HMAC

如果您未对消息进行身份验证,则任何人都可以将数据提供给您的服务。攻击者可能无法在解密后完全控制结果,但他/她可能仍然非常危险。例如,如果您使用CBC(您这样做)和最常见的填充方案(AES是块密码并且只能加密128位数据块),并且攻击者可以区分填充错误和任何其他错误,那么您的所有邮件都可以被攻击者解密。这称为padding oracle attack太常见了。

为了防止此类攻击,您可以使用经过身份验证的加密方案,例如GCM阻止模式。

此外,您必须防范 replay attacks 。考虑银行应用程序,您传输的数据是银行转帐单。除非任何TAN,否则攻击者可能会记录先前的交易并一次又一次地将此交易重播给您的服务,从而转移客户最初想要的多笔钱。

您是通过HTTPS传输数据的表单吗?如果不是:密钥是否可以被攻击者窃听?用户如何知道他从您而不是其他任何人那里得到了表格(SSL / TLS与身份保密一样多关于身份验证)。

可能我忘记了一些简单的CBC加密提供的其他攻击媒介。

替代

防止这些攻击的最简单方法可能是通过HTTPS传输表单数据。 SSL / TLS旨在防止上述所有攻击,客户端和服务器端实现需要很长时间才能成熟。