Java MySQL SSL-соединение с указанным сертификатом - PullRequest
0 голосов
/ 09 сентября 2018

Я пытаюсь создать приложение Java, которое использует jdbc (Connector / J) для подключения к базе данных mariadb с использованием SSL-шифрования. Я уже создал самозаверяющий сертификат, настроил сервер для его использования. Когда я пытаюсь подключиться, я получаю исключение, потому что сертификат не является доверенным, потому что он самоподписан и не добавлен в хранилище доверенных сертификатов Java. Поскольку я хочу изменить TrustStore или использовать другое для своего приложения, я искал способ сообщить только jdbc, какой сертификат является доверенным, и обнаружил "https://mariadb.com/kb/en/library/using-tlsssl-with-mariadb-connectorj/ Предоставить сертификат напрямую"

Когда я сейчас пытаюсь соединиться с:

DriverManager.getConnection("jdbc:mysql://<hostname>:3306/<database>?useSSL=true&requireSSL=true&serverSslCert=/tmp/ssl/server-cert.pem", "<username>", "<password>");

Я получаю это исключение, которое я уже получил, прежде чем больше не использовать параметр serverSslCert:

Exception in thread "main" 

com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

The last packet successfully received from the server was 136 milliseconds ago.  The last packet sent successfully to the server was 129 milliseconds ago.
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:425)
    at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:990)
    at com.mysql.jdbc.ExportControlled.transformSocketToSSLSocket(ExportControlled.java:203)
    at com.mysql.jdbc.MysqlIO.negotiateSSLConnection(MysqlIO.java:4901)
    at com.mysql.jdbc.MysqlIO.proceedHandshakeWithPluggableAuthentication(MysqlIO.java:1659)
    at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1226)
    at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2188)
    at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2219)
    at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2014)
    at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:776)
    at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:47)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:425)
    at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:386)
    at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:330)
    at gymcash.server.mysql.DriverWrapper.connect(DriverWrapper.java:22)
    at java.sql.DriverManager.getConnection(DriverManager.java:664)
    at java.sql.DriverManager.getConnection(DriverManager.java:247)
    at gymcash.server.mysql.MySQL.connect(MySQL.java:48)
    at gymcash.server.mysql.MySQL.connect(MySQL.java:52)
    at gymcash.server.main.Main.main(Main.java:25)
Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
    at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1964)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:328)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:322)
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1614)
    at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
    at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1052)
    at sun.security.ssl.Handshaker.process_record(Handshaker.java:987)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1072)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1385)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1413)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1397)
    at com.mysql.jdbc.ExportControlled.transformSocketToSSLSocket(ExportControlled.java:188)
    ... 21 more
Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors
    at com.mysql.jdbc.ExportControlled$X509TrustManagerWrapper.checkServerTrusted(ExportControlled.java:304)
    at 

sun.security.ssl.AbstractTrustManagerWrapper.checkServerTrusted(SSLContextImpl.java:992)
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1596)
    ... 29 more
Caused by: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors
    at sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:154)
    at sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:80)
    at java.security.cert.CertPathValidator.validate(CertPathValidator.java:292)
    at com.mysql.jdbc.ExportControlled$X509TrustManagerWrapper.checkServerTrusted(ExportControlled.java:297)
    ... 31 more

Я не понимаю, что я делаю неправильно, потому что файл существует, путь является абсолютным и используется сервером. Может кто-нибудь сказать, пожалуйста, что я делаю не так?

Я использую Java 8, mysql-connector-java-5.1.45

1 Ответ

0 голосов
/ 09 сентября 2018

Есть несколько способов сделать это. Один из них помещает самозаверяющий сертификат или центр сертификации, который вы использовали для подписания сертификата, в хранилище ключей Java по умолчанию, используемое JVM, с которой вы соединяетесь. Вам нужно использовать Keytool для этого. Но если вы не управляете корпоративным пакетом виртуальных машин, вы, вероятно, не захотите захватить хранилище ключей по умолчанию в пакете безопасности.

Сначала вам нужно понять, как работает ключевой инструмент.

[Команды инструмента Java Key] [1] https://www.sslshopper.com/article-most-common-java-keytool-keystore-commands.html

Проблема в том, что у вас может не быть доступа к хранилищу ключей по умолчанию, и он может не принять формат сертификата, который вы используете. Требуется работа в тренажерном зале, конвертирование сертификатов и сопоставление поддерживаемых криптоалгоритмов

Как правило, если вы не управляете предприятием, лучше просто

  1. создать новый файл хранилища ключей
  2. импортировать ваш сертификат в это хранилище ключей (или цепочку сертификатов)
  3. убедитесь, что вы отметили его как доверенное
  4. передать хранилище ключей вашей программе во время выполнения, используя опцию -D.

Обычно я просто добавляю это к своему коду и устанавливаю свойства перед подключением к БД

if (DB_SSL || SSL) {
            System.setProperty("javax.net.ssl.keyStore", KEYSTORE);
            System.setProperty("javax.net.ssl.keyStorePassword", KEYSTORE_PASS);
            System.setProperty("javax.net.ssl.trustStore", KEYSTORE);
            System.setProperty("javax.net.ssl.trustStorePassword", KEYSTORE_PASS);
        if (DEBUG_OPTION) {
            System.setProperty("javax.net.debug", "true");
        }
    }

private static String KEYSTORE = "/home/me/.keystore";
private static String KEYSTORE_PASS = "changeit";
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...