使用ruby解密encryption数据

我想要在ruby应用程序中encryption一些数据,然后在nodejs应用程序中对其进行解码。 我一直试图让这个工作,现在我只是试图encryption两种语言相同的数据,以获得相同的结果,但我似乎无法做到这一点。

//js var crypto = require('crypto'); var key = crypto.createHash('sha1').update('key').digest('hex'); console.log(key); // a62f2225bf70bfaccbc7f1ef2a397836717377de var encrypted = ""; var cipher = crypto.createCipher('bf-cbc', key); encrypted += cipher.update('text'); encrypted += cipher.final('hex'); console.log(encrypted); //outputs 4eafd5542875bd3c 

所以看起来像我从编码中得到一个hexstring。

 #ruby require 'openssl' require 'digest/sha1' c = OpenSSL::Cipher::Cipher.new("bf-cbc") c.encrypt # your pass is what is used to encrypt/decrypt c.key = key = Digest::SHA1.hexdigest("key") p key # a62f2225bf70bfaccbc7f1ef2a397836717377de e = c.update("text") e << c.final pe # 皋?;?? 

是否有某种我缺less的编码问题。 我试图base64解码e,但没有产生与节点应用程序相同的结果。 任何指针?

更新:所以这是一样的朋友,我可以得到: https : //gist.github.com/a880ea13d3b65a21a99d 。 Sheesh,我只是想在Ruby中encryption一些东西,并在节点中解密它。

UPDATE2:好的,这个问题的代码让我有很多方法: https : //github.com/joyent/node/issues/1395

有几个微妙的事情,使这个失败。 最重要的一个 – 你没有在你的代码中指定一个IV,所以一个随机值将会为你生成。 你会注意到你甚至不能用这种方式在相同的编程语言中解密你的密文。

所以你需要为这两个实现提供一个明确的IV。 但是在我向你展示代码之前,有一些build议:

密钥生成

Blowfish在64位块上运行,其密钥大小各不相同,但OpenSSL(目前支持Ruby和Node.js的密码实现)默认使用128位,即16个字节。

所以你的钥匙违反了两个原则 – 第一个原则:太简单了。 它是SHA-1散列的hex表示,它是20个字节* 2 = 40个字节而不是16个。大多数情况下,这很好,因为实现会适当地截断值,但这是不应该依赖的。

第二个错误,更严重的是,你使用hex表示,而不是原始字节:大的安全问题! hex字符根本不是随机的,因此实际上将input的熵减less到一半(因为基础字节是随机的)。

生成随机密钥的安全方法是使用OpenSSL :: Random

 key = OpenSSL::Random.random_bytes(cipher_key_len) 

第三个错误是把你的密钥硬编码在源代码中。 这是一个坏主意。 您应该至less将其存储在文件系统中的其他位置,在该文件系统中访问受到严格限制。 另请参阅我对另一个问题的回答。 密钥应该被存储在带外,只能在应用程序中dynamic加载。

密码

河豚变老了。 它仍然被认为是不间断的,因为强制它是打破它的唯一方法。 但对于资源性的攻击者来说,2 ^ 64的search空间并不是遥不可及的。 所以你应该转向AES。

填充

使用PKCS5Padding(也称为PKCS7Padding)的OpenSSL填充默认情况下。 ruby从这里获利,我的赌注是node.js也利用这个 – 所以你应该在这个安全。

现在到工作的解决scheme。 我们需要生成一个IV,Blowfish要求它是64位 – 8个字节。 您将需要rbytes在节点中获得安全的随机数字。 IV可能在你的源代码中被硬编码(这是公开的信息,没有安全影响) – 但是双方必须是相同的。 您应该预生成一个值,并将其用于node.js和Ruby。

 /*node.js*/ var rbytes = require('rbytes'); var iv = rbytes.randomBytes(8); /*see advice above - this should be out-of-band*/ var key = rbytes.randomBytes(16); var encrypted = ""; var cipher = crypto.createCipheriv('bf-cbc', key, iv); encrypted += cipher.update('text'); encrypted += cipher.final('hex'); 

现在Ruby部分:

 require 'openssl' c = OpenSSL::Cipher::Cipher.new("bf-cbc") c.encrypt # should be out-of-band again c.key = OpenSSL::Random.random_bytes(16) # may be public but has to be the same for Ruby and node iv = OpenSSL::Random.random_bytes(8) c.iv = iv e = c.update("text") e << c.final puts e.unpack('H*')[0] 

你的密码将是一些随机看字节。 这些字节可以表示为hex,Base64或其他方式。 看起来你的ruby代码正在输出原始字节。 我build议你将这些原始字节转换为hex来进行比较。

看你的代码,你也应该从Blowfish(“bf”)更改为AES。 Blowfish有一个64位块大小,现在已经过时了。

你会明确指定填充,PKCS7是常见的

好。 我想感谢大家帮助我。 基本上这个线程在这里回答我的问题: https : //github.com/joyent/node/issues/1395 。 我会继续发布这两个程序,以防其他任何人都要经过这个巨无霸。 请记住,这并不意味着硬核的安全,这是一个rubyencryption数据和节点解密它的垫脚石。 你将不得不采取更多措施来确保采取更高的安全措施。

代码位于这个要点: https : //gist.github.com/799d6021890f34734470

这些是运行在ruby1.9.2p290和节点0.4.10