Jur Clerkx
Jur Clerkx

Reputation: 698

Switching java stream to cipher stream

I'm trying to create a protocol that let's the client send the server it's login name. After this the server get's the clients password from the server and creates a cipherkey from that. The client creates a key from the password that is entered. This way I'm trying to get a secure connection.

However, after sending the username, getting the password etc. I'm trying to create a new objectinputstream from the cypherstream to read the data, but it blocks. I can't find a way to get it working, even after looking at a lot of other similar questions.

Serverside

private void switchToChipherStreams(String username) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException {
    byte key[] = dbMediator.getPasswordCypher(username);
    SecretKey key64 = new SecretKeySpec(key, "Blowfish");
    Cipher cipher = Cipher.getInstance("Blowfish");
    cipher.init(Cipher.ENCRYPT_MODE, key64);
    try {
        Thread.sleep(1000);
    } catch (InterruptedException ex) {
        Logger.getLogger(Connection.class.getName()).log(Level.SEVERE, null, ex);
    }
    out = new ObjectOutputStream(new CipherOutputStream(socket.getOutputStream(), cipher));
    out.reset();
    out.flush();
    out.writeObject("switch");
    in = new ObjectInputStream(new CipherInputStream(socket.getInputStream(), cipher));
}

Client side

private void switchToChipherStreams(String password) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException {
    //Generate key
    byte[] key = new byte[8];
    for (int i = 0; i < 8; i++) {
        if (password.length() > i) {
            key[i] = password.getBytes()[i];
        } else {
            key[i] = (byte) i;
        }
    }
    //Setup cipher streams
    SecretKey key64 = new SecretKeySpec(key, "Blowfish");
    Cipher cipher = Cipher.getInstance("Blowfish");
    cipher.init(Cipher.ENCRYPT_MODE, key64);
    in = new ObjectInputStream(new CipherInputStream(socket.getInputStream(), cipher));
    out = new ObjectOutputStream(new CipherOutputStream(socket.getOutputStream(), cipher));
    out.reset();
    out.flush();
    out.writeObject("switch");
}

At the moment it's trowing an exception (invalid header), because I'm trying to send data over, but if I don't it just blocks.

Could anybody tell me what I'm doing wrong here, or if it's is even possible changing to ciphered objectinputstream.

Kind regards,

Jur

EDIT

Changed the cipher to encrypt and decrypt of in and output streams, new code:

Serverside

byte key[] = dbMediator.getPasswordCypher(username);
    SecretKey key64 = new SecretKeySpec(key, "Blowfish");
    Cipher cipheren = Cipher.getInstance("Blowfish");
    cipheren.init(Cipher.ENCRYPT_MODE, key64);
    Cipher cipherde = Cipher.getInstance("Blowfish");
    cipheren.init(Cipher.DECRYPT_MODE, key64);
    out = new ObjectOutputStream(new CipherOutputStream(socket.getOutputStream(), cipheren));
    out.reset();
    out.flush();
    out.writeObject("switch");
    in = new ObjectInputStream(new CipherInputStream(socket.getInputStream(), cipherde));

Client side

//Generate key
        byte[] key = new byte[8];
        for (int i = 0; i < 8; i++) {
            if (password.length() > i) {
                key[i] = password.getBytes()[i];
            } else {
                key[i] = (byte) i;
            }
        }
        //Setup cipher streams
        SecretKey key64 = new SecretKeySpec(key, "Blowfish");
        Cipher cipheren = Cipher.getInstance("Blowfish");
        cipheren.init(Cipher.ENCRYPT_MODE, key64);
        Cipher cipherde = Cipher.getInstance("Blowfish");
        cipheren.init(Cipher.DECRYPT_MODE, key64);
        out = new ObjectOutputStream(new CipherOutputStream(socket.getOutputStream(), cipheren));
        out.reset();
        out.flush();
        out.writeObject("switch");
        in = new ObjectInputStream(new CipherInputStream(socket.getInputStream(), cipherde));

Now the invalid head problem is solved, but is freezes both client and server when objectinputstream constructor is called.

Upvotes: 2

Views: 947

Answers (1)

user207421
user207421

Reputation: 310840

You can't create a cipher input and output stream from the same Cipher object. You need two Cipher objects, one in DECRYPT mode and one in ENCRYPT mode.

Create and flush the ObjectOutputStreambefore the ObjectInputStream at both ends.

Upvotes: 1

Related Questions