2017-02-22 41 views
0

這是我的加密類:試圖刪除我所附到字節[](這是IV)的最後16個字節然後解密

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(); 
} 

這是我的解密方法:

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(); 
} 

}

正如你所看到的,我生成了一個16字節長的IV,我已經附加到加密文件的末尾。這樣我就可以將IV解密,並且每個文件都有獨特的IV。我目前得到的錯誤:

java.lang.IllegalArgumentException異常:IV緩衝區太短定偏移量/長度組合

除了問題產生的錯誤,是我的邏輯是否正確?這會工作嗎?

回答

4

I generated a 16 byte long IV that I have appended to the end of the encrypted file.

不,你沒有。你之前 - 已將其掛起。無論如何,這是一個更好的主意。所以你必須先閱讀它,然後構造你的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(); 
} 
+0

如果IV在開始時如何分開兩個? – champskee

+0

我說的方式。通過'FileInputStream'讀取前16個字節,然後將相同的'FileInputStream'傳遞給'CipherInputStream'。 – EJP

+0

你能舉個例子嗎?我不斷收到錯誤。它是一個漫長的一天盯着相同的代碼。 – champskee

相關問題