So I've seen a lot of examples, and done a lot of googling, and looked at examples on Stack Overflow... and I need help. I've got an Android application and I'm storing username and passwords on the device, and I need to encrypt them AES 256. From looking at examples, this is what I have so far:
public class Security { Cipher ecipher; Cipher dcipher; // 8-byte Salt byte[] salt = { (byte)0xA9, (byte)0x9B, (byte)0xC8, (byte)0x32, (byte)0x56, (byte)0x35, (byte)0xE3, (byte)0x03 }; // Iteration count int iterationCount = 19; public Security (String passPhrase) { try { // Create the key KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), salt, iterationCount); SecretKey key = SecretKeyFactory.getInstance( "PBEWithSHAAndAES").generateSecret(keySpec); ecipher = Cipher.getInstance(key.getAlgorithm()); dcipher = Cipher.getInstance(key.getAlgorithm()); // Prepare the parameter to the ciphers AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount); // Create the ciphers ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec); dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec); } catch (Exception e) { e.printStackTrace(); } } public String encrypt(String str) { try { // Encode the string into bytes using utf-8 byte[] utf8 = str.getBytes("UTF8"); // Encrypt byte[] enc = ecipher.doFinal(utf8); // Encode bytes to base64 to get a string return Base64.encodeToString(enc, Base64.DEFAULT); } catch (Exception e) { e.printStackTrace(); return null; } } public String decrypt(String str) { try { // Decode base64 to get bytes byte[] dec = Base64.decode(str, Base64.DEFAULT); // Decrypt byte[] utf8 = dcipher.doFinal(dec); // Decode using utf-8 return new String(utf8, "UTF8"); } catch (Exception e) { e.printStackTrace(); return null; } } }
I'm trying to make it password based, so a user will create an account the first time using the username and password needed to communicate back to the server, and create a PIN that will be used as the key for these credentials stored in the database.
What I'm mainly concerned about is does this look secure? I know a fixed salt is bad, how do I fix that?
I know there's been like a billion questions about this, but I want someone to just come out and say "THIS IS SECURE" or "THIS IS NOT SECURE, CHANGE THIS"
Thanks!
EDIT:
So this is the code I have so far, and it seems to be working...
public class Security { Cipher ecipher; Cipher dcipher; byte[] salt = new byte[8]; int iterationCount = 200; public Security(String passPhrase) { try { // generate a random salt SecureRandom random = new SecureRandom(); random.nextBytes(salt); // Create the key KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), salt, iterationCount); SecretKey key = SecretKeyFactory.getInstance( "PBEWithSHA256And256BitAES-CBC-BC").generateSecret(keySpec); ecipher = Cipher.getInstance(key.getAlgorithm()); dcipher = Cipher.getInstance(key.getAlgorithm()); // Prepare the parameter to the ciphers AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount); // Create the ciphers ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec); dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec); } catch (Exception e) { e.printStackTrace(); } } public String encrypt(String str) { try { // Encode the string into bytes using utf-8 byte[] utf8 = str.getBytes("UTF8"); // Encrypt byte[] enc = ecipher.doFinal(utf8); // Encode bytes to base64 to get a string return Base64.encodeToString(enc, Base64.DEFAULT); } catch (Exception e) { e.printStackTrace(); return null; } } public String decrypt(String str) { try { // Decode base64 to get bytes byte[] dec = Base64.decode(str, Base64.DEFAULT); // Decrypt byte[] utf8 = dcipher.doFinal(dec); // Decode using utf-8 return new String(utf8, "UTF8"); } catch (Exception e) { e.printStackTrace(); return null; } } public int getIterationCount() { return iterationCount; } public String getSalt() { return Base64.encodeToString(salt, Base64.DEFAULT); } }
I used this code to test it:
Security s = new Security(pinBox.getText().toString()); String encrypted = s.encrypt(passwordBox.getText().toString()); String decrypted = s.decrypt(encrypted); builder.setMessage("pin: " + pinBox.getText().toString() + "\n" + "password: " + passwordBox.getText().toString() + "\n" + "encrypted: " + encrypted + "\n" + "decrypted: " + decrypted + "\n" + "salt: " + s.getSalt());
So I don't need to worry about an initialization vector? Or specifically hardcode a Cipher algorithm?
Thanks again!