0

I want to do aes-128-cbc encryption in JAVA and Linux, but it keeps giving me different results. For example I want to decode string "my.txt". In Linux I do it in this way:

  echo -n my.txt | openssl aes-128-cbc -K 6f838655d1bd6312b224d3d1c8de4fe1 -iv 9027ce06e06dbc8b -a

I also encode it to base64 and it's giving me this result: 86M5fwdUpQ3tbFrz0ddHJw==

In Java I use this method:

public static String encrypt(String key, String initVector, String value) {
    try {
        IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
        SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);

        byte[] encrypted = cipher.doFinal(value.getBytes());
        System.out.println("encrypted string: "
                + Base64.encodeToString(encrypted, Base64.DEFAULT));

        return Base64.encodeToString(encrypted, Base64.DEFAULT);
    } catch (Exception ex) {
        ex.printStackTrace();
    }

    return null;
}

And with same data it gives me completely different result: vgk6yxCrQ5iLFvHxMtQO7w==

I also tried to use aes-256-cbc with 32-symbol length iv. In Linux I use aes-256-cbc and in Android I use Spongy Castle library for this purpose, but it give different results too.

What I did wrong? Or maybe you have suggestion to choose different cross-platform algorithm to encryption.

Artjom B.
  • 61,146
  • 24
  • 125
  • 222
  • 1
    Since AES is a well-defined and well-known standard, the algorithm is actually the same. The problem, I am certain, is the inputs. Are the actual bytes for the various inputs (key, iv, data) all the same? Note that bytes and characters are not the same thing. The character set or encoding is the relationship between them. Also verify that you are using the same padding for both. – dsh Mar 15 '17 at 16:36
  • 1
    [Java AES 128 encrypting differently to openssl](http://stackoverflow.com/q/21086103/608639), [Java equivalent of an OpenSSL AES CBC encryption](http://stackoverflow.com/q/32508961/608639), [How to decode a string encoded with openssl aes-128-cbc using java?](http://stackoverflow.com/q/31947256/608639), [Using Java to decrypt openssl aes-256-cbc using provided key and iv](http://stackoverflow.com/q/15594518/608639), etc. – jww Mar 15 '17 at 19:07

1 Answers1

3

The -K and -iv parameters expect Hex-encoded strings. Your key is 32 characters long, so it is 16 bytes or 128 bits. Your IV is 16 characters long, so it is 8 bytes or 64 bits. An IV for AES/CBC must be exactly 128 bits long. If it is not, then it must be padded somehow. Your IV is most likely padded with 0x00 bytes to get to 128 bits. You would have to do the same in Java.

The other issue is that you're treating the Hex-encoded key and IV as text, which means that you're treating it as a 256 bit key and 128 bit IV in Java. Which is probably not what you want. You have to decode the strings from Hex before use.

Let's use an imaginary implementation of byte[] fromHex(String hexStr):

byte[] ivBytes = new byte[16];
byte[] ivBytesShort = fromHex(initVector);
System.arraycopy(ivBytesShort, 0, ivBytes, 0, ivBytesShort.length);
IvParameterSpec iv = new IvParameterSpec(ivBytes);
SecretKeySpec skeySpec = new SecretKeySpec(fromHex(key), "AES");
Artjom B.
  • 61,146
  • 24
  • 125
  • 222
  • Yes, my initial iv was 32 characters long, but it gave me error about length of iv, and now I understand why. Yes, fromHex() is working and it give proper results. Thank you! – Андрій Бейлик Mar 15 '17 at 20:12