2014-12-08 191 views
1

我有一个读取文件(例如* .zip)的问题,并使用3DES对其进行加密,使用加密文件的名称生成的secretKey。 然后我需要解密这个文件,然后把它写在硬盘上。 我试图解决这个问题,但解密文件时卡住了。3des加密/解密文件java

这里是加密

public class Encryptor { 
    private static String inputFilePath = "D:/1.txt"; 
    public static void main(String[] args) { 
     FileOutputStream fos = null; 
     File file = new File(inputFilePath); 
     String keyString = "140405PX_0.$88"; 
     String algorithm = "DESede"; 
     try { 
      FileInputStream fileInputStream = new FileInputStream(file); 
      byte[] fileByteArray = new byte[fileInputStream.available()]; 
      fileInputStream.read(fileByteArray); 
      for (byte b : fileByteArray) { 
      System.out.println(b); 
      } 
      SecretKey secretKey = getKey(keyString); 
      Cipher cipher = Cipher.getInstance(algorithm); 
      cipher.init(Cipher.ENCRYPT_MODE, secretKey); 
      ObjectOutputStream objectOutputStream = new ObjectOutputStream 
        (new CipherOutputStream 
          (new FileOutputStream 
            ("D:/Secret.file"), cipher)); 
      objectOutputStream.writeObject(fileByteArray); 
      objectOutputStream.close(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
    public static SecretKey getKey(String message) throws Exception { 
     String messageToUpperCase = message.toUpperCase(); 
     byte[] digestOfPassword = messageToUpperCase.getBytes(); 
     byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24); 
     SecretKey key = new SecretKeySpec(keyBytes, "DESede"); 
     return key; 
    } 
} 

的代码这里是解密

public class Decryptor { 
    public static void main(String[] args) { 
     try { 
      File inputFileNAme = new File("d:/Secret.file"); 
      FileInputStream fileInputStream = new FileInputStream(inputFileNAme); 
      FileOutputStream fileOutputStream = new FileOutputStream(outputFilePath); 
      SecretKey secretKey = getKey(keyString); 
      Cipher cipher = Cipher.getInstance(algorithm); 
      cipher.init(Cipher.DECRYPT_MODE, secretKey); 
      ObjectInputStream objectInputStream = new ObjectInputStream 
        (new CipherInputStream(fileInputStream, cipher)); 
      System.out.println(objectInputStream.available()); 
      while (objectInputStream.available() != 0) { 
       fileOutputStream.write((Integer) objectInputStream.readObject()); 
       System.out.println(objectInputStream.readObject()); 
      } 
      fileOutputStream.flush(); 
      fileOutputStream.close(); 
      fileInputStream.close(); 
      objectInputStream.close(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
    public static SecretKey getKey(String message) throws Exception { 
     String messageToUpperCase = message.toUpperCase(); 
     byte[] digestOfPassword = messageToUpperCase.getBytes(); 
     byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24); 
     SecretKey key = new SecretKeySpec(keyBytes, "DESede"); 
     return key; 
    } 
} 

当我尝试解密我的文件,我没有得到在输出文件中的任何代码。
我试过做调试,并看到,objectInputStream.available()总是包含0.
请告诉我,我该如何解决这个问题,以及为什么会发生。

回答

2
  1. 的使用

    byte[] fileByteArray = new byte[fileInputStream.available()]; 
    

    specifically warned against in the Javadoc:“这是从来没有正确的使用这个方法的返回值来分配打算持有该流中的所有数据的缓冲器。”

    文件应该一次处理记录或缓冲区。

  2. 线:

    fileInputStream.read(fileByteArray); 
    

    不能保证填充缓冲区。你必须检查返回值:for -1,意思是文件结尾,或> 0,表示实际传输的字节数。看到Javadoc。

  3. 同样

    while (objectInputStream.available() != 0) { 
    

    不是流的末尾有效的测试。你应该叫readObject()直到它抛出EOFException.

1

这样的quickfix,这个工程:

try { 
     File inputFileNAme = new File("d:/Secret.file"); 
     FileInputStream fileInputStream = new FileInputStream(inputFileNAme); 
     FileOutputStream fileOutputStream = new FileOutputStream(outputFilePath); 
     SecretKey secretKey = getKey(keyString); 
     Cipher cipher = Cipher.getInstance(algorithm); 
     cipher.init(Cipher.DECRYPT_MODE, secretKey); 
     ObjectInputStream objectInputStream = new ObjectInputStream 
       (new CipherInputStream(fileInputStream, cipher)); 
     System.out.println(objectInputStream.available()); 
     fileOutputStream.write((byte[]) objectInputStream.readObject()); 
     fileOutputStream.flush(); 
     fileOutputStream.close(); 
     fileInputStream.close(); 
     objectInputStream.close(); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 

我所做的是去掉“.available() while循环”,并删除该投给Integer,这是错误的。

我同意EJP的回答,特别是关于使用.available()

您也可以使用http://www.jasypt.org/,它提供了一个更简单的API来加密文件。

+0

'close()'之前的'flush()'是多余的,就像关闭包装在其他流中的流一样。这些都没有解决发送方面的问题。 – EJP 2014-12-08 08:59:56

+0

这个解决方案不是一个不错的和干净的解决方案,它是一个解决OP问题的_quickfix_。如果需要的话,它可以被很好地和干净地重写。 (事实上​​,我为你的答案+1了@EJP) – superbob 2014-12-08 10:00:08