2014-04-07 3 views
0

암호 및 비용에 관한 학사 학위 논문을 작성하고 있습니다.Java에서 CipherOutputStream을 사용하면 암호화 된 파일이 손상됩니다.

그 중 일부는 런타임 및 리소스 비용면에서 서로 다른 암호화 알고리즘 및 암호 모드를 비교하는 것입니다. 이를 위해 나는 네 단계로 작동합니다 작은 도구 썼다 :

  1. 읽기 입력 파일
  2. 암호화 입력 파일을 새 파일에 기록.
  3. 방금 ​​작성한 암호화 된 파일을 읽고 해독합니다.
  4. 해독 된 파일의 다른 복사본을 파일 시스템에 씁니다.
  5. 초기 입력 파일과 암호 해독 된 파일을 비교하여 파일이 동일한 지 확인하십시오.

작은 .txt 입력 파일로 잘 작동합니다. 하지만 어떤 이유로 다른 파일과는 작동하지 않습니다. 이미지를 입력 파일로 사용하면 처음 몇 픽셀이 좋고 나머지는 손상됩니다. 그래서 내가 암호를 초기화하거나 스트림을 사용할 때 문제가 어떻게 든 이해해야합니다. 필자는 줄의 암호화와 해독에 대해 주석을 달아 봤지만 똑같은 입력 파일의 일반 복사본을 만들 때도 작동합니다.

제안 사항은 언제든지 환영하며, 가능한 빨리 테스트하고 결과가 나타나는지 다시보고하려고합니다. "헝가리 표기법"에 사과드립니다. p는 공용으로 사용하고 l은 로컬로 사용합니다. 그것은 우리 회사에서하는 방식입니다. 실수

import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.security.InvalidAlgorithmParameterException; 
import java.security.InvalidKeyException; 
import java.security.Key; 
import java.security.NoSuchAlgorithmException; 
import java.util.Arrays; 
import java.util.Date; 
import javax.crypto.Cipher; 
import javax.crypto.CipherInputStream; 
import javax.crypto.CipherOutputStream; 
import javax.crypto.KeyGenerator; 
import javax.crypto.NoSuchPaddingException; 
import javax.crypto.spec.IvParameterSpec; 


public class AES_Cipher_Test { 


    public String pLocalRef = "E:\\Test.txt"; 
    public String pLocalRefOutput = "E:\\Test-crypted.txt"; 
    public String pLocalCopyOutput = "E:\\Test-Neu.txt"; 
    public Key pKeyAES = null; 
    public int pBitKey = 128; 
    public Cipher pCipher; 
    public FileOutputStream pFos; 
    public FileInputStream pFis; 
    public CipherOutputStream pCos; 
    public CipherInputStream pCis; 
    public File pInputFile = new File(this.pLocalRef); 
    public File pOutputFile = new File(this.pLocalRefOutput); 
    public File pGeneratedFile = new File(this.pLocalCopyOutput); 

    public AES_Cipher_Test() { 
     crypt_decrypt_write_File(); 
    } 

