Reputation: 51
I'm currently implementing a symmetric en-/decryption using AES 256 on Android, inspired by this post: Java 256bit AES Encryption. The purpose of my implementation is that I want to encrypt the data in a database.
For key generation I use the following constructor which takes a char[] password:
public Cryptography(char[] password) throws NoSuchAlgorithmException,
InvalidKeySpecException, NoSuchPaddingException {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWITHSHA256AND256BITAES-CBC-BC");
KeySpec spec = new PBEKeySpec(password, salt, 1024, 256);
secretKey = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
cipher = Cipher.getInstance(AES/CBC/PKCS5Padding);
}
So when I start my Activity in Android I initialize a new instance of my Cryptography class and therefore get a generated key. The salt is a fixed random byte[] of 16 bytes. So that means that I always get the same key. The reason for that later.
Now after I got an object in one Activity I can use the following encrypt and decrypt methods with always the same key:
public byte[] encrypt(String cleartext) throws InvalidKeyException,
IllegalBlockSizeException, BadPaddingException,
UnsupportedEncodingException, InvalidParameterSpecException {
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] encText = cipher.doFinal(cleartext.getBytes(CHARSET_NAME));
byte[] iv = cipher.getParameters()
.getParameterSpec(IvParameterSpec.class).getIV();
byte[] enc = new byte[IV_SIZE + encText.length];
for (int i = 0; i < enc.length; i++) {
if (i < IV_SIZE)
enc[i] = iv[i];
else if (i < enc.length)
enc[i] = encText[i - IV_SIZE];
}
return enc;
}
public String decrypt(byte[] encryptedText) throws InvalidKeyException,
InvalidAlgorithmParameterException, UnsupportedEncodingException,
IllegalBlockSizeException, BadPaddingException {
byte[] iv = new byte[IV_SIZE];
byte[] dec = new byte[encryptedText.length - IV_SIZE];
for (int i = 0; i < encryptedText.length; i++) {
if (i < IV_SIZE)
iv[i] = encryptedText[i];
else if (i < encryptedText.length)
dec[i - IV_SIZE] = encryptedText[i];
}
cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(iv));
return new String(cipher.doFinal(dec), CHARSET_NAME);
}
As you can see, I save a fresh new IV along with the ciphertext everytime I encrypt a message.
In conclusion: I use ONE encryption key, ONE random salt and a new IV for EVERY field in a database table.
First I wanted to generate a new key with a new salt and a new IV everytime I encrypt ONE field in the database table and save the required salt and IV with along with the ciphertext, or at least for one table row. But the reason why I did it like above mentioned is, because generating a key on an Android device takes to much time. I tested in on an emulator, but it took about two seconds for generating a key. This is why I just generated one key when an Activity is started.
So finally my question: With my approach, is it secure enough by using just one key, but fresh random IV's for every message? Currently, I don't see another way to make it as secure as possible by keeping it in balance with performance.
I hope it is clear enough what I wrote and somebody could give me some advice on that.
Kind Regards
xoidberg
Upvotes: 3
Views: 2816
Reputation: 1683
I believe the question is not relevant for you (xoidberg), but it might be relevant for some other people.
From what I understand - you use the salt to create a (securely random) key from password. If every user has a random (different) salt - it is ok. Otherwise it might be problematic.
I believe that this is what you did, so it seems (to me) to be ok.
I just want to mention that usually you want to use salts when you save hash function of some values (usually password). Hash functions like MD5 or the SHAs do not have a key, and you must add randomness for this purpose. This is why you need the salt, and this is why in this case you usually need random salt for each value (if you just save passwords hashes with the same salt, one can detect the most common hashes and learn that the password of the users with the most common hash is 123456). In your case - every user needs a unique salt.
About the IV - you really need a random one each time (so it's ok).
Upvotes: 1