【问题标题】:Encrypting with CryptoJS, decrypt with Ruby / AES用 CryptoJS 加密,用 Ruby / AES 解密
【发布时间】:2014-08-17 06:29:09
【问题描述】:

这个问题差点让我跪下!

我正在尝试对将通过 AJAX 发送到 RoR 应用程序的数据进行加密。

我已经设法在 Ruby 中加密一个字符串并在 JavaScript 中解密它,但现在我无法进行相反的操作。

这是我的 JS:

function decrypt(data, key) {
    var index = data.indexOf('!$');
    var iv = data.substr(0, index);
    var crypttext = data.substr(index + 2);

    encrypted = {}
    encrypted.ciphertext = CryptoJS.enc.Base64.parse(crypttext);

    var decrypted = CryptoJS.AES.decrypt(encrypted, key, { iv: CryptoJS.enc.Base64.parse(iv) });

    return decrypted.toString(CryptoJS.enc.Utf8);
}

function encrypt( data, key ) {
    enc = CryptoJS.AES.encrypt( data, key );

    enc_str = CryptoJS.enc.Base64.stringify(enc.iv) + "!$" + CryptoJS.enc.Base64.stringify(enc.ciphertext);

    return enc_str;
}
// ...
var key = 'ABCDEF123ABCDEF123ABCDEF123ABCDEF123ABCDEF123';//CryptoJS.SHA256( 'ABCDEF123' ).toString();
var key2 = 'ABCDEF123ABCDEF123ABCDEF123ABCDEF123ABCDEF123_42'; //CryptoJS.SHA256( 'ABCDEF123_42' ).toString();
code = "123 456"
    uuid = "0000000000000000000000000000"

var enc_code    = encrypt( code, key );
var enc_uuid    = encrypt( uuid, key2 );

我将iv和密文分开,因为我在JS中解密时遇到了一些问题。

这是红宝石代码

def decrypt(string, key)
  salt = nil
  if string.include? '$$:'
    sp = string.split '$$:'
    string = sp[0]
    salt   = sp[1].to_i(16).to_s
  end

  parts = string.split '!$'

  @initialization_vector = Base64.decode64(parts[0])

  aes_decrypt(key, Base64.decode64(parts[1]), salt)
end

def aes(key,string)
  cipher = OpenSSL::Cipher::Cipher.new("aes-256-cbc")
  cipher.encrypt
  cipher.key = key #Digest::SHA256.digest(key)
  cipher.iv = @initialization_vector = cipher.random_iv# + '#'
  cipher_text = cipher.update(string)
  cipher_text << cipher.final
  return  cipher_text
end

def aes_decrypt(key, encrypted, salt = nil)
  p encrypted
  cipher = OpenSSL::Cipher::Cipher.new("aes-256-cbc")
  cipher.decrypt
  cipher.padding = 0 # I Spent a couple of hours with an exception from Cipher, all I had to do was add this line!!
  cipher.key = key #Digest::SHA256.digest(key)
  cipher.iv = encrypted.slice!(0, 16)
  unless salt.nil?
 #   cipher.pkcs5_keyivgen key, salt
  end
  d = cipher.update(encrypted)
  d << cipher.final
end

如您所见,我试图找出一种包含盐的方法,但没有运气(Cipher 不会接受盐并要求八位字节)!

Ruby 中的解密只是吐出乱码。 (这些方法有效,我已经直接在 Ruby 中解密了发送到客户端的字符串(在 JS 中解密没有问题),效果很好!

这是奇怪的事情,我试图立即在 JS 中解密字符串,但这也不起作用! 结果如下:

CryptoJS.AES.decrypt( enc, key, { iv: enc.iv, salt: enc.salt } ).toString() // In encrypt()
// => 31323320343536
// => 30303030303030303030303030303030303030303030303030303030

decrypt( enc_code, key ).toString(); // After encrypt
// => [EMPTY]

我的 Google-fu 让我失望了,我已经尝试了我发现的大多数东西!

有什么想法吗??

【问题讨论】:

  • 你为什么首先使用盐?
  • @owlstead 默认情况下它是打开的(无论如何它看起来如何!)。您从 AES.encrypt 获得的对象包含一个盐值(请参阅:code.google.com/p/crypto-js/#The_Cipher_Output),我猜这就是它使用的盐(为什么它会在那里?)。而且我找不到如何关闭它!

标签: javascript ruby-on-rails ruby encryption cryptojs


【解决方案1】:

您正在使用的库正在使用更高层的 OpenSSL。较高层支持基于密码的加密。默认情况下,您的 CryptoJS 代码似乎使用 OpenSSL 中专有的基于密码的密钥派生函数。然而,Ruby 代码默认做的更少;它只会使用您输入的密钥作为密钥,您需要自己进行密钥派生。

因此,如果您只想使用一个密钥(应该是随机二进制数据,而不是文本),您应该在 CryptoJS 中使用 custom key and IV。另一方面,如果你想使用密码(以及盐值),你应该使用method-i-pkcs5_keyivgen。在这种情况下,您可能还需要解析 OpenSSL 加密的 BLOB。

【讨论】:

    猜你喜欢
    • 2019-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-20
    • 2014-12-16
    相关资源
    最近更新 更多