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

nna*_*lle 18 python cryptography pycrypto node.js

我正在写这个问题+答案,因为我经历了很多努力(可能是因为缺乏经验),迷失了许多不同的加密/解密节点或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')
    [...]
    
    Run Code Online (Sandbox Code Playgroud)

    这对我的字符串编码非常好.

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

    from Crypto.Cipher import AES
    [...]
    my_string = data_coming_from_rabbitmq
    obj = AES.new('mykeywhatever', AES.MODE_CBC)
    obj.decrypt(ciphertext)
    [...]
    
    Run Code Online (Sandbox Code Playgroud)

    这显然不起作用:在自述文件中有一个IV,但由于我没有在节点脚本中给出一个,为什么我要在python中给一个?

经过更多的谷歌搜索,我了解到节点的Crypto使用OpenSSL,而PyCrypto显然没有.所以我调查了一下,找到了那些页面:

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

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

nna*_*lle 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');
    [...]
    
    Run Code Online (Sandbox Code Playgroud)

    iv需要16字节长,密钥是32字节.我们改变createCiphercreateCipheriv.

  • 回到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)
    
    Run Code Online (Sandbox Code Playgroud)

就这么简单......希望它能帮助你们中的一些人!

更新:

正如英仙座在他的回答评论中写道,对于每条信息,IV必须是随机的和不同的


Per*_*ids 9

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

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

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

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

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

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

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

备择方案

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

  • @nnaelle:如果你知道你在做什么那很好.问题是许多其他读者不会.我见过人们在互联网上阅读的代码,他们需要使用加密来保护他们的服务,然后只是在没有正确指令的情况下复制了一些代码如何使用它.例如,这样的读者不会知道你的帖子中的IV需要*random*和*不同的每条消息*(我暂时忽略了隐约填充的oracle攻击).结果通常与不使用任何加密一样糟糕. (4认同)