I used to encrypt/decrypt using below code, I used to use below code to encrypt while saving user data to DB(email, phone) and I used to fetch from db and decrypt in the response back to user. Catch out here is I used to use fixed IV and Secret so no matter how many ever times we encrypt a given a string it always to used to generate same Cipher text. We have a API to get user by email. We used to accept email in the path param and encrypt it and used the Cipher text in the DB query to find the user by email.
New change: Everything used to work well until now. But recently we changed the encryption/decryption algorithm to work with random IV. So in order to get the extract value back from ciperText we started storing the dynamic IV in the Cipher text itself. The format followed is below {Base64_Encoded_IV}Encoded_Cipher_Text while saving ciphet text to database.
Issue: The problem with this approach is that in the API that I talked above to get user data by email address. We accept the email and encrypt to get user data but this time it generates a new cipheText altogether because it uses a new IV to encrypt the email accepted to fetch the user data.
Note: I am looking for solutions around this. If anyone can throw light up on.
Eg: Text: [email protected]
EncryptedValue stored in db: {KF0RTjdsfd979DNJHKnlkRjkeg==}x07RYBVdfVQDS/fXaK/tHnJc7MAjdix4nA==
public class CipherUtils {
private CipherUtils() throws IllegalAccessException {
throw new IllegalAccessException("CipherUtil mustn't be instantiated");
}
private static final MyLogger logger = MyLogManager.getLogger(CipherUtils.class);
private static final SecretKeySpec SECRET_KEY;
private static final String AES_ALG = "AES";
private static final String IV = "0B4E9000B915F875";
private static final String TRANSFORMATION = "AES/GCM/NoPadding";
private static final String ENCRYPTION_KEY = "d3BhcKLHLKhbsddffbG9jYasdfadsJ4";
private static final GCMParameterSpec GCM_PARAMETER_SPEC;
static {
SECRET_KEY = new SecretKeySpec(ENCRYPTION_KEY.getBytes(), AES_ALG);
GCM_PARAMETER_SPEC = new GCMParameterSpec(128, IV.getBytes());
}
public static String encrypt(final String strToEncrypt) {
if (StringUtils.isBlank(strToEncrypt)) {
return strToEncrypt;
}
try {
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.ENCRYPT_MODE, SECRET_KEY, GCM_PARAMETER_SPEC);
return Base64.getEncoder().encodeToString(cipher.doFinal(strToEncrypt.getBytes()));
} catch (NoSuchPaddingException | IllegalBlockSizeException | NoSuchAlgorithmException | BadPaddingException |
InvalidKeyException | InvalidAlgorithmParameterException e) {
logger.error(ENCRYPTION_ERROR_MSG, e)
.log();
throw new EncryptDecryptException(e.getMessage());
}
}
public static String decrypt(final String strToDecrypt) {
if (StringUtils.isBlank(strToDecrypt)) {
return strToDecrypt;
}
try {
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.DECRYPT_MODE, SECRET_KEY, GCM_PARAMETER_SPEC);
return new String(cipher.doFinal(Base64.getDecoder().decode(strToDecrypt)));
} catch (NoSuchPaddingException | IllegalBlockSizeException | NoSuchAlgorithmException |
BadPaddingException | InvalidKeyException | InvalidAlgorithmParameterException e) {
logger.error(DECRYPTION_ERROR_MSG, e)
.log();
throw new EncryptDecryptException(e.getMessage(), null);
}
}
}