Сертификаты Java и SSL

Я пытаюсь установить соединение с моим PHP-скриптом на Java с использованием уровня защищенных сокетов (HTTPS), но я обнаружил, что для обеспечения максимальной безопасности / достоверности я должен импортировать сертификат SSL, который мой веб-сайт использует в моем приложении... Что-то, что я не знаю, как сделать.

Если это помогает, мой SSL-сертификат не является самоподписанным, скорее предоставляется StartSSL, и я использую Eclipse IDE.

Кто-нибудь может указать мне правильное направление? т.е. какие файлы мне нужны, куда я должен их импортировать и какой код мне нужен в Java и т. д.?

5 ответов

Решение

Я обнаружил, что для обеспечения максимальной безопасности / действительности я должен импортировать сертификат SSL, который мой веб-сайт использует в моем приложении

Вы частично правы, когда делаете это заявление. Вам не нужно импортировать сертификат SSL. Достаточно импортировать сертификат CA StartSSL.

Кроме того, нет такой вещи, как импорт сертификата в приложение Java. Поддержка SSL в Java основана на концепции хранилищ ключей и доверенных сертификатов, а не на каком-то сертификате, упакованном в вашем приложении. Если вы публикуете свое приложение для загрузки и выполнения конечными пользователями, вам не нужно публиковать свой сертификат или, в этом случае, свой личный ключ в своем приложении. Закрытый ключ и связанный с ним сертификат будут храниться в хранилище ключей, к которому имеют доступ только вы.

Конечные пользователи вашего приложения будут полагаться на поддержку SSL во время выполнения Java, что позволит приложению устанавливать SSL-соединения с сайтами после проверки сертификата сервера. Среда выполнения Java поставляется с набором сертификатов CA по умолчанию в хранилище доверенных сертификатов, и единственным условием успешного установления SSL-соединений является выдача SSL-сертификата сервера одним из CA в хранилище доверенных сертификатов. Сертификаты StartSSL отсутствуют в доверенном хранилище среды выполнения Java, по крайней мере начиная с версии 6, и поэтому:

  • Вы можете поручить своим конечным пользователям выполнить импорт сертификата CA StartSSL в склад доверенных сертификатов Java. Ссылки, которые могут помочь, включают эту ветку форума StartSSL (для импорта сертификатов CA в хранилище доверенных сертификатов необходимы только первые 4 шага), проект GitHub и это сообщение в блоге; отказ от ответственности - я не пытался использовать ни один из них, и вы должны использовать его на свой страх и риск.
  • Или вы можете инициализировать ваше приложение с собственным складом доверенных сертификатов, используя -Djavax.net.ssl.trustStore=<path_to_truststore> -Djavax.net.ssl.trustStorePassword=<truststore_password> Флаги запуска JVM или выполните следующий код перед инициализацией соединений SSL:

    System.setProperty("javax.net.ssl.trustStore","<path_to_truststore>");
    System.setProperty("javax.net.ssl.trustStorePassword","<truststore_password>");
    

    Это жизнеспособный подход, только если ваше приложение является приложением Java SE, которое не является апплетом (или приложением с аналогичными ограничениями на то, как указано хранилище доверенных сертификатов).


Это также помогло бы прочитать документацию Java keytool.

Следующий метод загружает хранилище ключей по умолчанию (cacerts), проверяет, установлен ли сертификат, и устанавливает его, если нет. Это устраняет необходимость вручную запускать keystore Команда на любых серверах.

Предполагается, что пароль хранилища ключей по умолчанию (changeit) не изменился, обновите CACERTS_PASSWORD если не. Обратите внимание, что метод сохраняет хранилище ключей после добавления сертификата, поэтому после запуска, когда сертификат будет постоянно находиться в хранилище.

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;

/**
 * Add a certificate to the cacerts keystore if it's not already included
 */
public class SslUtil {
    private static final String CACERTS_PATH = "/lib/security/cacerts";

    // NOTE: DO NOT STORE PASSWORDS IN PLAIN TEXT CODE, LOAD AT RUNTIME FROM A SECURE CONFIG
    // DEFAULT CACERTS PASSWORD IS PROVIDED HERE AS A QUICK, NOT-FOR-PRODUCTION WORKING EXAMPLE
    // ALSO, CHANGE THE DEFAULT CACERTS PASSWORD, AS IT IMPLORES YOU TO!
    private static final String CACERTS_PASSWORD = "changeit";

