title: "javax.crypto.BadPaddingException: pad block corrupted" exception during decryption
body: <p>I am working on an existing app, coming to it having not written it.</p>
  
  <p>I get this exception (javax.crypto.BadPaddingException: pad block corrupted) during decryption of a username and password in this method:</p>
  
  <pre><code>private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
      SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
      Cipher cipher = Cipher.getInstance("AES");
      cipher.init(Cipher.DECRYPT_MODE, skeySpec);
      byte[] decrypted = cipher.doFinal(encrypted);//ERROR HERE////////////////////////////////////////////////////////////////////////////
      return decrypted;
  } 
  </code></pre>
  
  <p>The value of encrypted is a byte array with 16 numeric values between -89 and 126. Can anyone see an issue with this code? Here is all of the important code:</p>
  
  <p>Inside the Settings class (the client of the Encryptor class):</p>
  
  <pre><code>private final String ENCRYPTION_SEED = "MH8734()9Akg&amp;*3d";
  
      public void loadAuthorization() {
                  try {
                      username = getStringEncrypted(sharedPreferences, KEY_USERNAME);
                      password = getStringEncrypted(sharedPreferences, KEY_PASSWORD);
                      isAuthorized = sharedPreferences.getBoolean(KEY_IS_AUTHORIZED,
                              false);
                  } catch (Exception e) {
                      Log.e("LOAD ERROR", "Exception during loading authorization");
                  }
              }
  
      public String getStringEncrypted(SharedPreferences sharedPreferences,
              String key) {
          try {
              String valueEncrypted = sharedPreferences.getString(key, "NULL");
              String valueDecrypted = Encryptor.decrypt(ENCRYPTION_SEED + key,
                      valueEncrypted);
              return valueDecrypted;
          } catch (Exception e) {
              return "NULL";
          }
      }
  
  public void saveAuthorization() {
      SharedPreferences.Editor ed = sharedPreferences.edit();
      try {
          setStringEncrypted(ed, KEY_USERNAME, username);
          setStringEncrypted(ed, KEY_PASSWORD, password);
          ed.putBoolean(KEY_IS_AUTHORIZED, isAuthorized);
      } catch (Exception e) {
              Log.e("SAVE ERROR", "Exception during saving authorization");
          }
          ed.commit();
      }
  
  public void setStringEncrypted(SharedPreferences.Editor ed, String key,
              String value) {
          try {
              String valueEncrypted = Encryptor.encrypt(ENCRYPTION_SEED + key,
                      value);
              ed.putString(key, valueEncrypted);
          } catch (Exception e) {
              e.printStackTrace();
          }
      }
  </code></pre>
  
  <p>The full Encryptor class:</p>
  
  <pre><code>package com.boolbalabs.petlinx.settings;
  
  import java.security.SecureRandom;
  
  import javax.crypto.Cipher;
  import javax.crypto.KeyGenerator;
  import javax.crypto.SecretKey;
  import javax.crypto.spec.SecretKeySpec;
  
  public class Encryptor {
  
      private final static String HEX = "0123456789ABCDEF";
  
      private static void appendHex(StringBuffer sb, byte b) {
          sb.append(HEX.charAt((b&gt;&gt;4)&amp;0x0f)).append(HEX.charAt(b&amp;0x0f));
      }
  
      private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
          SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
          Cipher cipher = Cipher.getInstance("AES");
          cipher.init(Cipher.DECRYPT_MODE, skeySpec);
          byte[] decrypted = cipher.doFinal(encrypted);//ERROR HERE////////////////////////////////////////////////////////////////////////////
          return decrypted;
      }
  
  
      public static String decrypt(String seed, String encrypted) throws Exception {
          byte[] rawKey = getRawKey(seed.getBytes());
          byte[] enc = toByte(encrypted);
          byte[] result = decrypt(rawKey, enc);
          return new String(result);
      }
  
      private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
          SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
          Cipher cipher = Cipher.getInstance("AES");
          cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
          byte[] encrypted = cipher.doFinal(clear);
          return encrypted;
      }
  
      public static String encrypt(String seed, String cleartext) throws Exception {
          byte[] rawKey = getRawKey(seed.getBytes());
          byte[] result = encrypt(rawKey, cleartext.getBytes());
          return toHex(result);
      }
      public static String fromHex(String hex) {
          return new String(toByte(hex));
      }
  
      private static byte[] getRawKey(byte[] seed) throws Exception {
          KeyGenerator kgen = KeyGenerator.getInstance("AES");
          SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
          sr.setSeed(seed);
          kgen.init(128, sr); // 192 and 256 bits may not be available
          SecretKey skey = kgen.generateKey();
          byte[] raw = skey.getEncoded();
          return raw;
      }
  
      public static byte[] toByte(String hexString) {
          int len = hexString.length()/2;
          byte[] result = new byte[len];
          for (int i = 0; i &lt; len; i++)
              result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue();
          return result;
      }
      public static String toHex(byte[] buf) {
          if (buf == null)
              return "";
          StringBuffer result = new StringBuffer(2*buf.length);
          for (int i = 0; i &lt; buf.length; i++) {
              appendHex(result, buf[i]);
          }
          return result.toString();
      }
      public static String toHex(String txt) {
          return toHex(txt.getBytes());
      }
  }
  </code></pre>
  
  <p><a href="https://stackoverflow.com/a/19965699/3935156">This answer</a> suggests not to use SecureRandom to generate a key. The code in the app that I'm working on does use SecureRandom for that. How can I fix it?</p>
  
  <p>Here is the code that uses SecureRandom.</p>
  
  <pre><code>private static byte[] getRawKey(byte[] seed) throws Exception {
      KeyGenerator kgen = KeyGenerator.getInstance("AES");
      SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
      sr.setSeed(seed);
      kgen.init(128, sr); // 192 and 256 bits may not be available
      SecretKey skey = kgen.generateKey();
      byte[] raw = skey.getEncoded();
      return raw;
  }
  </code></pre>