CipherInputStream зависает - PullRequest
       12

CipherInputStream зависает

0 голосов
/ 13 ноября 2018

Я пытаюсь использовать шифрование для связи через сокеты с использованием Java. Я успешно общался с сокетами без шифрования, но когда я пытаюсь с шифрованием, программа зависает.

Вот родительский класс Connection, который отлично работает:

public class Connection implements Runnable
{
    protected Socket socket;
    protected ObjectInputStream objectInputStream;
    protected ObjectOutputStream objectOutputStream;
    protected Thread listeningThread;
    protected Thread dispatchThread;
    protected boolean listen;
    protected ArrayBlockingQueue<Object> readingQueue;
    protected ConnectionListener connectionListener;

    public Connection()
    {
        listen = true;
        readingQueue = new ArrayBlockingQueue<Object>(10);
    }

    public Connection(Socket socket, ConnectionListener listener)
    {
        listen = true;
        connectionListener = listener;
        readingQueue = new ArrayBlockingQueue<Object>(10);

        this.socket = socket;

        try 
        {
            objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
            objectInputStream = new ObjectInputStream(socket.getInputStream()); 
        } 
        catch (IOException e) 
        {
            e.printStackTrace();
        }

        startConnection();
    }

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

public class EncryptedConnection extends Connection
{
    private Key key;
    private Cipher cipherEncryption;
    private Cipher cipherDecryption;

    public EncryptedConnection(Socket socket, ConnectionListener listener, byte[] keydata)
    {
        super();
        super.socket = socket;
        super.connectionListener = listener;

        try
        {
            key = new SecretKeySpec(keydata, "AES");
            cipherEncryption = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipherDecryption = Cipher.getInstance("AES/CBC/PKCS5Padding");

            byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
            IvParameterSpec ivspec = new IvParameterSpec(iv);

            cipherEncryption.init(Cipher.ENCRYPT_MODE, key, ivspec);
            cipherDecryption.init(Cipher.DECRYPT_MODE, key, ivspec);

            objectOutputStream = new ObjectOutputStream(new CipherOutputStream(socket.getOutputStream(),cipherEncryption));
            objectInputStream = new ObjectInputStream(new CipherInputStream(socket.getInputStream(),cipherDecryption));
//The hanging or freezing occurs on the above line of code

        } 
        catch(Exception e)
        {

        }

Вот код сервера, который создает сокет:

@Override
    public void run() 
    {
        try 
        {
            while(true)
            {
                Socket s = serverSocket.accept();

                byte[] key = new byte[16];
                for(int i=0;i<key.length;i++)
                    key[i] = 0x01;


                EncryptedConnection c = new EncryptedConnection(s,connectionListener,key);

                connections.add(c);
                System.out.println("New Connection Established From"+s.getInetAddress().toString());
            }
        } 
        catch(java.net.SocketException e)
        {
            System.out.println("Listening thread terminated with exception.");
        }
        catch(IOException e) 
        {

            e.printStackTrace();
        }
    }

А вот код клиента, который создает сокет:

@Override
    public void actionPerformed(ActionEvent e) 
    {
        if(e.getSource() == connect)
        {
            try 
            {
                Socket s = new Socket(ipBox.getText(), Integer.parseInt(portBox.getText()));
                byte[] key = new byte[16];
                for(int i=0;i<key.length;i++)
                    key[i] = 0x01;
                EncryptedConnection c = new EncryptedConnection(s,parent,key);

                parent.connectionSuccessful(c);
            } 
            catch (NumberFormatException e1) 
            {
                JOptionPane.showMessageDialog(this, "Error! Port number must be a number", "Error", JOptionPane.ERROR_MESSAGE);             
            } 
            catch (UnknownHostException e1) 
            {
                JOptionPane.showMessageDialog(this, "Error! Unable to find that host", "Error", JOptionPane.ERROR_MESSAGE);
            } 
            catch (IOException e1) 
            {
                e1.printStackTrace();
            }   
        }
    }

Я просмотрел этот пост, но не нашел его полезным. ObjectInputStream с зависанием CipherInputStream, зависание Я также пробовал разные режимы шифрования AES с включением и выключением заполнения, но получаю тот же результат.

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

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.Key;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class IOTest 
{
    public static void main(String[] args) 
    {
        FileOutputStream fos   = null;
        FileInputStream fis    = null;
        CipherInputStream cis  = null;
        CipherOutputStream cos = null;
        ObjectOutputStream oos = null;
        ObjectInputStream  ois = null;
        Key key                = null;
        Cipher cipherD         = null;
        Cipher cipherE         = null;
        byte[] keydata         = new byte[16];
        byte[] iv              = new byte[16];
        IvParameterSpec ivspect = new IvParameterSpec(iv);

        try
        {
            key = new SecretKeySpec(keydata,"AES");
            cipherE = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipherD = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipherE.init(Cipher.ENCRYPT_MODE, key,ivspect);
            cipherD.init(Cipher.DECRYPT_MODE, key, ivspect);

            fos = new FileOutputStream("hello.data");
            cos = new CipherOutputStream(fos,cipherE);
            oos = new ObjectOutputStream(cos);

            oos.writeObject(new String("H"));
            oos.flush();
            oos.close();


            fis = new FileInputStream("hello.data");
            cis = new CipherInputStream(fis, cipherD);
            ois = new ObjectInputStream(cis);

            String s = ois.readObject().toString();
            System.out.println(s);

            ois.close();

        }
        catch(Exception e)
        {

        }
    }
}

1 Ответ

0 голосов
/ 13 ноября 2018

Поскольку AES является блочным шифром (размер блока 128 бит), он обрабатывает данные в блоках по 16 байт. Если данных для полного блока шифрования недостаточно, данные просто будут хранитьсяво входном буфере в ожидании большего количества данных.На приемном конце вы просто застряли.

Только при наличии достаточного количества данных для полного блока или если пары закрыты, будут обрабатываться застрявшие данные.В случае закрытия потока окончательные данные исправляются до полного размера блока в соответствии с используемой схемой заполнения (например, PKCS5Padding).

...