title: AES-256 Password Based Encryption/Decryption in Java
body: <p>I found a guide for implementing AES encryption/decryption in Java and tried to understand each line as I put it into my own solution.  However, I don't fully understand it and am having issues as a result.  The end goal is to have passphrase based encryption/decryption. I've read other articles/stackoverflow posts about this, but most do not provide enough explanation (I am very new to crypto in Java)</p>
  
  <p>My main issues right now are that even when I set <code>byte[] saltBytes = "Hello".getBytes();</code> 
  I still get a different Base64 result in the end (<code>char[] password</code> is random each time, but I read that it is safer to leave passwords in <code>char[]</code> form.  My other problem is that when the program gets to <code>decrypt()</code>, I get a NullPointerException at
   <code>byte[] saltBytes = salt.getBytes("UTF-8");</code></p>
  
  <p>Thank you in advance for any help/advice you can give me.</p>
  
  <p>The code in question:</p>
  
  <pre><code>import java.security.AlgorithmParameters;
  import java.security.NoSuchAlgorithmException;
  import java.security.SecureRandom;
  
  import javax.crypto.BadPaddingException;
  import javax.crypto.Cipher;
  import javax.crypto.IllegalBlockSizeException;
  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 EncryptionDecryption {
  
      private static String salt;
      private static int iterations = 65536  ;
      private static int keySize = 256;
      private static byte[] ivBytes;
  
      public static void main(String []args) throws Exception {
  
          char[] message = "PasswordToEncrypt".toCharArray();
          System.out.println("Message: " + message.toString());
          System.out.println("Encrypted: " + encrypt(message));
          System.out.println("Decrypted: " + decrypt(encrypt(message).toCharArray()));
      }
  
      public static String encrypt(char[] plaintext) throws Exception {
  
          salt = getSalt();
          byte[] saltBytes = salt.getBytes();
  
          SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
          PBEKeySpec spec = new PBEKeySpec(plaintext, saltBytes, iterations, keySize);
          SecretKey secretKey = skf.generateSecret(spec);
          SecretKeySpec secretSpec = new SecretKeySpec(secretKey.getEncoded(), "AES");
  
          Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
          cipher.init(Cipher.ENCRYPT_MODE, secretSpec);
          AlgorithmParameters params = cipher.getParameters();
          ivBytes = params.getParameterSpec(IvParameterSpec.class).getIV();
          byte[] encryptedTextBytes = cipher.doFinal(plaintext.toString().getBytes("UTF-8"));
  
          return DatatypeConverter.printBase64Binary(encryptedTextBytes);
      }
  
      public static String decrypt(char[] encryptedText) throws Exception {
  
          byte[] saltBytes = salt.getBytes("UTF-8");
          byte[] encryptedTextBytes = DatatypeConverter.parseBase64Binary(encryptedText.toString());
  
          SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
          PBEKeySpec spec = new PBEKeySpec(encryptedText, saltBytes, iterations, keySize);
          SecretKey secretkey = skf.generateSecret(spec);
          SecretKeySpec secretSpec = new SecretKeySpec(secretkey.getEncoded(), "AES");
  
          Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
          cipher.init(Cipher.DECRYPT_MODE, secretSpec, new IvParameterSpec(ivBytes));
  
          byte[] decryptedTextBytes = null;
  
          try {
              decryptedTextBytes = cipher.doFinal(encryptedTextBytes);
          }   catch (IllegalBlockSizeException e) {
              e.printStackTrace();
          }   catch (BadPaddingException e) {
              e.printStackTrace();
          }
  
          return decryptedTextBytes.toString();
  
      }
  
      public static String getSalt() throws Exception {
  
          SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
          byte[] salt = new byte[20];
          sr.nextBytes(salt);
          return salt.toString();
      }
  }
  </code></pre>