Android AES 256-bit encryption data

So, I saw a lot of examples and did a lot to search on Google, and looked at the examples on Stack Overflow ... and I need help. I have an Android app and I store the username and passwords on the device and I need to encrypt them with AES 256. From a look at the examples, this is what I still have:

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 am trying to do this based on a password, so the user will first create an account using the username and password required to communicate with the server and create a PIN code that will be used as a key for these credentials stored in the database.

What I'm mostly worried about is it looking safe? I know that fixed salt is bad, how can I fix it?

I know that it was like a billion questions, but I want someone to just go out and say, “THIS IS SAFE” or “THIS IS NOT SAFE, CHANGE THIS”

Thanks!


EDIT:

So this is the code that I still have, and it seems to work ...

 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 do not need to worry about the initialization vector? Or, in particular, the hardcode encryption algorithm?

Thanks again!

+6
source share
1 answer

EDIT: although the code below is correct, what you have does basically the same thing, with an IV derived from a password, so you don't need to store it separately.

Does your code work as expected? For actual encryption / decryption, you would like to use AES, most likely in CBC mode. Then you need IV, so it will become something like this:

 ecipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); byte[] iv = new byte[IV_LENGTH]; SecureRandom random = new SecureRandom(); random.nextBytes(iv); ecipher.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(iv)); byte[] enc = ecipher.doFinal(utf8); 

Whether this is safe depends on what you use it for. The purpose of the salt is to obstruct the brute force of the phrase: if it is random, the attacker cannot use the pre-generated password tables (keyphraase-> key). If you are not too worried about such an attack, you can leave it fixed. If you decide to make it random, just save it with encrypted data. Same thing with IV.

+5
source

Source: https://habr.com/ru/post/913459/


All Articles