Aes/Cbc/Pkcs5Padding Encrypt in Java Decrypt in Ruby

AES/CBC/PKCS5Padding encrypt in java decrypt in ruby

There's two problems with your Ruby code.

First, you're using AES 256 when you should be using AES 128. Java uses AES 128 or 256 based on the size of the key you use, and you're using a 128 bit key.

Second, you need to Hex decode your key, iv, and encrypted_string values in Ruby. OpenSSL Cipher is expecting binary, not hex strings.

require 'openssl';

key = "97128424897797a166913557a6f4cc8e";
iv = "84e8c3ea8859a0e293941d1cb00a39c3";
encrypted_string = "395f6c0e8ad27f57c4a5a8975aa633e5b26f288d37ce18c6971779951f3b3527";

de_cipher = OpenSSL::Cipher::Cipher.new("AES-128-CBC");
de_cipher.decrypt;
de_cipher.key = [key].pack('H*');
de_cipher.iv = [iv].pack('H*');

puts de_cipher.update([encrypted_string].pack('H*')) << de_cipher.final;

Output:

{"timestamp":"1377499097199"}

Java encryption / decryption to Ruby

You need to use the IV and Key from your Java Example, not a new/random IV/Key:

require "openssl"
require "base64"
require 'byebug'

include Base64

plain_text = "abceeffslaj"

key = 'Bar12345Bar12345'
iv = 'RandomInitVector'

cipher = OpenSSL::Cipher::AES128.new(:CBC)
cipher.encrypt
cipher.key = key
cipher.iv = iv
cipher_text = cipher.update(plain_text) + cipher.final

cipher = OpenSSL::Cipher::AES128.new(:CBC)
cipher.decrypt
cipher.key = key
cipher.iv = iv
decrypted_plain_text = cipher.update(cipher_text) + cipher.final

puts "AES128 in CBC mode"
puts "Key: " + urlsafe_encode64(key)
puts "Iv: " + urlsafe_encode64(iv)
puts "Plain text: " + plain_text
puts "Cipher text: " + urlsafe_encode64(cipher_text)
puts "Decrypted plain text: " + decrypted_plain_text

AES/CBC/PKCS5Padding implementation in Ruby (for rails)

The Ruby code in my first post is correct, the problem was this AES/CBC/PKCS5Padding used by Java part.

Java program should not use this scheme for AES-CBC-256. PKCS5 pads to a 64 bit (8 byte) block size, but AES-256-CBC uses 16 byte blocks. Therefore, PKCS7 must be used.

AES CBC PKCS5Padding Java to Ruby

The code above works just fine. The problem was in the encoding of the base64 sent through a post request.

Coldfusion AES/CBC/PKCS5Padding decryption in Ruby

(Expanded from comments)

but I need a hex key

Then convert it from base64 to hex. In CF, you can use the BinaryEncode() and BinaryDecode functions:

binaryEncode(binaryDecode("QzYxMDI5N0NFODU3MDc1MA==", "base64"), "hex")

Looks like there are a few other problems:

  1. The CF code generates a 128 bit key, but the ruby code is using AES 256. It needs to use AES 128.

  2. The CF code is generating a random IV. The Ruby code is using a totally different iv. With CBC mode, both sides must use the same iv to get the expected results. "Decrypting with the incorrect IV causes the first block of plaintext to be corrupt ...", which is why your decrypted value is off. To resolve it, the Ruby code should use the same iv that was used to encrypt.


Update:

When CF generates the IV automatically (as it does here), it prepends that IV to the encrypted value:

When ColdFusion creates an IV automatically, it generates a secure,
random IV and prepends this to the encrypted data. When ColdFusion
decrypts the data, this IV is recovered and used. It is
cryptologically important that the IV varies between encryptions. This
is why the encrypted value changes when you repeatedly encrypt the
same string with an algorithm that uses an IV, like
DES/CBC/PKCS5Padding. Unlike the encryption key, it is not necessary
for the IV to be kept secret.

So the IV value can be extracted by removing the first "block" of the encrypted binary. The block size depends on the algorithm. For AES, it is 16. I do not know the exact Ruby code, but in CF you could extract the IV like so:

blockSize = 16;
rawBinary = binaryDecode(encryptedString, "base64");
// IV is always the first block
ivBytes = arraySlice(rawBinary, 1, blockSize);
// Remaining bytes are the encrypted value
dataBytes = arraySlice(rawBinary, blockSize+1, arrayLen(rawBinary)-blockSize);


Related Topics



Leave a reply



Submit