Java AES 128 crittografia in modo diverso per openssl

Abbiamo riscontrato una strana situazione in cui il metodo di crittografia che stiamo utilizzando in Java produce un output diverso da openssl, nonostante appaia identico nella configurazione.

Usando la stessa chiave e IV, il testo “La volpe MARRONE veloce salta sul cane pigro!” crittografa alle stringhe di base64 …

openssl: A8cMRIrDVnBYj2+XEKaMOBQ1sufjptsAf58slR373JTeHGPWyRqJK+UQxvJ1B/1L

Java: A8cMRIrDVnBYj2+XEKaMOBQ1sufjptsAf58slR373JTEVySz5yJLGzGd7qsAkzuQ

Questa è la nostra chiamata openssl …

 #!/bin/bash keySpec="D41D8CD98F00B2040000000000000000" ivSpec="03B13BBE886F00E00000000000000000" plainText="The quick BROWN fox jumps over the lazy dog!" echo "$plainText">plainText openssl aes-128-cbc -nosalt -K $keySpec -iv $ivSpec -e -in plainText -out cipherText base64 cipherText > cipherText.base64 printf "Encrypted hex dump = " xxd -p cipherText | tr -d '\n' printf "\n\n" printf "Encrypted base64 = " cat cipherText.base64 

E questo è il nostro Java …

 private static void runEncryption() throws Exception { String plainText = "The quick BROWN fox jumps over the lazy dog!"; Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); SecretKeySpec keySpec = new SecretKeySpec(hexToBytes("D41D8CD98F00B2040000000000000000"), 0, 16, "AES"); IvParameterSpec ivSpec = new IvParameterSpec(hexToBytes("03B13BBE886F00E00000000000000000")); cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); byte[] encrypted = cipher.doFinal(plainText.getBytes("UTF-8")); String encryptedHexDump = bytesToHex(encrypted); String encryptedBase64 = new String(DatatypeConverter.printBase64Binary(encrypted)); System.out.println("Encrypted hex dump = " + encryptedHexDump); System.out.println(""); System.out.println("Encrypted base64 = " + encryptedBase64); } private static byte[] hexToBytes(String s) { int len = s.length(); byte[] data = new byte[len / 2]; for (int i = 0; i < len; i += 2) data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16)); return data; } final protected static char[] hexArray = "0123456789abcdef".toCharArray(); public static String bytesToHex(byte[] bytes) { char[] hexChars = new char[bytes.length * 2]; for (int j = 0; j >> 4]; hexChars[j * 2 + 1] = hexArray[v & 0x0F]; } return new String(hexChars); } 

uscita oopenssl

 Encrypted hex dump = 03c70c448ac35670588f6f9710a68c381435b2e7e3a6db007f9f2c951dfbdc94de1c63d6c91a892be510c6f27507fd4b Encrypted base64 = A8cMRIrDVnBYj2+XEKaMOBQ1sufjptsAf58slR373JTeHGPWyRqJK+UQxvJ1B/1L 

Uscita Java

 Encrypted hex dump = 03c70c448ac35670588f6f9710a68c381435b2e7e3a6db007f9f2c951dfbdc94c45724b3e7224b1b319deeab00933b90 Encrypted base64 = A8cMRIrDVnBYj2+XEKaMOBQ1sufjptsAf58slR373JTEVySz5yJLGzGd7qsAkzuQ 

Ci manca qualcosa di ovvio? O c’è qualche complessità nascosta?

È davvero un problema fornire una stringa o un file. Se metti un “\ n” alla fine del tuo codice Java, il risultato sarà lo stesso di openSSL.

Credo che la differenza sia il padding, non i dati reali crittografati.

Hai provato a decifrare le stringhe?

Credo che si presenteranno allo stesso modo.

Perché l’imbottitura è diversa? perché lo stanno implementando in modo diverso, o perché viene fornito un file, mentre l’altro una stringa, che alla fine, quando li leggi, non sono la stessa cosa (uno ha un indicatore EoF, per esempio).

BTW: Poiché è CBC, Cipher Block Chaining, l’intero blocco è influenzato da questa differenza di riempimento