Передача файлов клиент/сервер с использованием CipherOutputStream

Попытка написать программу клиент/сервер, в которой клиент читает текстовый файл и отправляет его на сокет сервера с помощью CipherOutputStream. Ожидаемый текстовый файл создан, но пуст, и я получаю следующую ошибку

Длина чтения-1

EOF: ноль

У меня есть этот метод encrypt(), который выполняет шифрование, а затем отправляет данные

private static void encrypt(InputStream is, OutputStream os) {

    try {

        byte[] buf = new byte[1024];

// байты в этом потоке сначала кодируются

        os = new CipherOutputStream(os, ecipher);

// читаем в открытом тексте и записываем на выходе для шифрования

        int numRead = 0;

        while ((numRead = is.read(buf)) >= 0) {

            os.write(buf, 0, numRead);

        }

// закрываем все потоки

        os.close();

    } catch (IOException e) {

        System.out.println("I/O Error:" + e.getMessage());

    }

}

Ниже приведена большая часть кода на стороне клиента.

public void actionPerformed(ActionEvent e) {

    //Handle open button action.
    if (e.getSource() == openButton) {
        int returnVal = fc.showOpenDialog(FileChooserDemo.this);

        if (returnVal == JFileChooser.APPROVE_OPTION) {
            try {
                SecretKey key = KeyGenerator.getInstance("DES").generateKey();

                AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);

                ecipher = Cipher.getInstance("DES/CBC/PKCS5Padding");

                dcipher = Cipher.getInstance("DES/CBC/PKCS5Padding");

                ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);

                dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);

                File file = fc.getSelectedFile();

                Socket s = null;
                s = new Socket("localhost", 6880);
                DataOutputStream output = new DataOutputStream(s.getOutputStream());


                encrypt(new FileInputStream(file), output);

                log.append("encrypted " + newline);

                log.append("Sent" + file.getName() + "." + newline);
            } catch (Exception ex) {
                Logger.getLogger(FileChooserDemo.class.getName()).log(Level.SEVERE, null, ex);
            }
        } else {
            log.append("Open command cancelled by user." + newline);
        }
        log.setCaretPosition(log.getDocument().getLength());

        //Handle save button action.
    } else if (e.getSource() == saveButton) {
        int returnVal = fc.showSaveDialog(FileChooserDemo.this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = fc.getSelectedFile();
            //This is where a real application would save the file.
            log.append("Saving: " + file.getName() + "." + newline);
        } else {
            log.append("Save command cancelled by user." + newline);
        }
        log.setCaretPosition(log.getDocument().getLength());
    }
}

Затем прослушивающий сервер считывает данные с помощью CipherInputStream, а затем записывает их в текстовый файл. Сервер содержит следующее

private static void decrypt(InputStream is, OutputStream os) {

    try {

        byte[] buf = new byte[1024];

// байты, прочитанные из потока, будут расшифрованы

        CipherInputStream cis = new CipherInputStream(is, dcipher);

// читаем расшифрованные байты и записываем открытый текст в out

        int numRead = 0;

        while ((numRead = cis.read(buf)) >= 0) {

            os.write(buf, 0, numRead);

        }

// закрываем все потоки

        cis.close();

        is.close();

        os.close();

    } catch (IOException e) {

        System.out.println("I/O Error:" + e.getMessage());

    }

}

public void run() {
    try {

        SecretKey key = KeyGenerator.getInstance("DES").generateKey();

        AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);


        dcipher = Cipher.getInstance("DES/CBC/PKCS5Padding");

        dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);

        decrypt(input, new FileOutputStream("cleartext-reversed.txt"));

        FileWriter out = new FileWriter("test.txt");
        BufferedWriter bufWriter = new BufferedWriter(out);


        System.out.println("receive from : "
                + clientSocket.getInetAddress() + ":"
                + clientSocket.getPort());
        //Step 1 read length
        int nb = input.read();
        System.out.println("Read Length" + nb);

        String enctext = Character.toString(input.readChar());
        Integer.toString(nb);
        //Step 2 read byte

        String st = new String("see if it can write");
        bufWriter.append(enctext);
        bufWriter.close();


        //Step 1 send length
        output.writeInt(st.length());
        //Step 2 send length
        output.writeBytes(st); // UTF is a string encoding
        //  output.writeUTF(data);
    } catch (NoSuchPaddingException ex) {
        Logger.getLogger(Connection.class.getName()).log(Level.SEVERE, null, ex);
    } catch (InvalidKeyException ex) {
        Logger.getLogger(Connection.class.getName()).log(Level.SEVERE, null, ex);
    } catch (InvalidAlgorithmParameterException ex) {
        Logger.getLogger(Connection.class.getName()).log(Level.SEVERE, null, ex);
    } catch (NoSuchAlgorithmException ex) {
        Logger.getLogger(Connection.class.getName()).log(Level.SEVERE, null, ex);
    } catch (EOFException e) {
        System.out.println("EOF:" + e.getMessage());
    } catch (IOException e) {
        System.out.println("IO:" + e.getMessage());
    } finally {
        try {
            clientSocket.close();
        } catch (IOException e) {/*close failed*/

        }
    }
}

person Kenoye Rukari    schedule 24.08.2013    source источник


Ответы (1)


Сервер делает следующее:

decrypt(input, new FileOutputStream("cleartext-reversed.txt"));

который читает все из входного потока, расшифровывает его, записывает результат в текстовый файл и закрывает входной поток.

Затем сразу после этого вы пытаетесь сделать

int nb = input.read();
...
input.readChar()

который, таким образом, пытается снова прочитать входной поток, который только что был полностью прочитан и закрыт.

Примечание: диагностика была бы намного проще, если бы вместо того, чтобы прятать исключение за

System.out.println("EOF:" + e.getMessage());

ты сделал

e.printStackTrace();

который скажет вам, что это за исключение и где оно происходит.

person JB Nizet    schedule 24.08.2013
comment
спасибо за помощь, однако я все еще не могу заставить это работать. Любые предложения относительно того, как я могу проверить, действительно ли зашифрованный текстовый файл попадает на сервер? Я удалил другие попытки чтения из потока после вызова decrypt(), и у меня все еще остался пустой текстовый файл. - person Kenoye Rukari; 06.09.2013