2015-10-13 60 views
0

我使用下面的代码加密/解密:解密加密文件会破坏文件? Android的 - Java的

import javax.crypto.BadPaddingException; 
import javax.crypto.Cipher; 
import javax.crypto.IllegalBlockSizeException; 
import javax.crypto.NoSuchPaddingException; 
import javax.crypto.spec.SecretKeySpec; 


public class CryptoUtils { 
    private static final String ALGORITHM = "AES"; 
    private static final String TRANSFORMATION = "AES"; 

    public static void encrypt(String key, File inputFile, File outputFile) 
      throws CryptoException { 
     doCrypto(Cipher.ENCRYPT_MODE, key, inputFile, outputFile); 
    } 

    public static void decrypt(String key, File inputFile, File outputFile) 
      throws CryptoException { 
     doCrypto(Cipher.DECRYPT_MODE, key, inputFile, outputFile); 
    } 

    private static void doCrypto(int cipherMode, String key, File inputFile, 
           File outputFile) throws CryptoException { 
     try { 
      Key secretKey = new SecretKeySpec(key.getBytes(), ALGORITHM); 
      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PAdding"); 
      cipher.init(cipherMode, secretKey); 

      FileInputStream inputStream = new FileInputStream(inputFile); 
      byte[] inputBytes = new byte[(int) inputFile.length()]; 
      inputStream.read(inputBytes); 

      byte[] outputBytes = cipher.doFinal(inputBytes); 

      FileOutputStream outputStream = new FileOutputStream(outputFile); 
      outputStream.write(outputBytes); 

      inputStream.close(); 
      outputStream.close(); 

     } catch (NoSuchPaddingException e) { 
      e.printStackTrace(); 
     } catch (NoSuchAlgorithmException 
       | InvalidKeyException | BadPaddingException 
       | IllegalBlockSizeException | IOException ex) { 
      throw new CryptoException("Error encrypting/decrypting file", ex); 
     } 
    } 

    public static class CryptoException extends Exception { 

     public CryptoException() { 
     } 

     public CryptoException(String message, Throwable throwable) { 
      super(message, throwable); 
     } 
    } 
} 

我可以加密和解密的视频文件。 但是,我无法播放由相同代码加密的解密文件。

原始文件:http://www.megafileupload.com/hSTZ/a.mp4

加密文件:http://www.megafileupload.com/hSU2/encrypted-a.mp4

解密文件:http://www.megafileupload.com/hSU1/decrypted-final-a.mp4

的前16个字节解密文件的是从原始文件不同。长度是一样的。

+1

我对Java中的加密技术不太感兴趣,特别是在Android下,但我担心我没有看到如何将您的IV从加密函数传递给解密函数。 CBC模式使用该初始化向量来混淆第一个加密输出块,因此即使使用相同的密钥,相同的纯文本也会产生完全不同的加密文本。如果您使用与您在加密时使用的不同的IV进行解密,则解密将成功,但第一个块(16个字节)将被加密。尝试明确提供您的IV(硬编码测试,如果你喜欢),看看是否有效。 – WDS

+1

我没有提到我的怀疑,但在C#中.NET,如果你有CBC模式,并没有指定你的IV,算法会随机产生一个。通常,您会将其作为加密输出的第一个块编写,然后将其作为第一个加密输入块进行读取,以便使用该算法来准备解密算法。因此,将随机IV写入输出文件的开头,或者(仅用于测试)将其硬编码到程序中。请注意,硬编码的IV失去了IV提供的所有有益特性。但出于测试目的,我会尝试。 – WDS

+0

不知道你如何加密它,这是不可能知道解密代码有什么问题。我不想玩[猜谜游戏](https://blog.stackoverflow.com/2012/02/lets-play-the-guessing-game/)。 –

回答

0

你假设:

  1. 文件装入内存。
  2. 文件大小适合int。
  3. read()填充缓冲区。
  4. 加密或解密的结果与源内容一起放入内存中。

不需要这些假设。

FileInputStream inputStream = new FileInputStream(inputFile); 
FileOutputStream outputStream = new FileOutputStream(outputFile); 
byte[] buffer = new byte[8192]; 
int count; 
while ((count = in.read(buffer)) > 0) 
{ 
    byte[] output = cipher.update(buffer, 0, count); 
    outputStream.write(output); 
} 
outputStream.write(cipher.doFinal()); 
outputStream.close(); 
inputStream.close(); 

E & OE但你明白了。你可以通过使用CipherInput/OutputStreams,来让你的生活变得更简单,但是你会失去与加密例外的联系。

+0

谢谢你的帮助@EJP,但改变没有奏效..解密的加密文件不播放.. – manishKungwani