    public void crypt_decrypt_write_File() { 
     byte[] lLoadedFile = null; 
     byte[] lGeneratedFileByte = null; 
     try { 

      // generate new random AES Key 
      KeyGenerator lKeygen = KeyGenerator.getInstance("AES"); 
      lKeygen.init(this.pBitKey); 
      this.pKeyAES = lKeygen.generateKey(); 


      // read input File 
      this.pFis = new FileInputStream(this.pInputFile); 
      FileInputStream tempStream = new FileInputStream(this.pInputFile); 
      int count = 0; 
      while (tempStream.read() != -1){ 
       count ++; 
      } 
      lLoadedFile = new byte[count]; // new byte[this.pFis.available()] 
      this.pFis.read(lLoadedFile); 
      System.err.println("lLoadedFile.legth " + lLoadedFile.length); 
      this.pFis.close(); 

      //init Cipher with AES Encrypt Mode CFB8 oder CTR 
      this.pCipher = Cipher.getInstance("AES/CTR/PKCS5Padding"); 
      this.pCipher.init(Cipher.ENCRYPT_MODE, this.pKeyAES); 


      // build cipher stream from FileOutputStream 
      this.pFos = new FileOutputStream(this.pOutputFile); 
      this.pCos = new CipherOutputStream(this.pFos, this.pCipher); 

      //write encrypted Data to stream 
      this.pCos.write(lLoadedFile); 
      this.pCos.close(); 
      this.pFos.close(); 

      // init Cipher for decrypt Mode 
      this.pCipher.init(Cipher.DECRYPT_MODE, this.pKeyAES, new IvParameterSpec(this.pCipher.getIV())); 


      // read just written localFile and decrypt 
      this.pFis = new FileInputStream(this.pOutputFile); 
      tempStream = new FileInputStream(this.pOutputFile); 
      count = 0; 
      while (tempStream.read() != -1){ 
       count ++; 
      } 
      byte[] lBytes = new byte[count];// new byte[this.pFis.available()] 
      this.pCis = new CipherInputStream(this.pFis, this.pCipher); 
      int lBytesRead = this.pCis.read(lBytes); 
      while (lBytesRead > -1) { 
       lBytesRead = this.pCis.read(lBytes); 
      } 
      this.pCis.close(); 
      this.pFis.close(); 
      System.err.println("lBytes.length " + lBytes.length); 

      // write new not crypted File to see if procedure works 
      this.pFos = new FileOutputStream(this.pLocalCopyOutput); 
      this.pFos.write(lBytes); 
      this.pFos.close(); 


      //compare Input File and Output File 
      this.pFis = new FileInputStream(this.pGeneratedFile); 
      tempStream = new FileInputStream(this.pGeneratedFile); 
      count = 0; 
      while (tempStream.read() != -1){ 
       count ++; 
      } 
      lGeneratedFileByte = new byte[count]; // new byte[this.pFis.available()] 
      int i = this.pFis.read(lGeneratedFileByte); 
      this.pFis.close(); 

      System.err.println("lGeneratedFileByte.length " + i); 
      System.err.println("Test if initial File and new File are identical = " + Arrays.equals(lGeneratedFileByte, lLoadedFile)); 


     } catch (FileNotFoundException e) { 
      throw new RuntimeException("FILE_DOES_NOT_EXIST", e); 
     } catch (NoSuchAlgorithmException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (NoSuchPaddingException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (InvalidKeyException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (InvalidAlgorithmParameterException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 


    public static void main(String args[]) { 
     System.err.println("Start AES_Cipher_Test"); 
     long start = new Date().getTime(); 
     new AES_Cipher_Test(); 
     long runningTime = new Date().getTime() - start; 
     System.err.println("End AES_Cipher_Test"); 
     System.err.println("Runtime: " + runningTime); 

    } 
} 
+1

Java에서는 헝가리 표기법을 사용하지 않아야합니다. 그것은 완전히 불필요합니다. Java 식별자의 유형은 선언을 읽음으로써 판별 할 수 있습니다. 자바는 스타일 가이드를 가지고 있습니다. 다른 사람들이 코드를 읽으려면 스타일 가이드를 따라야합니다. –

+0

'while (lBytesRead <= 0)'루프에 대한 편집이 원본보다 훨씬 더 적합합니다. 'read()'는 길이가 0 인 버퍼를 제공하면 0을 리턴 할 수 있고, 스트림의 끝에서는 -1을 리턴 할 수 있습니다. 어떤 경우에도 루프를 만드는 것이 의미가 없으며 어떤 경우도'read()'가 버퍼를 채우지 못하는 경우를 보완하지 못합니다. 귀하의 성명서 "버퍼 크기와 읽기/쓰기가 문제가되지 않는 것만 큼 잘 작동하는 파일을 복사하지 않는 것"이 ​​* 비 연속입니다.* 당신이 여기에 오는 대답에 대해 조금이라도주의를 기울이지 않으면, 나는 게시 지점을 전혀 보지 못합니다. – EJP

+0

@StephenC 표기법에 대해 유감스럽게 생각하지만, 회사 표준을 사용하도록 요구되었습니다 ... – jonny

답변

1

평소 시리즈 :

그래서 여기 내 클래스입니다.

  • read()은 버퍼를 채우는 데 지정되지 않습니다. 적어도 1 바이트를 전송하는 경우에만 지정되며, 그렇지 않으면 스트림의 끝을 나타내는 -1이 반환됩니다. 당신은 루프가 :

    while ((count = in.read(buffer)) > 0) 
    { 
        out.write(buffer, 0, count); 
    } 
    

기존 루프 while (!(lBytesRead < lBytes.length))는 기본적으로 넌센스입니다.

  • available() 명시 적으로 스트림의 총 바이트 수, 명시 적으로 올바르지하기 위해 자바 독에 명시되어있는 크기의 버퍼를 할당하는 그것의 어떤 사용되지 않습니다. 다시 말하지만 위의 루프를 반복해야합니다. available(),을 사용하는 경우는 거의 없으며이 중 하나가 아닙니다.
+0

파일을 암호화하고 암호 해독하는 두 줄을 주석으로 처리 할 때 손상되지 않은 일반 복사본을 얻었습니다. 그 부분을 언급하는 것을 잊었습니다 ... – jonny

+0

정확히 '두 줄'은 무엇입니까? 그것은 저보다 더 중요합니다. 어쨌든 위의 수정을하면 어떻게 될지보고하는 것이 더 재미있을 것입니다. 선택 사항이 아니며 의무 사항입니다. – EJP

+0

"this.pCos = new CipherOutputStream (this.pFos, this.pCipher);"줄을 제거합니다. 및 "this.pCis = 새로운 CipherInputStream (this.pFis, this.pCipher);" 그리고 그것을 FileInputStream/FileOutputStream 읽기 및 쓰기로 편집하면 파일의 복사본을 만들뿐입니다. read() 및 available()에 문제가 없습니다. – jonny

관련 문제