Generazione della chiave di crittografia / decrittografia Java openssl

Sto usando Java 8 e sto tentando di emulare le seguenti chiamate openssl con 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

Ciao mondo

Domande:

  1. La mia implementazione non funziona. Ho visitato molte altre risposte StackOverflow ma non sono stato in grado di capire l’implementazione corretta. Qualcuno può indicarmi la giusta direzione per risolvere questo?
  2. La chiamata di sistema openssl nell’esempio precedente utilizza digest sha256. Se dovessi usare sha1, invece nell’implementazione di Java, sarebbe solo questione di cambiare PBKDF2WithHmacSHA256 con 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)); } } 

questo è l’output corrente dell’esecuzione del codice qui sopra:

 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) 

Aggiornamento : questo è il codice che ho implementato dopo aver usato questa risposta: https://stackoverflow.com/a/11786924 -> ha il resto delle costanti e l’implementazione di 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 ""; }