【问题标题】:AES - Encryption with Crypto (node-js) / decryption with Pycrypto (python)AES - 使用 Crypto (node-js) 加密/使用 Pycrypto (python) 解密
【发布时间】:2013-08-16 16:51:29
【问题描述】:

我写这个问题+答案是因为我很挣扎(可能是因为缺乏经验),迷失在使用 node 或 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')
    [...]
    

    这对我的字符串进行编码非常有效。

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

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

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

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

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

答案是我和我的同事想出的(嗯,主要是我的同事)。

【问题讨论】:

    标签: python node.js cryptography pycrypto


    【解决方案1】:

    所以我们从“我如何解密... 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 字节长,key 是 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)
      

    就这么简单... 希望对大家有所帮助!

    更新:

    正如 Perseids 在他的答案的 cmets 中所写,IV 必须是随机的,并且对于每条消息都不同

    【讨论】:

      【解决方案2】:

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

      除了存储之外,您基本上不想只加密您的数据,还要对其进行身份验证。在这种情况下,身份验证意味着只有知道密钥的人才能生成有效消息。一种广泛使用的身份验证方案是HMAC

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

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

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

      您获取数据的表单是通过 HTTPS 传输的吗?如果不是:密钥可以被攻击者窃听吗?用户如何知道他从您那里获得了表单,而不是其他任何人(SSL/TLS 与身份验证和机密性一样重要)。

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

      替代方案

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

      【讨论】:

      • 好吧,我刚刚介绍了加密操作,我不会谈论我们使用的所有其他安全系统,因为与 nodejs/python 加密/解密兼容性无关。但是感谢这个答案,这真的很有趣
      • @Perseids 请注意,padding oracle 攻击是针对 CBC 模式的攻击(尽管它确实使用 padding 函数作为 oracle)。
      • @nnaelle 安全始终关注全局。一个系统的安全性取决于其最薄弱的环节。即使是最小的问题也可能完全破坏整个系统。这就是为什么你不能孤立地处理它的不同部分。
      • @ntoskrnl:谢谢,我忘了把它写到答案中。不过,nnaelle 正在使用 CBC。
      • @nnaelle:如果你知道自己在做什么,那很好。问题是许多其他读者不会。我已经看到人们在互联网上的某个地方阅读的代码,他们需要使用加密来保护他们的服务,然后只是复制了一些代码,而没有正确说明如何使用它。例如,这样的读者不会知道您帖子中的 IV 需要 随机 并且 每条消息都不同(我暂时忽略了即将到来的填充预言攻击) .结果通常与根本不使用任何密码学一样糟糕。
      猜你喜欢
      • 2014-01-18
      • 2022-09-27
      • 2020-11-24
      • 2021-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-28
      相关资源
      最近更新 更多