I am trying to implement message encryption/decryption with password in java. Here is the code I'm using:
import java.security.MessageDigest;
import java.security.spec.InvalidKeySpecException;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
public class Cryptography {
public static final int SECRET_KEY_ITERATIONS = 45928;
public static final int SALT_ITERATIONS = 11879;
public static final int IV_ITERATIONS = 13275;
public static final int KEY_LENGTH = 256;
private static Cipher cipher;
private static MessageDigest sha256;
private static SecretKeyFactory secretKeyFactory;
static {
try {
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
sha256 = MessageDigest.getInstance("SHA-256");
secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
} catch (Exception e) {
e.printStackTrace();
}
}
public static String encryptText(String password, String plaintext) throws Exception {
byte[] passwordBytes = password.getBytes();
SecretKey secretKey = getKeyFromPassword(password, getSaltFromPassword(passwordBytes));
IvParameterSpec ivParameterSpec = getIvFromPassword(passwordBytes);
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec);
return Base64.getEncoder().encodeToString(cipher.doFinal(plaintext.getBytes()));
}
public static String decryptText(String password, String ciphertext) throws Exception {
byte[] passwordBytes = password.getBytes();
SecretKey secretKey = getKeyFromPassword(password, getSaltFromPassword(passwordBytes));
IvParameterSpec ivParameterSpec = getIvFromPassword(passwordBytes);
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
return new String(cipher.doFinal(Base64.getDecoder().decode(ciphertext)));
}
private static SecretKey getKeyFromPassword(String password, byte[] salt)
throws InvalidKeySpecException {
PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, SECRET_KEY_ITERATIONS, KEY_LENGTH);
byte[] bytes = secretKeyFactory.generateSecret(spec).getEncoded();
return new SecretKeySpec(bytes, "AES");
}
private static byte[] getSaltFromPassword(byte[] passwordByteArray) {
byte[] bytes = sha256.digest(passwordByteArray);
for (int i = 0; i < SALT_ITERATIONS; i++) {
bytes = sha256.digest(bytes);
}
return bytes;
}
private static IvParameterSpec getIvFromPassword(byte[] passwordByteArray) {
byte[] bytes = sha256.digest(passwordByteArray);
for (int i = 0; i < IV_ITERATIONS; i++) {
bytes = sha256.digest(bytes);
}
byte[] ivBuffer = new byte[16];
System.arraycopy(bytes, 0, ivBuffer, 0, 16);
return new IvParameterSpec(ivBuffer);
}
}
Is this a secure way to do encryption/decryption, or does it have serious issues?