    /**
     * Add a certificate to the cacerts keystore if it's not already included
     * 
     * @param alias The alias for the certificate, if added
     * @param certInputStream The certificate input stream
     * @throws KeyStoreException
     * @throws NoSuchAlgorithmException
     * @throws CertificateException
     * @throws IOException
     */
    public static void ensureSslCertIsInKeystore(String alias, InputStream certInputStream)
            throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException{
        //get default cacerts file
        final File cacertsFile = new File(System.getProperty("java.home") + CACERTS_PATH);
        if (!cacertsFile.exists()) {
            throw new FileNotFoundException(cacertsFile.getAbsolutePath());
        }

        //load cacerts keystore
        FileInputStream cacertsIs = new FileInputStream(cacertsFile);
        final KeyStore cacerts = KeyStore.getInstance(KeyStore.getDefaultType());
        cacerts.load(cacertsIs, CACERTS_PASSWORD.toCharArray());
        cacertsIs.close();

        //load certificate from input stream
        final CertificateFactory cf = CertificateFactory.getInstance("X.509");
        final Certificate cert = cf.generateCertificate(certInputStream);
        certInputStream.close();

        //check if cacerts contains the certificate
        if (cacerts.getCertificateAlias(cert) == null) {
            //cacerts doesn't contain the certificate, add it
            cacerts.setCertificateEntry(alias, cert);
            //write the updated cacerts keystore
            FileOutputStream cacertsOs = new FileOutputStream(cacertsFile);
            cacerts.store(cacertsOs, CACERTS_PASSWORD.toCharArray());
            cacertsOs.close();
        }
    }
}

Используйте это так:

SslUtil.ensureSslCertIsInKeystore("startssl", new FileInputStream("/path/to/cert.crt"));

Очевидно, что инженеры почтовых пушек по какой-то причине не хотят давать нам четкие инструкции о том, как решить эту проблему. Это то что я сделал

Мы запускаем tomcat8 и подключаемся через веб-сервисы Джерси к API почтового оружия. Я следовал инструкциям этого пользователя, и он работал нормально. Надеюсь, это кому-нибудь поможет.

1/22 мы обновили наши SSL-сертификаты, поскольку инфраструктура PKI Symantec стала ненадежной. Некоторые старые версии Java не имеют CA "DigiCert Global Root G2".

Есть несколько вариантов:

Импортируйте CA "DigiCert Global Root G2" в ваш файл "cacerts". Обновите JRE до 8u91 (или выше), который включает этот корень. Чтобы импортировать "DigiCert Global Root G2", вы можете скачать рут с https://www.digicert.com/digicert-root-certificates.htm. Убедитесь, что вы загружаете правильный корневой сертификат.

Как только сертификат будет загружен, вам нужно будет импортировать его с помощью команды, подобной следующей:

keytool -import -trustcacerts -keystore / path / to / cacerts -storepass changeit -noprompt -alias digicert-global-root-g2 -file /path/to/digicert.crt Вам потребуется указать путь к хранилищу ключей Java и расположение корневого сертификата, который вы скачали.


Итак, 1. /path/to/digicert.crt - это файл, который вы только что скачали. 2. / путь / к / cacerts - это ваш путь JRE. Я "найду / -name cacerts -print", это поможет вам быстро найти все java cacerts в вашей файловой системе. Для меня это был /usr/lib/jvm/java-7-openjdk-amd64/jre/lib/security/cacerts

Взгляните на следующую статью: http://stilius.net/java/java_ssl.php Содержит пример кода, который может помочь в случае, если вы пытаетесь получить доступ к вашему сценарию из кода.

Обратите внимание, что вы либо должны использовать системные свойства

javax.net.ssl.keyStore
javax.net.ssl.keyStorePassword

передать SSL-сертификат в JVM или импортировать его в хранилище ключей JRE с помощью инструмента keytool

Эта статья содержит код для изменения пароля доверенного хранилища и добавления туда других сертификатов:

http://thetechawesomeness.ideasmatter.info/changing-trust-store-password.html

Я обнаружил, что для обеспечения максимальной безопасности / действительности я должен импортировать сертификат SSL

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

Другие вопросы по тегам