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

huangapple go评论82阅读模式
英文:

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

问题

以下是翻译好的内容:

我正在构建一个使用安全RSA连接传输数据的Java应用程序(目前我正在手动编写加密/解密技术,如果有库或更好的方法来实现这一点,请随意说明),这是我第一次这样做,所以我对这个主题了解不多。

这是我在服务器和客户端上都用来加密/解密的类:

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("Cipher初始化错误:" + 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;
    }
}

RSAEncryption类继承了AsymmetricalEncryption,因为我希望将来能够实现不同的加密协议。

这是服务器端的连接:

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();
            // 发送公钥
            oos.writeUTF(encryption.encodeBase64PublicKey(encryption.publicKey));
            oos.flush();
            // 读取sharedKey
            String encodedKey = ois.readUTF();
            encryption.setSharedKey(encryption.decodeBase64PublicKey(encodedKey, "RSA"));
            this.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 其他代码...

    @Override
    public void run() {
        // ...
    }

    public void response(Response response){
        // ...
    }
}

这是客户端的连接:

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();
            // 发送公钥
            oos.writeUTF(encryption.encodeBase64PublicKey(encryption.publicKey));
            oos.flush();
            // 读取sharedKey
            String encodedKey = ois.readUTF();
            encryption.setSharedKey(encryption.decodeBase64PublicKey(encodedKey, "RSA"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 其他代码...

    public Response request(Request request){
        // ...
    }
}

目前我不知道为什么,但当我从客户端向服务器发送数据时,服务器会显示一个新连接已经到来,但却停在了什么都不做的地方,而在客户端中,它会显示数据已经被发送。

英文:

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.

答案1

得分: 2

用TLS来实现这一点是最好的方法。在Java中,您可以通过SSLContext创建服务器和客户端套接字工厂。

试图设计自己的加密系统并将其应用于其他人信任您保护的任何数据是不道德的。但是,如果您是出于兴趣或学习目的而这样做,并且不打算在实际工作中使用它,您可以通过尝试学习实际加密系统的工作原理来充分利用自己的努力。

RSA的速度相对较慢,并且每次操作可以加密的数据量受您选择的RSA密钥大小的限制。它最好用于为诸如AES的对称密码编码器加密另一个密钥。这是RSA在任何广泛接受的加密方案中的用法。然后,可以使用通过RSA交换的密钥,通过对称密码编码器快速加密大量应用数据。

英文:

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.

huangapple
  • 本文由 发表于 2020年10月10日 22:06:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/64294303.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定