尝试删除我附加到 byte[](即 IV)上的最后 16 个字节,然后解密

cha*_*kee 1 java arrays encryption aes

这是我的加密类:

public static void encrypt(byte[] file, String password, String fileName, String dir) throws Exception {

    SecureRandom r = new SecureRandom();
    //128 bit IV generated for each file
    byte[] iv = new byte[IV_LENGTH];
    r.nextBytes(iv);
    IvParameterSpec ivspec = new IvParameterSpec(iv);
    SecretKeySpec keySpec = new SecretKeySpec(password.getBytes(), "AES");

    Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
    cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivspec);

    FileOutputStream fos = new FileOutputStream(dir + fileName);
    fos.write(iv);

    CipherOutputStream cos = new CipherOutputStream(fos, cipher);

    // Have to append IV --------

    cos.write(file);

    fos.flush();
    cos.flush();
    cos.close();
    fos.close();
}
Run Code Online (Sandbox Code Playgroud)

这是我的解密方法:

public static void decrypt(byte[] file, String password, String fileName, String dir) throws Exception
{   
    // gets the IV
    int ivIndex = file.length - 16;

    byte[] truncatedFile = Arrays.copyOfRange(file, 0, file.length - 16);

    SecretKeySpec keySpec = new SecretKeySpec(password.getBytes(), "AES");

    Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
    cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(truncatedFile, ivIndex, 16));

    //IvParameterSpec ivspec = new IvParameterSpec(iv);
    //
    //cipher.init(Cipher.DECRYPT_MODE, keySpec, ivspec);

    FileOutputStream fos = new FileOutputStream(dir + fileName);
    CipherOutputStream cos = new CipherOutputStream(fos, cipher);

    cos.write(file);
    fos.flush();
    cos.flush();
    cos.close();
    fos.close();
}
Run Code Online (Sandbox Code Playgroud)

}

正如您所看到的,我生成了一个 16 字节长的 IV,并将其附加到加密文件的末尾。这样我就可以获得用于解密的 IV,并且每个文件都有一个唯一的 IV。我目前收到错误:

java.lang.IllegalArgumentException:IV 缓冲区对于给定的偏移/长度组合太短

除了产生错误的问题之外,我的逻辑是否正确?这行得通吗?

use*_*421 5

我生成了一个 16 字节长的 IV,并将其附加到加密文件的末尾。

不,你没有。你预先决定了。无论如何,这是一个更好的主意。因此,您必须先读取它,然后构造您的CipherCipherInputStream并解密文件输入流的其余部分。您不需要将整个文件读入内存来完成此操作:

public static void decrypt(File file, String password) throws Exception
{
    byte[] iv = new byte[16];
    DataInputStream dis = new DataInputStream(new FileInputStream(file));
    dis.readFully(iv);

    SecretKeySpec keySpec = new SecretKeySpec(password.getBytes(), "AES");

    Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
    cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(iv));
    CipherInputStream cis = new CipherInputStream(dis, cipher);

    // Now just read plaintext from `cis` and do whatever you want with it.

    cis.close();
}
Run Code Online (Sandbox Code Playgroud)