2

I got an infinite loop in this problem. At first, i was receiving a encrypted file from a server and then decrypt it using cipherInputStream, and this was working well. But then i was a bit annoyed, because for that i always need to create the encrypted file i receive from the server.

Then i thought that CipherInputStream just take an InputStream, no matter if it's a fileInputStream or something else. So i've decided to give him directly the DataInputStream i get from the server (with sockets)

Now, it still nearly work. I receive the data, it is decrypted, but the while loop in my decrpyting method never end, because i is never -1 but always 8. Plus, the decrypted file i get is not totally complete (it miss maybe one or two rows of data at the end).

Here's my decrytpion method:

public static void decrypt(DataInputStream dis, SecretKeySpec aesKey, String filename) throws NoSuchAlgorithmException, NoSuchPaddingException{
    Cipher c = Cipher.getInstance("AES");
    try {
        c.init(Cipher.DECRYPT_MODE, aesKey);            

        FileOutputStream fos;
        CipherInputStream cis;

        cis = new CipherInputStream(dis, c);
        fos = new FileOutputStream(filename);

        byte[] b = new byte[8];
        int i = cis.read(b);
        while (i != -1) {
            fos.write(b, 0, i);
            i = cis.read(b);
            System.out.println(i);
        }
        fos.close();
        cis.close();
        new File(filename);

    } catch (InvalidKeyException e) {
        // TODO Auto-generated catch block
        System.out.println("clé incorrecte.");
        e.printStackTrace();
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

my dis is:

DataInputStream dis = new DataInputStream(socket.getInputStream());

And here the code to send out the file from the DB on server:

public void sendFile(String fileID, String owner, Socket clientSocket)  {
    String sql = "SELECT file FROM files WHERE owner LIKE '" + owner + "' AND filename LIKE '"+ fileID + "'";
    try (Connection conn = DriverManager.getConnection(url);
             Statement stmt  = conn.createStatement();
             ResultSet rs    = stmt.executeQuery(sql)){
        DataOutputStream dOut = new DataOutputStream(clientSocket.getOutputStream());
        if(rs.next()) {
            InputStream input = rs.getBinaryStream("file");
            int count;
            byte[] buffer = new byte[4096];
            while ((count = input.read(buffer)) > 0)
            {
              dOut.write(buffer, 0, count);
            }
        }

        else
            System.err.println("File not found in DB!");

    } catch (SQLException | IOException e) {
        System.out.println(e.getMessage());
    }
}

I've tried a buffer of 4096 in the cipher code; then i will be always 512 except for the last one. So the input does have an end, but the -1 doesn't happen as it should (as says in Javadoc: If no byte is available because the end of the stream has been reached, the value -1 is returned )

Anyone have an idea?

Ablia
  • 317
  • 1
  • 3
  • 14
  • A `DataInputStream` uses a very specific protocol, it is not a generic `InputStream`. Don't use it as such. – Mark Rotteveel Aug 03 '18 at 10:35
  • Well, what for an inputStream should i use then? I've tried the simple InputStream in = socket.getInputStream(), but it's not better (just the same in fact). I'm using DataInputStream and DataOutputStream a lot with client/server communication, it was never a problem. What's wrong with it? – Ablia Aug 03 '18 at 11:33
  • Moreover, javadoc says: If no byte is available because the end of the stream has been reached, the value -1 is returned (both for CipherInputStream and DataInputStream). So this -1 should happen, but it doesn't :'( – Ablia Aug 03 '18 at 11:41
  • `DataInputStream` and `DataOutputStream` is for writing primitives and strings in a very specific data exchange format, given that isn't used here, you shouldn't be using a `DataOutputStream` at all. In any case it is entirely unclear to me what your problem is, but in your `sendFile` method you don't seem to be closing or flushing the stream, which could mean that there is still data in the buffer. – Mark Rotteveel Aug 03 '18 at 11:42
  • i've read that closing the streams are most of the time unecessary, except for file streams. However, since i had this problem, i've tried closing th stream on both side. It didn't work better. One server side, the programm continue running after sending the file, so everything is done well. But on client side, i never get this -1 for the end of the stream. Even if i use a simple inputStream and no DataInputStream. – Ablia Aug 03 '18 at 11:45
  • 2
    You should always close streams when you're done, especially with network streams because as long as you haven't closed a network stream, it will never end, so the read on the other side will just block waiting for more data. Not closing streams is never an option, best case they get closed when garbage collected, worst case you get problems with running out of file descriptors or other resource problems (eg running out of memory), and subsequent problems like you seem to have here. – Mark Rotteveel Aug 03 '18 at 11:47
  • 1
    To be specific, you should close `dOut` in your `sendFile` method. – Mark Rotteveel Aug 03 '18 at 11:49
  • I was going to say that i did try before posting and it didn't change anything, but then it suddenly worked, and i realised the fact was: i did try, but i dumbly forgot to launch the server again. So now it works. Thanks :) – Ablia Aug 03 '18 at 12:07

0 Answers0