0

I'm doing a uni project where the client has to send his Public Key to the Server, so I'm trying to send a DSA PublicKey via socket from the client to the server but I'm struggling, and all the solutions I found only apply to RSA Public Keys.

I'm using this to send information to the server:

BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

And i'm looking for a way to "transform" the PublicKey's values in a String and then the server converts that String into a PublicKey.

Part of the client code:

public Client(String nickname, int port, String ip, Socket socket){
        try {
            this.nickname=nickname;
            this.port= port;
            this.socket=socket;
            this.ip=ip;
            this.in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            this.out = new PrintWriter(socket.getOutputStream(), true);

            generateKeys(this);
            //sends client info to server
            out.println(nickname);
            out.println(port);
            out.println(ip);

            String c = this.getChave_pub().getEncoded().toString();
            out.println(c);
        }catch (IOException e){
            System.out.println("#### Error connecting! "+e+" ####");
        }
    }

public void generateKeys(Client client){
        KeyPairGenerator keyPairGen = null;
        try {
            keyPairGen = KeyPairGenerator.getInstance("DSA");
        } catch (NoSuchAlgorithmException e) {
            System.out.println("Error "+e);
        }
        keyPairGen.initialize(2048);

        KeyPair par = keyPairGen.generateKeyPair();

        //separate the pair of keys and put the values in the variables of the clients
        client.setKey_priv(par.getPrivate());
        client.setKey_pub(par.getPublic());
    }

Part of the server code:

public ClientHandler(Socket socket){
        try{
            this.socket=socket;
            this.in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            this.out = new PrintWriter(socket.getOutputStream(), true);
            this.nickname= in.readLine();
            this.port = in.readLine();
            this.ip = in.readLine();
            //i used to have stuff here but it doesn't work
            System.out.println("A new user has entered: "+ nickname + "\n");
        } catch (IOException e){
            System.out.println("#### Error "+e+" ####");
    }
}

I've tried also using ObjectOutputStream and ObjectInputStream to send it as an object, but i kept getting errors, being one of them:

java.io.StreamCorruptedException: invalid stream header: 73720014 

Also, don't come too hard on me, I'm yet learning now all about Private and Public Keys, I understand why the code doesn't work but i can't find other ways to do it.

UPDATE: I have now changed the code to send Object, and it's working but only if i create the obj_o/obj_in and the line after I write/read the object, if I separate them I get this error:

java.io.StreamCorruptedException: invalid stream header: 73720014 

Can somebody explain why?

Part of the client code:

public Client(String nickname, int port, String ip, Socket socket){
        try {
            this.nickname=nickname;
            this.port= port;
            this.socket=socket;
            this.ip=ip;
            this.in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            this.out = new PrintWriter(socket.getOutputStream(), true);

            generateKeys(this);
            //sends client info to server
            out.println(nickname);
            out.println(port);
            out.println(ip);

            ObjectOutputStream obj_o = new ObjectOutputStream(socket.getOutputStream());
            obj_o.writeObject(this.getChave_pub());
        }catch (IOException e){
            System.out.println("#### Error connecting! "+e+" ####");
        }
    }

public void generateKeys(Client client){
        KeyPairGenerator keyPairGen = null;
        try {
            keyPairGen = KeyPairGenerator.getInstance("DSA");
        } catch (NoSuchAlgorithmException e) {
            System.out.println("Error "+e);
        }
        keyPairGen.initialize(2048);

        KeyPair par = keyPairGen.generateKeyPair();

        //separate the pair of keys and put the values in the variables of the clients
        client.setKey_priv(par.getPrivate());
        client.setKey_pub(par.getPublic());
    }

Part of the server code:

public ClientHandler(Socket socket){
        try{
            this.socket=socket;
            this.in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            this.out = new PrintWriter(socket.getOutputStream(), true);
            this.nickname= in.readLine();
            this.port = in.readLine();
            this.ip = in.readLine();
            //only used to receive the object that represents the key
            ObjectInputStream obj_in = new ObjectInputStream(socket.getInputStream());      
            this.chave_pub=(PublicKey)obj_in.readObject();
            System.out.println("A new user has entered: "+ nickname + "\n");
        } catch (IOException e){
            System.out.println("#### Error "+e+" ####");
    }
}
Rui
  • 3
  • 2
  • `ObjectOutputStream` is a much more direct way of doing things . Please post your code using that class – g00se Dec 01 '22 at 23:11
  • `this.getChave_pub().getEncoded().toString()` doesn't make sense in Java. If you want to send a `byte[]` then send a `byte[]`, don't feel that you need to convert everything to string. – President James K. Polk Dec 02 '22 at 00:03
  • If you are sending data between Java programs then yes, ObjectOutputStream/ObjectInputStream may be simpler. – President James K. Polk Dec 02 '22 at 00:07
  • You're doing far too much in the ctor. Just do initializations - nothing else. Call the key generation method *after* that, not *in* it – g00se Dec 02 '22 at 00:35
  • @g00se I have changed my code using `ObjectOutputStream`. – Rui Dec 02 '22 at 10:53
  • None of the changes I suggested has been done. All you seem to have done is throw into the original an `ObjectOutputStream`, which in that context is incorrect. That should be the *only* thing writing to the output stream. – g00se Dec 02 '22 at 11:14
  • Personally I would make a `Serializable` class that encapsulates the ip, port, nickname and key and write that with `ObjectOutputStream` before proceeding with the 'real communication' – g00se Dec 02 '22 at 14:43

0 Answers0