Click here to Skip to main content
15,884,176 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Hi i have the following code for decryption similar to openssl. I am looking for java code for encryption that mimics openssl -aes-256-cbc -a -salt with given string and a password. Any clue/help is appreciated.

import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;

public class AES5 {

    private static final Charset ASCII = Charset.forName("ASCII");
    private static final int INDEX_KEY = 0;
    private static final int INDEX_IV = 1;
    private static final int ITERATIONS = 1;
    private static final int SALT_OFFSET = 8;
    private static final int SALT_SIZE = 8;
    private static final int CIPHERTEXT_OFFSET = SALT_OFFSET + SALT_SIZE;
    private static final int KEY_SIZE_BITS = 256;

    /**
     * Thanks go to Ola Bini for releasing this source on his blog. The source was
     * obtained from <a href="http://olabini.com/blog/tag/evp_bytestokey/">here</a>
     * 
     */

    public static byte[][] EVP_BytesToKey(int key_len, int iv_len, MessageDigest md, byte[] salt, byte[] data,
            int count) {

        byte[][] both = new byte[2][];
        byte[] key = new byte[key_len];
        int key_ix = 0;
        byte[] iv = new byte[iv_len];
        int iv_ix = 0;
        both[0] = key;
        both[1] = iv;
        byte[] md_buf = null;
        int nkey = key_len;
        int niv = iv_len;
        int i = 0;
        if (data == null) {
            return both;
        }
        int addmd = 0;
        for (;;) {
            md.reset();
            if (addmd++ > 0) {
                md.update(md_buf);
            }
            md.update(data);
            if (null != salt) {
                md.update(salt, 0, 8);
            }
            md_buf = md.digest();
            for (i = 1; i < count; i++) {
                md.reset();
                md.update(md_buf);
                md_buf = md.digest();
            }
            i = 0;
            if (nkey > 0) {
                for (;;) {
                    if (nkey == 0)
                        break;
                    if (i == md_buf.length)
                        break;
                    key[key_ix++] = md_buf[i];
                    nkey--;
                    i++;
                }
            }
            if (niv > 0 && i != md_buf.length) {
                for (;;) {
                    if (niv == 0)
                        break;
                    if (i == md_buf.length)
                        break;
                    iv[iv_ix++] = md_buf[i];
                    niv--;
                    i++;
                }
            }
            if (nkey == 0 && niv == 0) {
                break;
            }
        }
        for (i = 0; i < md_buf.length; i++) {
            md_buf[i] = 0;
        }
        return both;
    }


    public static byte[][] getKeyIV(byte[] headerSaltAndCipherText, Cipher aesCBC, String password) {       
        byte[] salt = Arrays.copyOfRange(headerSaltAndCipherText, SALT_OFFSET, SALT_OFFSET + SALT_SIZE);
        byte[][] keyAndIV=null;
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            keyAndIV = EVP_BytesToKey(KEY_SIZE_BITS / Byte.SIZE, aesCBC.getBlockSize(), md5, salt,
                    password.getBytes(ASCII), ITERATIONS);
        } catch (Exception e) {e.printStackTrace();}

        return keyAndIV;
    }

    // https://stackoverflow.com/questions/11783062/how-to-decrypt-file-in-java-encrypted-with-openssl-command-using-aes
    public static String decrypt(String encryptedMsg, String password) {

        String decryptedMsg =null;      
        byte[] headerSaltAndCipherText = Base64.decodeBase64(encryptedMsg);
        byte[] encrypted = Arrays.copyOfRange(headerSaltAndCipherText, CIPHERTEXT_OFFSET, headerSaltAndCipherText.length);
        try {
            Cipher aesCBC = Cipher.getInstance("AES/CBC/PKCS5Padding");
            final byte[][] keyAndIV = getKeyIV(headerSaltAndCipherText, aesCBC, password);
            SecretKeySpec key = new SecretKeySpec(keyAndIV[INDEX_KEY], "AES");
            IvParameterSpec iv = new IvParameterSpec(keyAndIV[INDEX_IV]);
            aesCBC.init(Cipher.DECRYPT_MODE, key, iv);
            byte[] decrypted = aesCBC.doFinal(encrypted);
            decryptedMsg = new String(decrypted, ASCII);
        } catch (Exception e) {e.printStackTrace();}

        return decryptedMsg;
    }

    public static void main(String[] args) {

        String msg = "the decrypted message is this";
        String password = "pass";

        System.out.println(encrypt(msg, password));

        String encryptedMsg = "U2FsdGVkX190A5FsNTanwTKBdex29SpnH4zWkZN+Ld+MmbJgK4BH1whGIRRSpOJT";
        System.out.println(decrypt(encryptedMsg, password));
    }
}


