Java openssl加密/解密密钥生成

我正在使用Java 8,我试图用Java模拟以下openssl调用。

加密:

echo -n 'hello world' | openssl enc -a -aes-256-cbc -md sha256 -pass pass:97DE:4F76

U2FsdGVkX18PnO / NLSxJ1pg6OKoLyZApMz7aBRfKhJc =

解密:

echo U2FsdGVkX18PnO/NLSxJ1pg6OKoLyZApMz7aBRfKhJc= | openssl enc -d -a -aes-256-cbc -md sha256 -pass pass:97DE:4F76

你好,世界

问题:

  1. 我的实现不起作用。 我已经访问了许多其他StackOverflow答案,但未能找到正确的实现。 任何人都可以指出我正确的方向来解决这个问题吗?
  2. 上例中的openssl系统调用使用摘要sha256。 如果我使用sha1,而不是Java实现,那么只需PBKDF2WithHmacSHA256 PBKDF2WithHmacSHA1更改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)); } } 

这是运行上面代码的当前输出:

 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) 

更新 :这是我在使用此答案后最终实现的代码: https ://stackoverflow.com/a/11786924 – >具有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 ""; }