2017-08-17 18 views
1

クライアントからサーバー に暗号化されたファイルを送信するコードを書いていますが、クライアントはまずファイルの暗号化されたメッセージダイジェストをサーバーに送信してから、それは、暗号化されたファイルの をバイトを送信します終了しますが、サーバー側でそれがダイジェストで一つの変数、InputStreamから別の入力を読み込むJAVA

として、これらすべての変数を読み込むと、サーバが解読しようとしたとき、それはここIllegal Block Size Exception 私の質問を投げているダイジェストどのようにサーバーがさまざまな変数でそれらを読み込んで保存できますか?

クライアント

  // set mode to encrypt 
      AesCipher.init(Cipher.ENCRYPT_MODE, key); 

      DataOutputStream toServer = new DataOutputStream(socket.getOutputStream()); 

      // get the digest of the file 
      MessageDigest md = MessageDigest.getInstance("MD5"); 
      byte[] hash = md.digest(bytes); 

      // encrypt digest and write it to file 
      byte [] encryptedHash = AesCipher.doFinal(hash); 
      toServer.write(encryptedHash); 


      // write file name to server 
      toServer.writeUTF(fileName); 

      //encrypt file 
      byte[] encryptedByte = AesCipher.doFinal(bytes); 


      // write file to server 
      toServer.write(encryptedByte); 
      toServer.flush(); 
      socket.close(); 

サーバー

// read digest of the file 
     byte [] digest =IOUtils.toByteArray(fromClient); 

     // decrypt it 
     AesCipher.init(Cipher.DECRYPT_MODE, key); 
     byte[] decryptedDigest = AesCipher.doFinal(digest); 

     // read file name to be received 
     String fileName = fromClient.readUTF(); 

     File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), fileName); 
     file.createNewFile(); 
     FileOutputStream fos = new FileOutputStream(file); 
     BufferedOutputStream bos = new BufferedOutputStream(fos); 

     // read file bytes from client 
     byte[] fileBytes = IOUtils.toByteArray(fromClient); 

     AesCipher.init(Cipher.DECRYPT_MODE, key); 
     byte[] decryptedByte = AesCipher.doFinal(fileBytes); 
     bos.write(decryptedByte, 0, decryptedByte.length); 
     bos.close(); 

も私はこのコードを試してみましたが、それはありませんが、あまりにも

// read digest of the file 
     ByteArrayOutputStream buffer = new ByteArrayOutputStream(); 

     int nRead; 
     byte[] data = new byte[1024]; 

     while ((nRead = fromClient.read(data, 0, data.length)) != -1) { 
      buffer.write(data, 0, nRead); 
     } 

     buffer.flush(); 
     byte[] digest = buffer.toByteArray(); 

     // decrypt it 
     AesCipher.init(Cipher.DECRYPT_MODE, key); 
     byte[] decryptedDigest = AesCipher.doFinal(digest); 

     // read file name to be received 
     String fileName = fromClient.readUTF(); 

     File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), fileName); 
     file.createNewFile(); 
     FileOutputStream fos = new FileOutputStream(file); 
     BufferedOutputStream bos = new BufferedOutputStream(fos); 

     // read file bytes from client 
     byte[] fileBytes = IOUtils.toByteArray(fromClient); 

     AesCipher.init(Cipher.DECRYPT_MODE, key); 
     byte[] decryptedByte = AesCipher.doFinal(fileBytes); 
     bos.write(decryptedByte, 0, decryptedByte.length); 
     bos.close(); 
+1

サーバー側では、各ピースごとに書き出されたバイト数と同じバイト数で読み込むのではなく、 'digest'に書き込まれた量全体を読み込みます。片方が16バイトの場合は、16バイトで読み込む必要があります。それ以前に何バイトかが分からなければ、ピースの長さにピース自体の前に接頭辞を付ける必要があります。 –

+0

@JamesKPolkどのようにすることができます=私はダイジェストを暗号化した後に何バイトを知っていますか? – Inspiration

+0

あなたはそれよりも先にその長さを送る必要があります。 – EJP

答えて

2

IOUtils.toByteArray(InputStream)作品全体の流れを読みました。だから、ハッシュバイトを取得するのではなく、ストリーム全体を取得し、ファイル名や暗号文に何も残らず、ハッシュはチェックしませんでした。

このために外部ライブラリは必要ありません。あなたはすべてDataInputStreamDataOutputStreamでそれを行うことができます。しかし、ハッシュの前にハッシュの長さを送る必要があります。

クライアント:

 // set mode to encrypt 
     AesCipher.init(Cipher.ENCRYPT_MODE, key); 

     DataOutputStream toServer = new DataOutputStream(socket.getOutputStream()); 

     // get the digest of the file 
     MessageDigest md = MessageDigest.getInstance("MD5"); 
     byte[] hash = md.digest(bytes); 

     // encrypt digest and write it to file 
     byte [] encryptedHash = AesCipher.doFinal(hash); 
     toServer.writeInt(encryptedHash.length); 
     toServer.write(encryptedHash); 

     // write file name to server 
     toServer.writeUTF(fileName); 

     //encrypt file 
     byte[] encryptedByte = AesCipher.doFinal(bytes); 

     // write file to server 
     toServer.writeInt(encryptedByte.length); 
     toServer.write(encryptedByte); 
     socket.close(); 

サーバー:これの暗号化と復号化の部分がはるかに優れてCipherInputStreamCipherOutputStreamで行わだろうしかし

// read digest of the file 
    int digestLength = fromClient.readInt(); 
    byte[] digest = new byte[digestLength]; 
    fromClient.readFully(digest); 

    // decrypt it 
    AesCipher.init(Cipher.DECRYPT_MODE, key); 
    byte[] decryptedDigest = AesCipher.doFinal(digest); 

    // read file name to be received 
    String fileName = fromClient.readUTF(); 

    File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), fileName); 
    FileOutputStream fos = new FileOutputStream(file); 
    BufferedOutputStream bos = new BufferedOutputStream(fos); 

    // read file bytes from client 
    int fileLength = fromClient.readInt(); 
    byte[] fileBytes = new byte[fileLength]; 
    fromClient.readFully(fileBytes); 

    AesCipher.init(Cipher.DECRYPT_MODE, key); 
    byte[] decryptedByte = AesCipher.doFinal(fileBytes); 
    bos.write(decryptedByte, 0, decryptedByte.length); 
    bos.close(); 

。ファイル全体をメモリにロードしないでください。

file.createNewFile()コールがnew FileOutputStream(...)より前に冗長であったことに注意してください。

メッセージダイジェストを暗号化する理由はもう一つ謎です。復号後にローカルで生成されたダイジェストと比較するための最後のステップとして使用する必要があります。

+0

ありがとう、私はちょうどサーバーが復号化の後にローカルで生成されたダイジェストとそれを比較するようにサーバーに暗号化MDを送った、エラーを生成するコードを掲示しました。 – Inspiration

+0

しかし、MDを暗号化する必要はありません。それは秘密ではない。 – EJP

関連する問題