title: Java AES encryption and decryption with static secret
body: <p>I have an application that needs to store some secret passwords in a configuration file such as database and ftp passwords/detail. I've looked around and found a lot of encryption/decryption solutions using AES, but I can't seem to figure out how to make it work without changing the key. That means I can encrypt and decrypt (using the same SecretKey), but to maintain persistence across restarts etc. I can't seem to make the SecretKey stay the same. The example below shows my methods working:</p>
  
  <pre><code>String secret = Encryptor.encrpytString("This is secret");
  String test = Encryptor.decrpytString(secret);
  System.out.println(test); //This is secret is printed
  </code></pre>
  
  <p>So far so good. However if I run it once I might get the value of '2Vhht/L80UlQ184S3rlAWw==' as my secret, the next time it is 'MeC4zCf9S5wUUKAu8rvpCQ==', so presumably the key is changing. I'm assuming I am applying some counter-intuative logic to the problem and would appreciate if someone can shed some light on either a) what I'm doing wrong, or b) a solution that would allow me to store the password information encrypted and retrievable with the information provided.</p>
  
  <p>My methods are as follows:</p>
  
  <pre><code>private static final String salt = "SaltySalt";
  
  private static byte [] ivBytes = null;
  
  private static byte[] getSaltBytes() throws Exception {
      return salt.getBytes("UTF-8");
  }
  
  private static char[] getMasterPassword() {
      return "SuperSecretPassword".toCharArray();
  }
  
  private static byte[] getIvBytes() throws Exception {
      if (ivBytes == null) {
          //I don't have the parameters, so I'll generate a dummy encryption to create them
          encrpytString("test");
      }
      return ivBytes;
  }
  
  public static String encrpytString (String input) throws Exception {
      SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
      PBEKeySpec spec = new PBEKeySpec(getMasterPassword(), getSaltBytes(), 65536,256);
      SecretKey secretKey = factory.generateSecret(spec);
      SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
      cipher.init(Cipher.ENCRYPT_MODE, secret);
      ivBytes = cipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();
      byte[] encryptedTextBytes = cipher.doFinal(input.getBytes("UTF-8"));
      return DatatypeConverter.printBase64Binary(encryptedTextBytes);        
  }
  
  public static String decrpytString (String input) throws Exception {
      byte[] encryptedTextBytes = DatatypeConverter.parseBase64Binary(input);
      SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
      PBEKeySpec spec = new PBEKeySpec(getMasterPassword(), getSaltBytes(), 65536, 256);
      SecretKey secretKey = factory.generateSecret(spec);
      SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
      cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(getIvBytes()));
      byte[] decryptedTextBytes = cipher.doFinal(encryptedTextBytes);
      return new String(decryptedTextBytes);
  }
  </code></pre>
  
  <p>Thanks for the help!</p>