Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

So, I have the encryption and decryption methods on ruby and they work fine ruby. I followed the answer from this question (How to decrypt message with CryptoJS AES. I have a working Ruby example) but it's returning an empty string.

Ruby Code

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>
like image 514
Suthan Bala Avatar asked Jan 13 '17 19:01

Suthan Bala


People also ask

What encryption does CryptoJS use?

CryptoJS supports AES-128, AES-192, and AES-256. It will pick the variant by the size of the key you pass in. If you use a passphrase, then it will generate a 256-bit key. DES is a previously dominant algorithm for encryption, and was published as an official Federal Information Processing Standard (FIPS).

What is IV in CryptoJS?

In case of AES-256 - block size is, obviously, 256 bits, which is 32 bytes, which is exactly what you get by CryptoJS. enc. Base64. parse() of 22 byte Base64 string. According to specification and algorithm, IV is exactly block size length, which is 32 bytes with AES-256.

What is secret passphrase in CryptoJS?

It means that the key (secret passphrase) used to encrypt and decrypt is the same. So, it's security relies mostly in keeping the key secure. If someone obtains the key, they will be able to decrypt anything encrypted with that passphrase.


1 Answers

The problem is that Ruby expects the key to be in binary format, not hex. So you need to do this:

#!/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

For me that prints

mdnLCY6MdwEONY1AxR/vjVKMssB+yrPsz4QMjfl6fDXxv68E0EUxtAqa4VUo
fTkjq2Hqyd48UV3dyWmEbwXw5Q==

If I put that into your HTML file (without changing any code), I get back the original message:

<!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>

So the problem is that your Ruby code produced a gibberish cyphertext. Fix the key and re-encrypt, and the JS should start working.

like image 117
Paul A Jungwirth Avatar answered Oct 24 '22 01:10

Paul A Jungwirth