Почему CipherI/OStream не передаёт данные поверх Socket I/OStream?

Есть некое клиент-серверное приложение, между ними устанавливается соединение посредством java.net.Socket.
Используя поверх Output и Input stream Data stream передаю открытый ключ, после чего вешаю на них Cipher streamы и опять Data streamы. В итоговом коде input и output это DataI/OStream(CipherI/OStream(socket.getI/OStream,cipherI/O)). Суть в том, что данные или не принимаются Input Streamом или не отправляются Output Streamом даже при flush. Как это заставить работать? Вариант ограничить до односторонней передачи не подходит.
Отправка клиентом (остановка на 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;
}


Приём сервером (остановка на 2й строке):
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 в клиенте
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);
    }
}
  • Вопрос задан
  • 2412 просмотров
Решения вопроса 1
vlad20012
@vlad20012
Тут все дело в том, что в режиме ECB данные шифруются блоками. Соответственно, отправка будет происходить только при накоплении блока данных определенного размера. Для возможности отправки отдельно каждого байта, стоит использовать режим CTR.
Cipher.getInstance("AES/CTR/PKCS5Padding");
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы