问题
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
回答1:
Note that you may not need to re-generate a random IV as long as you change the salt and therefore the resulting key. If you do not change the salt each time you (re-)encrypt then you do need a separate IV or you may leak information to an adversary.
You can keep the salt and IV the same. But it is generally easier to derive the IV together with the key from the password and salt. If you use PBKDF2 with a SHA-512 hash this is easy: just take 128, 192 or 256 bits of AES key from the resulting hash and then take another 128 subsequent bits as IV and use that.
If you need multiple keys or if you use a smaller hash then you may need to derive more keys from the result of PBKDF2. In that case it is best to mark the result of PBKDF2 as a master secret and perform N key derivations from it, one for each key and one for the IV. You could use e.g. HKDF for this, which Bouncy Castle has an implementation of (for which I provided the initial source code).
来源:https://stackoverflow.com/questions/48709703/reusing-pbkdf2-salt-for-aes-gcm-as-iv-dangerous