Java AES CBC encryption/decryption I've looked at multiple examples of Java AES CBC mode encryption but I couldn't find a proper solution that's safe to use. I ended up writing my own utility class. My questions is: Is this code safe to use? I've read some stuff about padding oracle attacks but I don't really understand how they work.

I've tested the code and it seems to work properly:

CryptoUtils.removeCryptoRestriction();

String string = "Hello world! This is a test string. Have a nice day!";
byte[] iv = CryptoUtils.generateIv();
byte[] key = CryptoUtils.generateKey();

byte[] encrypted = CryptoUtils.doCrypto(Cipher.ENCRYPT_MODE, key, iv, string.getBytes("UTF-8"));
System.out.println(new String(encrypted));

byte[] decrypted = CryptoUtils.doCrypto(Cipher.DECRYPT_MODE, key, iv, encrypted);
System.out.println(new String(decrypted));


Output:

��zI Fğ��O&gt;��_�@3�ܷ+|ZI�m���M�4�;���ygr8G�ܪ8�6u���M
Hello world! This is a test string. Have a nice day!


Here's the util code:

public static byte[] doCrypto(int mode, byte[] keyBytes, byte[] ivBytes, byte[] bytes) throws GeneralSecurityException {
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
    SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, 0, keyBytes.length, "AES");
    IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes);
    cipher.init(mode, secretKeySpec, ivParameterSpec);
    return cipher.doFinal(bytes);
}

public static void doCrypto(int mode, byte[] keyBytes, byte[] ivBytes, File in, File out) throws GeneralSecurityException, IOException {
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
    SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, 0, keyBytes.length, "AES");
    IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes);
    cipher.init(mode, secretKeySpec, ivParameterSpec);

    try (FileInputStream fileInputStream = new FileInputStream(in); FileOutputStream fileOutputStream = new FileOutputStream(out)) {
        byte[] buffer = new byte[1024];

        for (int i = 0; i != -1; i = fileInputStream.read(buffer)) {
            byte[] updateBytes = cipher.update(buffer, 0, i);
            if (updateBytes != null) fileOutputStream.write(updateBytes);
        }
        byte[] finalBytes = cipher.doFinal();
        if (finalBytes != null) fileOutputStream.write(finalBytes);
    }
}

public static byte[] generateIv() {
    SecureRandom secureRandom = new SecureRandom();
    byte[] iv = new byte[16];
    secureRandom.nextBytes(iv);
    return iv;
}

public static byte[] generateKey() throws NoSuchAlgorithmException {
    KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
    keyGenerator.init(256);
    SecretKey secretKey = keyGenerator.generateKey();
    return secretKey.getEncoded();
}

public static void removeCryptoRestriction() {
    Security.setProperty("crypto.policy", "unlimited");
}


The file encryption works too.

Thanks in advance!
You should move to an authenticated mode of encryption like CCM, EAX, OCB or GCM. The fact that you are generating a random sequence of bytes from the OS's PRNG is sound. It looks like the argument provided to the crypto object is already padding the resulting cipher text of the file stream.

The top bit about removing the restrictions is suspect.

Padding attacks are a side channel attack in crypto that allows an attacker to perform cryptanalysis on a block of cipher text because the plain text input would determine the resulting cipher texts length.  By padding the resulting cipher text it makes that side channel more difficult.