Greetings. For training purposes, I wrote a password storage program in Java using AES encryption. Wrote a class that uses methods from the javax.crypto package. In an application on Windows, everything works fine, encrypts and decrypts. I decided to make a mobile version of this application on Android, for aes I used the same class, but there was a problem - the data is not decrypted, throws an exception indicating a decryption error. Why it happens?

An exception:

javax.crypto.BadPaddingException: pad block corrupted

My class code:

public class AES { public static SecretKeySpec getSecretKeySpec(String data) { try { SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); sr.setSeed(data.getBytes()); KeyGenerator kg = KeyGenerator.getInstance("AES"); kg.init(128, sr); return (new SecretKeySpec((kg.generateKey()).getEncoded(), "AES")); } catch (Exception e) { System.out.println("Ошибка ΠΏΡ€ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠΈ сСкрСтного ΠΊΠ»ΡŽΡ‡Π°!"); } return null; } public static byte[] Encode(SecretKeySpec sks, byte[] data) { try { Cipher c = Cipher.getInstance("AES"); c.init(Cipher.ENCRYPT_MODE, sks); return c.doFinal(data); } catch (Exception e){ System.out.println("Ошибка ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΡˆΠΈΡ„Ρ€ΠΎΠ²Π°Π½ΠΈΡ!"); } return null; } public static byte[] Decode(SecretKeySpec sks, byte[] data) { try { Cipher c=Cipher.getInstance("AES"); c.init(Cipher.DECRYPT_MODE,sks); return c.doFinal(data); } catch (Exception e) { System.out.println("Ошибка ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ Π΄Π΅ΡˆΠΈΡ„Ρ€ΠΎΠ²ΠΊΠΈ"); } return null; } } 
  • one
    Where are all the experts? - Dimarik
  • one
    If possible, publish the solution found in response to your question . I am sure it will help many of your colleagues in the future. - Nicolas Chabanovsky ♦

2 answers 2

An article on this topic. And also the answers to SO: one , two, and many others. In short, your Android getSecretKeySpec method will return a new key on every call. A quick, but not recommended solution is to replace SecureRandom.getInstance("SHA1PRNG") with SecureRandom.getInstance("SHA1PRNG", "Crypto") . A better option is to change the body of the method to something like:

 SecureRandom random = new SecureRandom(); byte[] salt = new byte[8]; sr.nextBytes(salt); KeySpec keySpec = new PBEKeySpec(data.toCharArray(), salt, 1000, 256); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); byte[] keyBytes = keyFactory.generateSecret(keySpec).getEncoded(); SecretKey key = new SecretKeySpec(keyBytes, "AES"); return key; 

    I found this option:

     byte[] result; SecretKeySpec sks=new SecretKeySpec(keyBytes,"AES"); Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding"); c.init(Cipher.ENCRYPT_MODE, sks, new IvParameterSpec(ivBytes)); result=c.doFinal(data); return result; 

    It uses the initialization vector. Everything works fine on the android and on the PC, besides, they say that this algorithm is more crack-proof.