CryptoJS 不适用于 IV 和密钥,但它适用于 Ruby

CryptoJS is not working with IV and key, but it works in Ruby

所以,我在 ruby 上有加密和解密方法,它们工作正常 ruby。我遵循了 this question (How to decrypt message with CryptoJS AES. I have a working Ruby example) 的答案,但它返回了一个空字符串。

Ruby代码

def load_vars
        @key = "2e35f242a46d67eeb74aabc37d5e5d05"
        @algorithm = "aes-128-cbc"
    end

    def encryption(data)
        begin
            key = @key
            aes = OpenSSL::Cipher.new(@algorithm)
            aes.encrypt()
            aes.key = key
            iv_value = aes.random_iv
            aes.iv = iv_value
            crypt = aes.update(data) + aes.final()
            crypt_string = (Base64.encode64(iv_value + crypt))
            return crypt_string
        end
    end

    def decryption(data)
        begin
            key = @key
            aes = OpenSSL::Cipher.new(@algorithm)
            iv_value = Base64.decode64(data)[0...16]
            data_value = Base64.decode64(data)[16..-1]
            aes.decrypt
            aes.key = @key
            aes.iv = iv_value
            results = aes.update(data_value) + aes.final
            return results
        end
    end

HTML JSFIDDLE

<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/core-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/aes.js"></script>

<script>        
    data = "wlkAKa4ps+Xizx4VIdUSp43yfQvOmt9FNlVTQ1ANsCU=\n"; // The data received from the ruby encryption method
    key = "2e35f242a46d67eeb74aabc37d5e5d05";

    // Decode the base64 data so we can separate iv and crypt text.
    var rawData = atob(data);
    var iv = rawData.substring(0,16);
    var crypttext = rawData.substring(16);

    // Decrypt...
    var plaintextArray = CryptoJS.AES.decrypt(
      { ciphertext: CryptoJS.enc.Latin1.parse(crypttext) },
      CryptoJS.enc.Hex.parse(key),
      { iv: CryptoJS.enc.Latin1.parse(iv) }
    );

    console.log(CryptoJS.enc.Latin1.stringify(plaintextArray));
</script>

问题是 Ruby 期望密钥是二进制格式,而不是十六进制格式。所以你需要这样做:

#!/usr/bin/env ruby

require 'openssl'
require 'base64'

data = "When in Rome do as the Romans do"
key = "2e35f242a46d67eeb74aabc37d5e5d05"
aes = OpenSSL::Cipher.new("aes-128-cbc")
aes.encrypt()
aes.key = key.scan(/../).collect{|x| x.hex}.pack("c*")
iv_value = aes.random_iv
aes.iv = iv_value
crypt = aes.update(data) + aes.final()
crypt_string = (Base64.encode64(iv_value + crypt))
puts crypt_string

对我来说打印

mdnLCY6MdwEONY1AxR/vjVKMssB+yrPsz4QMjfl6fDXxv68E0EUxtAqa4VUo
fTkjq2Hqyd48UV3dyWmEbwXw5Q==

如果我将其放入您的 HTML 文件(不更改任何代码),我会取回原始消息:

<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/core-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/aes.js"></script>

<script>        
data = "mdnLCY6MdwEONY1AxR/vjVKMssB+yrPsz4QMjfl6fDXxv68E0EUxtAqa4VUo\nfTkjq2Hqyd48UV3dyWmEbwXw5Q==\n";
key = "2e35f242a46d67eeb74aabc37d5e5d05";

var rawData = atob(data);
var iv = rawData.substring(0,16);
var crypttext = rawData.substring(16);

// Decrypt...
var plaintextArray = CryptoJS.AES.decrypt(
  { ciphertext: CryptoJS.enc.Latin1.parse(crypttext) },
  CryptoJS.enc.Hex.parse(key),
  { iv: CryptoJS.enc.Latin1.parse(iv) }
);

console.log(plaintextArray);
console.log(CryptoJS.enc.Latin1.stringify(plaintextArray));
</script>
</head>
<body>
</body>
</html>

所以问题是您的 Ruby 代码产生了乱码密文。修复密钥和 re-encrypt,JS 应该开始工作了。