DRE
DRE

Reputation: 323

Encrypted socket connection java using RSA (IllegalArgumentException: Illegal base64 character 10)

So i am building a java app which uses a secure RSA connection to deliver data (at the moment i am coding encryption/decryption techniques by hand if there is a library or a better way to do this feel free to write it), it's the first time i am doing this so i don't know that much of the topic.

This is the class i use both on the server and the client side to encrypt/decrypt:

public class RSAEncryption extends AsymmetricalEncryption {

    public RSAEncryption() {
        super("RSA");
    }

    @Override
    public byte[] encrypt(String data) {
        Cipher cipher = null;
        byte[] encryptedData = new byte[0];
        try {
            cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, super.sharedKey);
            encryptedData = cipher.doFinal(data.getBytes());
            encryptedData = Base64.getEncoder().encode(encryptedData);
        } catch (Exception e) {
            System.err.println("Error on Cipher initialization " + e);
        }
        return encryptedData;
    }

    @Override
    public byte[] decrypt(byte[] data) {
        Cipher cipher = null;
        byte[] encryptedData = null;
        try {
            cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, super.privateKey);
            encryptedData = cipher.doFinal(Base64.getDecoder().decode(data));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return encryptedData;
    }

}

The RSAEncryption class AsymmetricalEncryption because i would like in the future to implement different encryption protocols. This is the Server-side connection:

public class Connection extends Thread {

    private Socket connection;
    private ObjectInputStream ois;
    private ObjectOutputStream oos;
    private AsymmetricalEncryption encryption;

    public Connection(Socket connection) {
        try {
            this.connection = connection;
            this.ois = new ObjectInputStream(connection.getInputStream());
            this.oos = new ObjectOutputStream(connection.getOutputStream());
            encryption = new RSAEncryption();
            // sending the public key
            oos.writeUTF(encryption.encodeBase64PublicKey(encryption.publicKey));
            oos.flush();
            // read sharedKey
            String encodedKey = ois.readUTF();
            encryption.setSharedKey(encryption.decodeBase64PublicKey(encodedKey, "RSA"));
            this.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public Connection(Socket connection, String encryptionMethod) {
        try {
            //this.connection = connection;
            this.ois = new ObjectInputStream(connection.getInputStream());
            this.oos = new ObjectOutputStream(connection.getOutputStream());
            encryption = AsymmetricalEncryptionFactory.getAsymmetricalEncryption(encryptionMethod);
            // sending the public key
            oos.writeUTF(encryption.encodeBase64PublicKey(encryption.publicKey));
            oos.flush();
            // read sharedKey
            String encodedKey = ois.readUTF();
            encryption.setSharedKey(encryption.decodeBase64PublicKey(encodedKey, encryptionMethod));
            this.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        boolean isRunning = true;
        while(isRunning){
            try {
                byte[] encryptedStringRequest = ois.readAllBytes();
                System.out.println("Encrypted Request: " + encryptedStringRequest);
                byte[] stringRequest = encryption.decrypt(encryptedStringRequest);
                System.out.println("Request: " + new String(stringRequest));
                System.out.println("When you fix the bug remeber to decomment the following two lines of Connection");
                //Request request = Request.parse(this, new JSONObject(stringRequest));
                //RequestQueue.RequestQueue().enqueue(request);
            } catch (Exception e) {
                e.printStackTrace();
                isRunning = false;
            }
        }
    }

    public void response(Response response){
        try {
            byte[] encryptedStringResponse = encryption.encrypt(response.toJSONString().getBytes());
            oos.write(encryptedStringResponse);
            oos.flush();
        } catch (IOException e) {
            System.err.println("Error during response sending "+ e);
        }
    }

}

This is the Client-side Connection:

public class Connection {

    private Socket connection;
    private ObjectInputStream ois;
    private ObjectOutputStream oos;
    private AsymmetricalEncryption encryption;

    public Connection(Socket connection) {
        try {
            this.connection = connection;
            this.oos = new ObjectOutputStream(connection.getOutputStream());
            this.ois = new ObjectInputStream(connection.getInputStream());
            encryption = new RSAEncryption();
            // sending the public key
            oos.writeUTF(encryption.encodeBase64PublicKey(encryption.publicKey));
            oos.flush();
            // read sharedKey
            String encodedKey = ois.readUTF();
            encryption.setSharedKey(encryption.decodeBase64PublicKey(encodedKey, "RSA"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public Connection(Socket connection, String encryptionMethod) {
        try {
            //this.connection = connection;
            this.ois = new ObjectInputStream(connection.getInputStream());
            this.oos = new ObjectOutputStream(connection.getOutputStream());
            encryption = AsymmetricalEncryptionFactory.getAsymmetricalEncryption(encryptionMethod);
            // sending the public key
            oos.writeUTF(encryption.encodeBase64PublicKey(encryption.publicKey));
            oos.flush();
            // read sharedKey
            String encodedKey = ois.readUTF();
            encryption.setSharedKey(encryption.decodeBase64PublicKey(encodedKey, encryptionMethod));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public Response request(Request request){
        try {
            byte[] encryptedStringResponse = encryption.encrypt(request.toJSONString());
            oos.write(encryptedStringResponse);
            oos.flush();
            byte[] response =  ois.readAllBytes();
            response = encryption.decrypt(response);
            return new Response(new JSONObject(new String(response)));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}

At the moment i don't know why but when i send data from client to server the server says that a new connection has come but hangs on doing nothing while in the client side it says that the data has been sent.

Upvotes: 2

Views: 858

Answers (1)

erickson
erickson

Reputation: 269627

The best way to do this is to use TLS. In Java, you can create server and client socket factories through an SSLContext.

It would be unethical to try to devise your own cryptosystem and apply it to any data that other people are trusting you to secure. But if you are doing this for fun, as a learning exercise, and don't intend to do any real work with it, you can make the most of your effort by trying to learn how real cryptosystems work.

RSA is relatively slow, and the amount of data that can be encrypted in each operation is limited by the RSA key size that you choose. It is best used to encrypt another key for a symmetric cipher like AES. This is how RSA is used in any widely accepted encryption scheme. Large amounts of application data can then encrypted quickly with the symmetric cipher, using a key exchanged via RSA.

Upvotes: 2

Related Questions