Android cipher does not decrypt the first 16 bytes / characters of encrypted data

I am working on file encryption / decryption. I am using a simple .txt file for testing. When I select a file from the application and select for encryption, all file data is encrypted. However, when I decrypt only part of the files, the data is decrypted. For some reason, the first 16 bytes / characters are not decrypted.

Contents of test_file.txt: "This sentence is used to check file encryption/decryption results."

encryption result: "¾mÁSTÐÿT:Y„"O¤]ÞPÕµß~ëqrÈb×ßq²¨†ldµJ,O|56\e^-'@þûÝû"

decryption result: "£ÿÒÜÑàh]VÄþ„- used to check file encryption/decryption results."

There are no errors in logcat.

What am I doing wrong?

File Encryption Method:

 public void encryptFile(String password, String filePath) { byte[] encryptedFileData = null; byte[] fileData = null; try { fileData = readFile(filePath);//method provided below // 64 bit salt for testing only byte[] salt = "goodsalt".getBytes("UTF-8"); SecretKey key = generateKey(password.toCharArray(), salt);//method provided below byte[] keyData = key.getEncoded(); SecretKeySpec sKeySpec = new SecretKeySpec(keyData, "AES"); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, sKeySpec); encryptedFileData = cipher.doFinal(fileData); saveData(encryptedFileData, filePath);//method provided below } catch (Exception e) { e.printStackTrace(); } } 

The way to read the contents of a file:

 public byte[] readFile(String filePath) { byte[] fileData; File file = new File(filePath); int size = (int) file.length(); fileData = new byte[size]; try { BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(file)); inputStream.read(fileData); inputStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return fileData; } 

Secret key generation method:

 private SecretKey generateKey(char[] password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException { // Number of PBKDF2 hardening rounds to use. Larger values increase computation time. You // should select a value that causes computation to take >100ms. final int iterations = 1000; // Generate a 256-bit key final int outputKeyLength = 256; SecretKeyFactory secretKeyFactory; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // Use compatibility key factory -- only uses lower 8-bits of passphrase chars secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1And8bit"); } else { // Traditional key factory. Will use lower 8-bits of passphrase chars on // older Android versions (API level 18 and lower) and all available bits // on KitKat and newer (API level 19 and higher). secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); } KeySpec keySpec = new PBEKeySpec(password, salt, iterations, outputKeyLength); return secretKeyFactory.generateSecret(keySpec); } 

The way to save encrypted / decrypted data to a file:

 private void saveData(byte[] newFileData, String filePath) { File file = new File(filePath); try { BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(file)); outputStream.write(newFileData); outputStream.flush(); outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } 

File decryption method:

 public void decryptFile(String password, String filePath) { byte[] decryptedFileData = null; byte[] fileData = null; try { fileData = readFile(filePath); byte[] salt = "goodsalt".getBytes("UTF-8");//generateSalt(); SecretKey key = generateKey(password.toCharArray(), salt); byte[] keyData = key.getEncoded(); SecretKeySpec sKeySpec = new SecretKeySpec(keyData, "AES"); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, sKeySpec); decryptedFileData = cipher.doFinal(fileData); saveData(decryptedFileData, filePath); } catch (Exception e) { e.printStackTrace(); } } 

This line of code encrypts the file:

 //simple password for testing only encryptor.encryptFile("password", "storage/emulated/0/Download/test_file.txt"); 

This line decodes the file:

 encryptor.decryptFile("password", "storage/emulated/0/Download/test_file.txt"); 

Edit : thanks to DarkSquirrel42 and Oncaphillis. You guys are awesome!

Adding this line of code to encrypt and decrypt functions solved my problem.

 //note: the initialization vector (IV) must be 16 bytes in this case //so, if a user password is being used to create it, measures must //be taken to ensure proper IV length; random iv is best and should be //stored, possibly alongside the encrypted data IvParameterSpec ivSpec = new IvParameterSpec(password.getBytes("UTF-8")); 

and then

 cipher.init(Cipher.XXXXXXX_MODE, sKeySpec, ivSpec); 
+5
source share
2 answers

your problem has something to do with the encryption mode of operation ... cbc or encryption block lock mode

In general, CBC is simple ... take everything that was in your previous encryiption block, and xor on the current input before encrypting it

for the first block, we obviously have a problem ... there is no previous block ... so we introduce something called IV ... an initialization vector ... a block step of random bytes ...

now ... as you can imagine, you will need the same IV when you want to decrypt ...

since you are not saving this, the implementation of AES will give you a random IV every time ...

therefore, you do not have all the information to decrypt block 1 ... which is the first 16 bytes in the case of AES ...

when processing CBC mode data, there is always a good choice to just add the used IV to your output in cypertext ... IV will be just random ... it's not a secret ...

+5
source

Like @ ÐarkSquirrel42 already indicates that the en / decrytion procedure for CBC seems to interpret the first 16 bytes as an initialization vector. This worked for me:

  // got to be random byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; IvParameterSpec ivspec = new IvParameterSpec(iv); cipher.init(Cipher.XXXXX_MODE, sKeySpec,ivspec); 
+2
source

Source: https://habr.com/ru/post/1206957/


All Articles