N
N
Neutro2014-06-17 13:45:46
Java
Neutro, 2014-06-17 13:45:46

Why doesn't CipherI/OStream pass data over Socket I/OStream?

There is a certain client-server application, a connection is established between them via java.net.Socket.
Using over the Output and Input stream Data stream, I transfer the public key, after which I hang Cipher streams on them and again Data streams. In the resulting code, input and output are DataI/OStream(CipherI/OStream(socket.getI/OStream,cipherI/O)). The bottom line is that data is either not received by the Input Stream or not sent by the Output Stream even with flush. How to make it work? The option to limit to one-way transfer is not suitable.
Send by client (stop on line 5):

try {
    UtilDHSocket socket = UtilDHSocket.safeInstance(0);
    socket.output().writeFloat(1.0F);
    socket.output().flush();
    int answer = socket.input().readInt();
    socket.input().close();
    socket.output().close();
    socket.close();
    return answer == 200;
} catch(Exception ex) {
    error(ex);
    return false;
}


Reception by the server (stop on the 2nd line):
try {
    float clientVersion = _input.readFloat();
    if(clientVersion == Main._version) {
        _output.writeInt(200);
    } else {
        _output.writeInt(418);
    }
    _output.flush();
    _input.close();
    _output.close();
    _client.close();
} catch(Exception ex) {
    warning("Unable to process packet form ",this._client.getInetAddress().getHostAddress());
    debug(ex);
}


UPD: Cipher initialization in the client
private void initDH() throws IOException {
    try {
        UtilDH util = new UtilDH(true);
        _output.writeUTF(UtilDH.bytesToString(util.getPublicKey().getEncoded()));
        _output.flush();
        util.getKeyAgreement().doPhase(util.serverPublicKey,true);
        Key secretKey = util.getKeyAgreement().generateSecret("AES");
        Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");
        c.init(Cipher.ENCRYPT_MODE,secretKey);
        CipherOutputStream cos = new CipherOutputStream(getOutputStream(),c);
        _output = new DataOutputStream(cos);
        c = Cipher.getInstance("AES/ECB/PKCS5Padding");
        c.init(Cipher.DECRYPT_MODE,secretKey);
        CipherInputStream cis = new CipherInputStream(getInputStream(),c);
        _input = new DataInputStream(cis);
        secretKey = null;
    } catch(Exception ex) {
        throw (IOException) new IOException(ex);
    }
}

Answer the question

In order to leave comments, you need to log in

1 answer(s)
V
vlad20012, 2014-06-26
@Neutro

The thing is that in ECB mode, data is encrypted in blocks. Accordingly, sending will occur only when a data block of a certain size is accumulated. To be able to send each byte separately, you should use the CTR mode.
Cipher.getInstance("AES/CTR/PKCS5Padding");

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question