1

Hi i am using openSSL command to encrypt and decrypt my message. Now i want this command to be converted in the java code i have tried different solutions provided on the web but none of the code matches the results.

Here is my OpenSSL command with my understating in the comments:

key="FB4FF1BA6F1FCC1A11B8B3910342CBD3A2BEAEB8F52E8910D9B25C0C96280EEA"

# Getting 16 digits from the iv.txt file and putting it into the bin
head -c 16 iv.txt > iv.bin

# Converting iv.bin text into the HEXA value
iv=`xxd -l 16 -p iv.bin`

# encrypt without "-a" 
openssl enc -aes-256-cbc -K $key -iv $iv -in plainKey.txt -out encryptedKey.bin

# printing encrypted results in base64 format this need to be matched with my java code.
echo "<enc>"`cat encryptedKey.bin | base64`"</enc>"

This is what i have done in Java :

Note: this code from stack overflow accepted answer with minor change I have tried some other codes as well but cannot mention all here.

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;

public class Test {

public static void main(String[] args) {
    try {
        runEncryption();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private static void runEncryption() throws Exception
{
    //String to be encrypted
    String plainText = "abcd@1234\n";

    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

    // IV text
    String iv = "C837E1B6C3D3A7E28F47719DE0C182C9";

    // getting 16 characters of iv text
    iv = iv.substring(0,16);

    // Value of key
    String key = "FB4FF1BA6F1FCC1A11B8B3910342CBD3A2BEAEB8F52E8910D9B25C0C96280EEA";

    // Logic for converting 16 Digits of IV into HEX
    StringBuffer hexString = new StringBuffer();
    for (int i=0;i<iv.getBytes().length;i++) {
        String hex=Integer.toHexString(0xff & iv.getBytes()[i]);
        if(hex.length()==1) hexString.append('0');
        hexString.append(hex);
    }

    // Seems something wrong here because if i am passing all the bytes to keySpe like key.getBytes() it is producing exception  so i am passing 16 bytes as previous code was doing in SO
    SecretKeySpec keySpec = new SecretKeySpec(hexToBytes(key), 0, 16, "AES");
    IvParameterSpec ivSpec = new IvParameterSpec(hexToBytes(hexString.toString()));

    cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
    byte[] encrypted = cipher.doFinal(plainText.getBytes("UTF-8"));

    String encryptedBase64 = new String(DatatypeConverter.printBase64Binary(encrypted));

    System.out.println("");
    System.out.println("Encrypted base64 = " + encryptedBase64);
}

private static byte[] hexToBytes(String s)
{
    int len = s.length();
    byte[] data = new byte[len / 2];

    for (int i = 0; i < len; i += 2)
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16));

    return data;
}    
}

I am generating key and iv using openSSL command

openssl enc -aes-256-cbc -k secret -P -md sha1

it Seems something wrong here because if i am passing all the bytes to keySpec like key.getBytes() it is producing exception so i am passing 16 bytes as previous code was doing in SO i have also mentioned this in the code comments please advise on this thanks.

Zahid Ali
  • 456
  • 6
  • 20
  • There may be other issues, but first lets have the same parameters - you are passing only 16 key bytes, you are effectively doing AES-128 where the openssl is used with `aes-256-cbc`. Next - why do you do hex/string conversion youself? (isn't – gusto2 Nov 27 '17 at 15:37
  • [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 Nov 28 '17 at 00:57
  • Usually [`EVP_BytesToKey`](http://wiki.openssl.org/index.php/Manual:EVP_BytesToKey(3)) is one of the issues. See [Java equivalent of C++ encryption](http://stackoverflow.com/q/12920740/608639), [How to use OpenSSL generated keys in Java?](http://security.stackexchange.com/q/9600/29925), [Java openssl encryption / decryption key generation](http://stackoverflow.com/q/34502705/608639), [Password to key function compatible with OpenSSL commands?](http://stackoverflow.com/q/9488919), [How to decrypt file in Java encrypted with openssl command using AES?](http://stackoverflow.com/q/11783062), etc. – jww Nov 28 '17 at 00:57

1 Answers1

0

You have several mistakes in your code

let's assume what you want to do is

 openssl enc -aes-256-cbc -K FB4FF1BA6F1FCC1A11B8B3910342CBD3A2BEAEB8F52E8910D9B25C0C96280EEA -iv 03B13BBE886F00E00000000000000000 -base64 -in input.txt

in your code you have a few mistakes (wtf moments). I won't fix them for you, but basically:

  1. I'd advice to use some normal library (e.g. commons-codec, ..) to encode/decode from hex, though seems it's working so far

  2. you are using 16 bytes (128 bit) iv and key effectively doing AES-128. You need to use AES-256 having key and iv 256 bit long (32 bytes). You've cut both to 16 bytes so they are different from values used with openssl

  3. the main breaking point: IvParameterSpec ivSpec = new IvParameterSpec(hexToBytes(hexString.toString())); please think about this a little. hexToBytes(iv)

gusto2
  • 11,210
  • 2
  • 17
  • 36
  • as for as point 1 is concerned i was not getting the same hex code using a few libraries that is why i did it normally but i will use the library once i will get my desired encrypted results and for point 2 if i am increasing the size of key and iv i am getting error invalid key and this key i am generating with open ssl using command $ openssl enc -aes-256-cbc -k secret -P -md sha1 – Zahid Ali Nov 28 '17 at 07:02
  • Please make sure both iv and key (they real byte array size) are 256 bit (32 bytes). It worked for me. Just an idea - what Java version/distribution do you use? Don't you need [Unlimited Strength JCE Policy](http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html)? – gusto2 Nov 28 '17 at 09:29
  • it is working in my case also but the problem is its output is not matched with the output of the openSSL i don't have much knowledge of openSSL and Cryptography can you guide me how can i get 256 bit iv and key thanks. – Zahid Ali Nov 28 '17 at 09:57
  • 2
    If you use Oracle JRE, you need to install the Unlimited Strength JCE Policy, Otherwise you are limited to AES-128 (as far I know). So maybe for the start you may try to use 16 bytes keys and aes-128 with openssl and Java to see if it's done right (it is strong enough, don't worry). Or you may try to use BouncyCastle or OpenJDK – gusto2 Nov 28 '17 at 10:02
  • Thank your last comments worked for me after installing Unlimited Strength JCE Policy the error Illegal key size vanished and the output matched with the desired output. now i am trying BouncyCastle so that the application does not require JRE change. – Zahid Ali Nov 28 '17 at 11:26