У меня есть клиентские / серверные приложения на основе java TLS, которые я писал 2-3 года go и с тех пор почти ежедневно использую на различных установках linux. Я не делаю много работы в java - писать это было действительно упражнением.
Во всяком случае, это никогда не вызывало у меня горя с тех пор, до вчерашнего дня, когда я вдруг не могу пройти аутентификацию на сервере из коробки Fedora 31. Причиной было обновление openjdk накануне. Другие машины, на которых не было обновления, не имеют проблемы. Тем не менее, я попытался восстановить с помощью Oracle JDK 13, и проблема была воспроизведена.
Просто чтобы прояснить:
- Сервер, на котором выброшено исключение, не обновлено.
- Единственные клиенты, которые в настоящее время терпят неудачу, это клиенты, подключающиеся из системы с обновлением jdk.
- Компиляция всего приложения и тестирование с недавним Oracle JDK имеет проблема - клиенты не могут подключиться к серверам. Так что это то, что я должен исправить или откатить JRE и использовать это везде. > _ <</li>
Аутентификация выполняется с использованием PKIX, где имеется частный ЦС, поддерживающий набор сертификатов клиента и сервера, в файлах pkcs12, созданных с помощью keytool
. SSLContext
инициализируется с TrustManagerFactor
и KeyStore
более или менее так:
KeyStore trusts;
TrustManagerFactory tmf;
String trustPassword("abc123");
try (
FileInputStream trustIn =
new FileInputStream(new File("foobar.pkcs12"))
) {
tmf = TrustManagerFactory.getInstance("PKIX");
trusts = KeyStore.getInstance("pkcs12");
trusts.load(trustIn, trustPassword.toCharArray());
tmf.init(trusts);
}
SSLContext sscon = SSLContext.getInstance("TLSv1.2");
sscon.init (
someKeyManager,
tmf.getTrustManagers(),
new SecureRandom()
);
Как уже упоминалось, я не волшебник java. Тем не менее, я занимался сетевым программированием TLS на других языках, поэтому концепции довольно знакомы.
Создается сокет сервера:
SSLServerSocket listenSock = sscon
.getServerSocketFactory()
.createServerSocket(port, backlog);
И клиентское соединение:
SSLSocket client = (SSLSocket)listenSock.accept();
SSLParameters sslp = new SSLParameters();
sslp.setProtocols(new String[]{"TLSv1.2"});
client.setSSLParameters(sslp);
try { client.startHandshake(); }
То, что try
- это то место, где теперь на сервере выдается исключение, «Получено фатальное оповещение: сертификат_ответ» .
A jdb dump
исключения:
ex = {
serialVersionUID: 4511006460650708967
java.io.IOException.serialVersionUID: 7818375828146090155
java.lang.Exception.serialVersionUID: -3387516993124229948
java.lang.Throwable.serialVersionUID: -3042686055658047285
java.lang.Throwable.backtrace: instance of java.lang.Object[5] (id=2005)
java.lang.Throwable.detailMessage: "readHandshakeRecord"
java.lang.Throwable.UNASSIGNED_STACK: instance of java.lang.StackTraceElement[0] (id=2007)
java.lang.Throwable.cause: instance of java.net.SocketException(id=2008)
java.lang.Throwable.stackTrace: instance of java.lang.StackTraceElement[0] (id=2007)
java.lang.Throwable.depth: 5
java.lang.Throwable.SUPPRESSED_SENTINEL: instance of java.util.Collections$EmptyList(id=2009)
java.lang.Throwable.suppressedExceptions: instance of java.util.ArrayList(id=2010)
java.lang.Throwable.NULL_CAUSE_MESSAGE: "Cannot suppress a null exception."
java.lang.Throwable.SELF_SUPPRESSION_MESSAGE: "Self-suppression not permitted"
java.lang.Throwable.CAUSE_CAPTION: "Caused by: "
java.lang.Throwable.SUPPRESSED_CAPTION: "Suppressed: "
java.lang.Throwable.EMPTY_THROWABLE_ARRAY: instance of java.lang.Throwable[0] (id=2015)
java.lang.Throwable.$assertionsDisabled: true
}
Ничто из этого не полезно для меня, то есть я не понимать это.
Откуда я go отсюда? Сертификаты в порядке, по крайней мере, в соответствии с keytool
, и, как уже упоминалось, этот код работал в течение многих лет, часто обращался без проблем. 1 Я искал вокруг о специфике * Ошибка 1064 * («сертификат неизвестен»), но результаты не очень полезны - сертификат есть, сертификат не просрочен, доверие было загружено изначально без спецификации, и т. Д. c.
- Это включает в себя регенерацию материала PKIX с
keytool
через регулярные промежутки времени, поскольку сертификаты создаются с ограниченным сроком службы. Пары ключей используют 2048 бит RSA и -sigalg SHA256withRSA
.