What I have tried:

I have the following function for encryption, but its not giving the expected output..

<pre>public static String encrypt(String msg, String password) {

    String encryptedMsg =null;      
    byte[] headerSaltAndCipherText = Base64.decodeBase64(msg);      
    try {
        Cipher aesCBC = Cipher.getInstance("AES/CBC/PKCS5Padding");
        final byte[][] keyAndIV = getKeyIV(headerSaltAndCipherText, aesCBC, password);
        SecretKeySpec key = new SecretKeySpec(keyAndIV[INDEX_KEY], "AES");
        IvParameterSpec iv = new IvParameterSpec(keyAndIV[INDEX_IV]);
        aesCBC.init(Cipher.ENCRYPT_MODE, key, iv);
        encryptedMsg = Base64.encodeBase64String(aesCBC.doFinal(msg.getBytes("UTF-8")));                        
    } catch (Exception e) {e.printStackTrace();}

    return encryptedMsg;
}


Output:

+uu21LwpQq3IXRfOxpSgF8rrQHfc9owMrha/TnEsv/8=
the decrypted message is this

Expected encrypted String =
"U2FsdGVkX190A5FsNTanwTKBdex29SpnH4zWkZN+Ld+MmbJgK4BH1whGIRRSpOJT"

Actual encrypted String =
"+uu21LwpQq3IXRfOxpSgF8rrQHfc9owMrha/TnEsv/8="
Posted
Updated 31-Mar-19 7:41am
v2
Comments
k5054 31-Mar-19 10:58am    
You need to pass the same password and salt to get identical outputs e.g.
k5054@debian:~$ echo "the encrypted message is this" | openssl enc -aes-256-cbc -a -salt 
enter aes-256-cbc encryption password:
Verifying - enter aes-256-cbc encryption password:
U2FsdGVkX1+SWiZRzt/w0ZkUz3EjOFTiVtibL9m+gEeyrdtpNap3MNLS/SoWhkKP
k5054@debian:~$ echo "the encrypted message is this" | openssl enc -aes-256-cbc -a -salt 
enter aes-256-cbc encryption password:
Verifying - enter aes-256-cbc encryption password:
U2FsdGVkX19wGMNxrjGSdAXVw6cDCWTlMc9gGbVIOnf+R4DTZ7vRS7Liabcglpm9
k5054@debian:~$ echo "the encrypted message is this" | openssl enc -aes-256-cbc -a -salt 
enter aes-256-cbc encryption password:
Verifying - enter aes-256-cbc encryption password:
U2FsdGVkX1/x2Om88MSlWgHtzEuarh8UIMOHo4aA63OA8ruhRbJr4ba6/vPEv1Pr

Further, assuming that the expected string is correct when trying to decode I get
k5054@debian:~$ echo "U2FsdGVkX190A5FsNTanwTKBdex29SpnH4zWkZN+Ld+MmbJgK4BH1whGIRRSpOJT" | openssl enc -aes-256-cbc -d -a -salt
enter aes-256-cbc decryption password: [enter pass]
bad decrypt
140066702831680:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:../crypto/evp/evp_enc.c:536:
<gibberish removed>k5054@debian:~$ 

so I suspect you are not using the same password between the two runs. Try using openssl enc -a aes-256-cbc -a -S 0102030405060709 -k pass
to generate your expected encrypted string. More troublesome, though, is the fact that your two strings are of different lengths.
Member 14205873 31-Mar-19 13:40pm    
But any idea how to do it in Java, Or what is the correction needed in the encrypt function ?

The code generates "+uu21LwpQq3IXRfOxpSgF8rrQHfc9owMrha/TnEsv/8=" but i was expecting
"U2FsdGVkX190A5FsNTanwTKBdex29SpnH4zWkZN+Ld+MmbJgK4BH1whGIRRSpOJT". The decryption works fine.
Richard MacCutchan 1-Apr-19 4:24am    
It may be due to the fact that Java stores data in big-endian format, whereas the default for C# is little endian. This means that converting characters to bytes does not produce identical results. See Sha 256 in java and C# are getting different values[^].

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900