TCP-соединение Java SSL нормально, но данные, полученные на сервер, неверны

1

Моя проблема в том, что у меня есть ssl-соединение между java-iso-клиентом и тестовым сервером. Соединение в порядке, никаких проблем с рукопожатием, но сервер получает неверные данные.

Как я вижу, в журнале сервер получает только частичные данные во время одной операции чтения, а некоторые странные данные также присутствуют во входном потоке - возможно, это связано с информацией сертификата.

Обратите внимание: без ssl этот клиент и сервер работают без проблем. Также, когда я создаю стандартный сертификат jks, просто java keyTool, все в порядке, и проблема не возникает.

Но когда я работаю с x509, проблемы возникают независимо от того, отправляю ли я сертификат как параметр для jvm сервера, генерируя jks из cmd или используя код ниже для генерации jks в коде. Соединение и рукопожатие всегда в порядке, но данные во входном потоке нарушены.

Это как получить сертификат, используя библиотеку boucycastle. Почти то же самое для клиента и сервера

private SSLServerSocketFactory handleCertificate() throws KeyManagementException, KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, UnrecoverableKeyException {
    Security.addProvider(new BouncyCastleProvider());

    PEMReader pr = new PEMReader(new FileReader("p.pem"));
    X509CertificateObject cert = (X509CertificateObject) pr.readObject();

    PEMReader pr2 = new PEMReader(new FileReader("klient.cer"));
    X509CertificateObject cert2 = (X509CertificateObject) pr2.readObject();

    PEMReader kr = new PEMReader(new FileReader("001.key"),
            new PasswordFinder() {
                public char[] getPassword() {
                    return "password".toCharArray();
                }
            });

    KeyStore trustKeys = KeyStore.getInstance("JKS");
    trustKeys.load(null, "".toCharArray());
    trustKeys.setCertificateEntry("1", cert);

    KeyStore ksKeys = KeyStore.getInstance("JKS");
    ksKeys.load(null, "password".toCharArray());
    ksKeys.setCertificateEntry("1", cert2);

    org.bouncycastle.jce.provider.JCERSAPrivateCrtKey key;
    Object PK = kr.readObject();

    if (PK instanceof KeyPair) {
        key = (JCERSAPrivateCrtKey) ((KeyPair) PK).getPrivate();
    } else {
        key = (JCERSAPrivateCrtKey) PK;
    }

    ksKeys.setKeyEntry("1", key, "password".toCharArray(), new Certificate[] { cert2 });

    KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
    kmf.init(ksKeys, "password".toCharArray());

    TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
    tmf.init(trustKeys);

    SSLContext sslContext = SSLContext.getInstance("SSLv3");
    sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new java.security.SecureRandom());

    SSLServerSocketFactory factory = sslContext.getServerSocketFactory();
    return factory;
}

