I'm developing an encryption utility class to be reused for common operations.
A very common case is to encrypt a plaintext with a user-provided password.
In this case, I'm using PBKDF2 to derive a valid AES key, then use it in GCM mode to encrypt the plaintext.
Some code:
// IV_LEN = 96
// ITERATIONS = 1000 ~ 4000
// KEY_LEN = 128 ~ 256
// TAG_LEN = 128
public static String encrypt(byte[] plain, char[] password) throws GeneralSecurityException
{
SecureRandom rng = SecureRandom.getInstanceStrong();
byte[] iv = new byte[IV_LEN / 8];
rng.nextBytes(iv);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
SecretKey derivedKey = factory.generateSecret(new PBEKeySpec(password, iv, ITERATIONS, KEY_LEN));
SecretKey secretKey = new SecretKeySpec(derivedKey.getEncoded(), "AES");
Cipher c = Cipher.getInstance("AES/GCM/NoPadding");
c.init(Cipher.ENCRYPT_MODE, secretKey, new GCMParameterSpec(TAG_LEN, iv));
byte[] encrypted = c.doFinal(plain);
Encoder encoder = Base64.getUrlEncoder().withoutPadding();
return encoder.encodeToString(iv) + ":" + encoder.encodeToString(encrypted);
}
Currently, I'm using the PBKDF2 salt (96 bit - SecureRandom) also as the IV for AES/GCM encryption.
Both the salt and IV can be public, but they shouldn't be reused.
Is it to be understood that they shouldn't be reused within the same Feature/Service/Algorithm, or that they shouldn't be reused anywhere?
It's very easy to modify this method to generate different salt and IV, but is there a reason to do it?
Thanks