'AES secret key lost on application start
I am using AES encryption and have encrypted a message with a key generated from key generator. Encryption and Decryption is working as expected. But when the application is restarted and I am trying to decrypt the same message again, it is giving error as the secret key is not stored anywhere which was used to encrypt the message and on restart of application we don't have that secret key anymore.
Cannot invoke javax.crypto.Cipher.getIV() because AES.encryptionCipher is null.
I don't want to store the secret key in database. Can I store the secretKey and write it in a file and place that file in src/main/resources folder.Will it be a good approach?
Is there any other place where I could store the secret key and at the time of decrypting the meesages I could load the key from that place and decrypt messages.
This is what I have done so far.
private static SecretKey key;
private static int KEY_SIZE = 128;
private static int T_LEN = 128;
private static Cipher encryptionCipher;
public static String encrypt(String message) {
byte[] messageInBytes = message.getBytes();
byte[] encryptedBytes = null;
try {
KeyGenerator generator = KeyGenerator.getInstance("AES");
generator.init(KEY_SIZE);
key = generator.generateKey();
encryptionCipher = Cipher.getInstance("AES/GCM/NoPadding");
encryptionCipher.init(Cipher.ENCRYPT_MODE, key);
encryptedBytes = encryptionCipher.doFinal(messageInBytes);
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
e.printStackTrace();
}
catch (IllegalBlockSizeException | BadPaddingException | InvalidKeyException e) {
e.printStackTrace();
}
return encode(encryptedBytes);
}
public static String decrypt(String encryptedMessage) {
byte[] messageInBytes = decode(encryptedMessage);
byte[] decryptedBytes = null;
try {
Cipher decryptionCipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec spec = new GCMParameterSpec(T_LEN, encryptionCipher.getIV());
decryptionCipher.init(Cipher.DECRYPT_MODE, key, spec);
decryptedBytes = decryptionCipher.doFinal(messageInBytes);
} catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException | NoSuchPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException | BadPaddingException | InvalidKeyException e) {
e.printStackTrace();
}
return new String(decryptedBytes);
}
private static String encode(byte[] data) {
return Base64.getEncoder().encodeToString(data);
}
private static byte[] decode(String data) {
return Base64.getDecoder().decode(data);
}
Solution 1:[1]
I had similar situation, still have some open part. Suggested solution solve some, but still there are some open question, hopefully we can have common approach with expert inputs.
Keytool to generate Secret Key
keytool -genseckey -alias aeskey -keyalg AES -keysize 128 -keypass password -keystore project.keystore -storetype pkcs12
refer the Oracle documentation for details.
Java provide standard Java keystore(JKS), Secret key can be stored in jks file before starting application and this file can be read again on restart.
JKS also need password to access, in this approach, challenge is how to keep java keystore password securely
my suggestion is keystore password can be saved securely in new platform like kubernetes ( any other suggestion?)
Reference source code to retrieve Secret Key from Java Keystore:
KeyStore ks = KeyStore.getInstance("pkcs12");
String keyStorePassword = appSecurityConfig.getJksPass(); //get keystore password from external configuration, like kubernetes secret
//appSecurityConfig is configuration class
char [] password = keyStorePassword.toCharArray();
ks.load(new FileInputStream(appSecurityConfig.getKeystoreFile()), password); //keystoreFile -> JKS file name
SecretKey secretKey = (SecretKey) ks.getKey("kskey", password); //kskey -> is secreykey alias
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