Код сервера:

    InputStream is = new BufferedInputStream(socket.getInputStream());
        while (!Thread.currentThread().isInterrupted()) {
            int size = 0;
            String mess_length = "";
            byte[] lenbuf = new byte[4];
            if (socket != null && socket.isConnected()) {
                socket.getInputStream().read(lenbuf);
                mess_length = new String(lenbuf);
                log.debug("Lenth of received message: " + mess_length);
            }
            int responseSize = 0;
            try {
                responseSize = Integer.valueOf(mess_length);
                size = responseSize;
            } catch (Exception int_e) {
                log.debug("Error of message lenth numbering: ", int_e);

            }
            byte[] buf = new byte[size];
            if (socket.isConnected() && socket.getInputStream().read(buf) == size) {
                log.debug("Message received.");
            }

            // -----------------------------------------------------------------------------------------------------------
            OutputStream out = new BufferedOutputStream(socket.getOutputStream());
            if ("echo".equals(EnvironmentProperties.getMode())) {
                log.info("responsing in echo mode");
                log.debug("Data to send from server: {} in connection id={}", new String(buf,
                        "UTF-8"), uuid);
                out.write(buf);
            }
            out.flush();
            bytesSet.clear();
            log.info("responded");

журнал с сервера:


    17:37:26.166 [pool-1-thread-13] DEBUG r.b.t.app.server.ConnectionCallable - Mess
    age received.
    17:37:26.166 [pool-1-thread-13] INFO  r.b.t.app.server.ConnectionCallable - resp
    onsing in echo mode
    17:37:26.166 [pool-1-thread-13] DEBUG r.b.t.app.server.ConnectionCallable - Data
     to send from server:  in connection id=ee7f73ac-6be9-4e7b-876f-35d31845d69e
    17:37:26.166 [pool-1-thread-13] INFO  r.b.t.app.server.ConnectionCallable - resp
    onded
    17:37:26.166 [pool-1-thread-13] DEBUG r.b.t.app.server.ConnectionCallable - Lent
    h of received message: 200r
    17:37:26.167 [pool-1-thread-13] DEBUG r.b.t.app.server.ConnectionCallable - :
    java.lang.NumberFormatException: For input string: "200r"
            at java.lang.NumberFormatException.forInputString(Unknown Source) ~[na:1
    .8.0_05]
            at java.lang.Integer.parseInt(Unknown Source) ~[na:1.8.0_05]
            at java.lang.Integer.valueOf(Unknown Source) ~[na:1.8.0_05]
            at ru.billing.tcpipServerDummy.app.server.ConnectionCallable.call(Connec
    tionCallable.java:87) [TcpipServerDummy-0.0.1-SNAPSHOT.jar:na]
            at ru.billing.tcpipServerDummy.app.server.ConnectionCallable.call(Connec
    tionCallable.java:1) [TcpipServerDummy-0.0.1-SNAPSHOT.jar:na]
            at java.util.concurrent.FutureTask.run(Unknown Source) [na:1.8.0_05]
            at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [na
    :1.8.0_05]
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [n
    a:1.8.0_05]
            at java.lang.Thread.run(Unknown Source) [na:1.8.0_05]
    17:37:26.167 [pool-1-thread-13] DEBUG r.b.t.app.server.ConnectionCallable - Mess
    age received.
    17:37:26.167 [pool-1-thread-13] INFO  r.b.t.app.server.ConnectionCallable - resp
    onsing in echo mode
    17:37:26.167 [pool-1-thread-13] DEBUG r.b.t.app.server.ConnectionCallable - Data
     to send from server:  in connection id=ee7f73ac-6be9-4e7b-876f-35d31845d69e
    17:37:26.168 [pool-1-thread-13] INFO  r.b.t.app.server.ConnectionCallable - resp
    onded
    17:37:26.168 [pool-1-thread-13] DEBUG r.b.t.app.server.ConnectionCallable - Lent
    h of received message: 4А
    17:37:26.168 [pool-1-thread-13] DEBUG r.b.t.app.server.ConnectionCallable - ╬°шс
    ър яЁхюсЁрчютрэш  фышэ√ ёююс∙хэш :
    java.lang.NumberFormatException: For input string: "4А "
            at java.lang.NumberFormatException.forInputString(Unknown Source) ~[na:1
    .8.0_05]
            at java.lang.Integer.parseInt(Unknown Source) ~[na:1.8.0_05]
            at java.lang.Integer.valueOf(Unknown Source) ~[na:1.8.0_05]
            at ru.billing.tcpipServerDummy.app.server.ConnectionCallable.call(Connec
    tionCallable.java:87) [TcpipServerDummy-0.0.1-SNAPSHOT.jar:na]
            at ru.billing.tcpipServerDummy.app.server.ConnectionCallable.call(Connec
    tionCallable.java:1) [TcpipServerDummy-0.0.1-SNAPSHOT.jar:na]
            at java.util.concurrent.FutureTask.run(Unknown Source) [na:1.8.0_05]
            at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [na
    :1.8.0_05]
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [n
    a:1.8.0_05]
            at java.lang.Thread.run(Unknown Source) [na:1.8.0_05]
    17:37:26.168 [pool-1-thread-13] DEBUG r.b.t.app.server.ConnectionCallable - Mess
    age received.
    17:37:26.168 [pool-1-thread-13] INFO  r.b.t.app.server.ConnectionCallable - resp
    onsing in echo mode
    17:37:26.168 [pool-1-thread-13] DEBUG r.b.t.app.server.ConnectionCallable - Data
     to send from server:  in connection id=ee7f73ac-6be9-4e7b-876f-35d31845d69e
    17:37:26.168 [pool-1-thread-13] INFO  r.b.t.app.server.ConnectionCallable - resp
    onded
    17:37:26.168 [pool-1-thread-13] DEBUG r.b.t.app.server.ConnectionCallable - Lent
    h of received message: ┴А 2
    17:37:26.169 [pool-1-thread-13] DEBUG r.b.t.app.server.ConnectionCallable - ╬°шс
    ър яЁхюсЁрчютрэш  фышэ√ ёююс∙хэш :
    java.lang.NumberFormatException: For input string: "┴А 2"
            at java.lang.NumberFormatException.forInputString(Unknown Source) ~[na:1
    .8.0_05]
            at java.lang.Integer.parseInt(Unknown Source) ~[na:1.8.0_05]
            at java.lang.Integer.valueOf(Unknown Source) ~[na:1.8.0_05]
            at ru.billing.tcpipServerDummy.app.server.ConnectionCallable.call(Connec
    tionCallable.java:87) [TcpipServerDummy-0.0.1-SNAPSHOT.jar:na]
            at ru.billing.tcpipServerDummy.app.server.ConnectionCallable.call(Connec
    tionCallable.java:1) [TcpipServerDummy-0.0.1-SNAPSHOT.jar:na]
            at java.util.concurrent.FutureTask.run(Unknown Source) [na:1.8.0_05]
            at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [na
    :1.8.0_05]
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [n
    a:1.8.0_05]
            at java.lang.Thread.run(Unknown Source) [na:1.8.0_05]
    17:37:26.169 [pool-1-thread-13] DEBUG r.b.t.app.server.ConnectionCallable - Mess
    age received.
    17:37:26.169 [pool-1-thread-13] INFO  r.b.t.app.server.ConnectionCallable - resp
    onsing in echo mode
    17:37:26.169 [pool-1-thread-13] DEBUG r.b.t.app.server.ConnectionCallable - Data
     to send from server:  in connection id=ee7f73ac-6be9-4e7b-876f-35d31845d69e
    17:37:26.169 [pool-1-thread-13] INFO  r.b.t.app.server.ConnectionCallable - resp
    onded
    17:37:26.169 [pool-1-thread-13] DEBUG r.b.t.app.server.ConnectionCallable - Lent
    h of received message: 1194
    17:37:26.169 [pool-1-thread-13] DEBUG r.b.t.app.server.ConnectionCallable - ╧Ёхю
    сЁрчютрээр  фышээр ёююс∙хэш : 1194
    17:37:26.169 [pool-1-thread-13] INFO  r.b.t.app.server.ConnectionCallable - resp
    onsing in echo mode
    17:37:26.169 [pool-1-thread-13] DEBUG r.b.t.app.server.ConnectionCallable - Data
     to send from server: 6817121021052420000000000000000100000730173724000048001121
    101581111310001749439  749138         00809203123643













                     in connection id=ee7f73ac-6be9-4e7b-876f-35d31845d69e

  • 0
    Не могли бы вы рассказать нам больше об ОС вашего клиента и сервера? Сервер и клиент работают в одной системе?
  • 0
    Клиент и сервер работают на Win7 на localhost. JVM 8
Теги:
ssl
tcp
x509

1 ответ

3
Лучший ответ

Обычная проблема. Вы игнорируете результат, возвращаемый read() в какой-то момент и предполагая, что он заполняет буфер длины, а затем, если следующее чтение не возвращает точно такое количество байтов, которое вы игнорируете фактически возвращенные байты. Вам нужно сохранить результат, возвращаемый read() в переменную, и:

  • проверьте его на -1, указав конец потока
  • в противном случае продолжайте цикл, пока не получите цельное сообщение, однако это определено в вашем протоколе приложения.

Другие проблемы:

  • Тест Socket.isConnected() здесь бессмыслен. Он не станет волшебным, если он отключится. Вы должны обнаружить это, получив -1 от read(), null от readLine(), т.д.

  • Тоже socket == null test. Он уже должен быть не нулевым, иначе вы бы socket.getOutputStream(). NPE в socket.getOutputStream().

  • Каждый раз вы создаете новый BufferedOutputStream. Вы должны использовать его для жизни сокета.

  • 0
    Спасибо, некоторые проблемы исчезают.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню