Reputation: 848
I have next code that was copied from the right answer here:
public static String decrypt(String cipherText) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
byte[] cipherData = Base64.getDecoder().decode(cipherText);
byte[] saltData = Arrays.copyOfRange(cipherData, 8, 16);
MessageDigest md5 = MessageDigest.getInstance("MD5");
final byte[][] keyAndIV = generateKeyAndIV(32, 16, 1, saltData, secret.getBytes(StandardCharsets.UTF_8), md5);
SecretKeySpec key = new SecretKeySpec(keyAndIV[0], "AES");
IvParameterSpec iv = new IvParameterSpec(keyAndIV[1]);
byte[] encrypted = Arrays.copyOfRange(cipherData, 16, cipherData.length);
Cipher aesCBC = Cipher.getInstance("AES/CBC/PKCS5Padding");
aesCBC.init(Cipher.DECRYPT_MODE, key, iv);
byte[] decryptedData = aesCBC.doFinal(encrypted);
String decryptedText = new String(decryptedData, StandardCharsets.UTF_8);
return decryptedText;
}
How can I write encrypt function for this in Java? I tried something like this, but it doesn't work:
public static String encrypt(String plainText) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException {
MessageDigest md5 = MessageDigest.getInstance("MD5");
final byte[][] keyAndIV = generateKeyAndIV(32, 16, 1, getNextSalt(), secret.getBytes(StandardCharsets.UTF_8), md5);
SecretKeySpec skeySpec = new SecretKeySpec(keyAndIV[0], "AES");
IvParameterSpec iv = new IvParameterSpec(keyAndIV[1]);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] encrypted = cipher.doFinal(plainText.getBytes());
return Base64.getEncoder().encodeToString(encrypted);
}
public static byte[] getNextSalt() {
byte[] salt = new byte[8];
RANDOM.nextBytes(salt);
return salt;
}
Upvotes: 1
Views: 334
Reputation: 49390
The encrypt
-method must return the data in OpenSSL format, which consists of the ASCII encoding of Salted__, followed by the 8 bytes randomly generated salt and the actual ciphertext, whereby the data are Base64 encoded after their concatenation.
Note, however, that the key derivation function used for the OpenSSL format is insecure and is not a standard, here. A possible extension of the encrypt
method could be:
public static String encrypt(String plainText) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException {
byte[] salt = getNextSalt();
MessageDigest md5 = MessageDigest.getInstance("MD5");
final byte[][] keyAndIV = generateKeyAndIV(32, 16, 1, salt, secret.getBytes(StandardCharsets.UTF_8), md5);
SecretKeySpec skeySpec = new SecretKeySpec(keyAndIV[0], "AES");
IvParameterSpec iv = new IvParameterSpec(keyAndIV[1]);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] encrypted = cipher.doFinal(plainText.getBytes());
byte[] prefix = "Salted__".getBytes(StandardCharsets.US_ASCII);
byte[] prefixSaltEncrypted = new byte[prefix.length + salt.length + encrypted.length];
System.arraycopy(prefix, 0, prefixSaltEncrypted, 0, prefix.length);
System.arraycopy(salt, 0, prefixSaltEncrypted, prefix.length, salt.length);
System.arraycopy(encrypted, 0, prefixSaltEncrypted, prefix.length + salt.length, encrypted.length);
return Base64.getEncoder().encodeToString(prefixSaltEncrypted);
}
Upvotes: 2