This question already has an answer here:
I'm using Java 8 and I'm attempting to emulate the following openssl calls with Java.
Encrypt:
echo -n 'hello world' | openssl enc -a -aes-256-cbc -md sha256 -pass pass:97DE:4F76
U2FsdGVkX18PnO/NLSxJ1pg6OKoLyZApMz7aBRfKhJc=
Decrypt:
echo U2FsdGVkX18PnO/NLSxJ1pg6OKoLyZApMz7aBRfKhJc= | openssl enc -d -a -aes-256-cbc -md sha256 -pass pass:97DE:4F76
hello world
Questions:
- My implementation doesn't work. I've visited many other StackOverflow answers but wasn't able to figure out the right implementation. Can anyone point me out in the right direction for solving this?
- The openssl system call in the example above uses digest sha256. If I were to use sha1, instead in the Java implemementation, would it be just a matter of changing PBKDF2WithHmacSHA256withPBKDF2WithHmacSHA1?
Test.java
package test;
import java.security.spec.KeySpec;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
public class Test {
    public static final String PASSWORD = "97DE:4F76";
    public static String encryptString(String clearText, String password) {
        return "";
    }
    // echo U2FsdGVkX18PnO/NLSxJ1pg6OKoLyZApMz7aBRfKhJc= | openssl enc -d -a -aes-256-cbc -md sha256 -pass pass:97DE:4F76
    //
    // see https://stackoverflow.com/a/992413, https://stackoverflow.com/a/15595200,
    // https://stackoverflow.com/a/22445878, https://stackoverflow.com/a/11786924
    public static String decryptString(String cypherText, String password) {
        byte[] dataBase64 = DatatypeConverter.parseBase64Binary(cypherText);
        byte[] salt = {
                (byte)0x0, (byte)0x0, (byte)0x0, (byte)0x0,
                (byte)0x0, (byte)0x0, (byte)0x0, (byte)0x0
        };
        try {
            // generate the key
            SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); // "PBKDF2WithHmacSHA1"
            KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256);
            SecretKey tmp = factory.generateSecret(spec);
            SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
            // decrypt the message
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            byte[] iv = cipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();
            cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
            byte[] decrypted = cipher.doFinal(dataBase64);
            String answer = new String(decrypted, "UTF-8");
            return answer;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return "";
    }
    public static void main(String[] args) {
        System.out.println(decryptString("U2FsdGVkX18PnO/NLSxJ1pg6OKoLyZApMz7aBRfKhJc=", PASSWORD));
    }
}
this is the current output of running the code above:
java.security.InvalidKeyException: Illegal key size     at
         javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1039)  at
         javax.crypto.Cipher.init(Cipher.java:1393)     at
         javax.crypto.Cipher.init(Cipher.java:1327)     at
         test.Test.decryptString(Test.java:42)  at
         test.Test.main(Test.java:55)
Update: this is the code I ended up implementing after I used this answer: https://stackoverflow.com/a/11786924 -> has the rest of the constants and implementation of EVP_BytesToKey
public static String decryptString(String cypherText, String password) {
        try {
            // decode the base64 cypherText into salt and encryptedString
            byte[] dataBase64 = DatatypeConverter.parseBase64Binary(cypherText);
            byte[] salt = Arrays.copyOfRange(dataBase64, SALT_OFFSET, SALT_OFFSET + SALT_SIZE);
            byte[] encrypted = Arrays.copyOfRange(dataBase64, CIPHERTEXT_OFFSET, dataBase64.length);
            System.out.println("dataBase64 = " + new String(dataBase64));
            System.out.println("salt: " + new BigInteger(1, salt).toString(16));
            System.out.println("encrypted: " + new BigInteger(1, encrypted).toString(16));    
            // --- specify cipher and digest for EVP_BytesToKey method ---
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            MessageDigest sha1 = MessageDigest.getInstance("SHA-256");
            // create key and IV
            final byte[][] keyAndIV = EVP_BytesToKey(
                    KEY_SIZE_BITS / Byte.SIZE,
                    cipher.getBlockSize(),
                    sha1,
                    salt,
                    password.getBytes("ASCII"),
                    ITERATIONS);
            SecretKeySpec key = new SecretKeySpec(keyAndIV[INDEX_KEY], "AES");
            IvParameterSpec iv = new IvParameterSpec(keyAndIV[INDEX_IV]);
            // initialize the Encryption Mode
            cipher.init(Cipher.DECRYPT_MODE, key, iv);
            // decrypt the message
            byte[] decrypted = cipher.doFinal(encrypted);
            String answer = new String(decrypted, "UTF-8"); // should this be "ASCII"?
            return answer;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return "";
    }
来源:https://stackoverflow.com/questions/34502705/java-openssl-encryption-decryption-key-generation