Java openssl encryption / decryption key generation [duplicate]

对着背影说爱祢 提交于 2019-11-26 11:28:42

问题


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:

  1. 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?
  2. 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 PBKDF2WithHmacSHA256 with PBKDF2WithHmacSHA1?

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!