Rya*_*n S 8 javascript ruby encryption cryptography node.js
我想在ruby应用程序中加密一些数据,然后在nodejs应用程序中对其进行解码.我一直试图让这个工作,现在我只是尝试加密两种语言中的同一块数据,以获得相同的结果,但我似乎无法做到这一点.
//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
Run Code Online (Sandbox Code Playgroud)
所以看起来我从编码中得到一个十六进制字符串.
#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
p e # ??;??
Run Code Online (Sandbox Code Playgroud)
是否存在某些我遗漏的编码问题.我尝试使用base64解码e,但这并没有产生与节点应用相同的结果.有什么指针吗?
更新:所以这和朋友一样接近,我可以得到:https://gist.github.com/a880ea13d3b65a21a99d.Sheesh,我只是想在ruby中加密一些东西并在节点中解密它.
更新2:好的,这个问题中的代码让我有很多方式:https://github.com/joyent/node/issues/1395
有几个微妙的事情使这个失败。最重要的一个 - 您没有在代码中指定 IV,因此将为您生成一个随机值。您会注意到,您甚至无法以这种方式在相同的编程语言中解密您的密文。
所以你需要为这两个实现提供一个明确的 IV。但在我向您展示代码之前,有一些建议:
密钥生成:
Blowfish 在 64 位块上运行,其密钥大小各不相同,但 OpenSSL(目前支持 Ruby 和 node.js 的密码实现)默认使用 128 位,即 16 字节。
所以你的密钥违反了两个原则 - 第一个:它太长了。这是一个SHA-1散列,这是十六进制表示20个字节×2 = 40个字节,而不是16大部分的时间,这是好的,因为实现适当截断值,但是这是你应该不依赖。
第二个更严重的错误是您使用十六进制表示而不是原始字节:大安全问题!十六进制字符根本不是随机的,因此实际上您将输入的熵减少到长度的一半(因为底层字节是随机的)。
一种生成随机密钥的安全方法是使用 OpenSSL::Random
key = OpenSSL::Random.random_bytes(cipher_key_len)
Run Code Online (Sandbox Code Playgroud)
第三个错误是将您的密钥硬编码在源代码中。这是个坏主意。您至少应该将它存储在文件系统上的其他地方,在那里访问受到严格限制。另见我对另一个问题的回答。密钥应该存储在带外,并且只能在应用程序中动态加载。
密码:
河豚变老。从某种意义上说,它仍然被认为是完整的,因为强制执行它是破坏它的唯一方法。但是 2^64 的搜索空间对于足智多谋的攻击者来说并非遥不可及。所以你确实应该转向AES。
填充:
默认情况下,OpenSSL 使用 PKCS5Padding(也称为 PKCS7Padding)填充。Ruby 从中获利,我敢打赌 node.js 也利用了这一点 - 所以你应该对此保持安全。
现在到工作解决方案。我们需要生成一个 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');
Run Code Online (Sandbox Code Playgroud)
现在是 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]
Run Code Online (Sandbox Code Playgroud)
好的。我要感谢大家帮助我。基本上这个线程在这里回答了我的问题: https: //github.com/joyent/node/issues/1395。我将继续发布这两个程序,以防其他人必须经历这个繁琐的过程。请记住,这并不意味着绝对安全,这是 ruby 加密数据和节点解密数据的垫脚石。您将必须采取更多步骤来确保采取更高的安全措施。
代码位于此要点:https ://gist.github.com/799d6021890f34734470
这些在 ruby 1.9.2p290 和 Node 0.4.10 上运行
归档时间: |
|
查看次数: |
3499 次 |
最近记录: |