Моя проблема в том, что у меня есть 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
Обычная проблема. Вы игнорируете результат, возвращаемый read()
в какой-то момент и предполагая, что он заполняет буфер длины, а затем, если следующее чтение не возвращает точно такое количество байтов, которое вы игнорируете фактически возвращенные байты. Вам нужно сохранить результат, возвращаемый read()
в переменную, и:
Другие проблемы:
Тест Socket.isConnected()
здесь бессмыслен. Он не станет волшебным, если он отключится. Вы должны обнаружить это, получив -1 от read()
, null
от readLine(),
т.д.
Тоже socket == null
test. Он уже должен быть не нулевым, иначе вы бы socket.getOutputStream().
NPE в socket.getOutputStream().
Каждый раз вы создаете новый BufferedOutputStream
. Вы должны использовать его для жизни сокета.