truststore keystore что это
Определения Truststore и Keystore
В чем разница между хранилищем ключей и хранилищем доверенных сертификатов?
Хранилище ключей содержит закрытые ключи и сертификаты с соответствующими им открытыми ключами.
Склад доверенных сертификатов содержит сертификаты от других сторон, с которыми вы собираетесь общаться, или от центров сертификации, которым вы доверяете для идентификации других сторон.
Хранилище ключей содержит закрытые ключи. Это необходимо только в том случае, если вы являетесь сервером или если сервер требует аутентификации клиента.
Склад доверенных сертификатов содержит сертификаты CA для доверия. Если сертификат вашего сервера подписан распознанным центром сертификации, хранилище доверенных сертификатов по умолчанию, которое поставляется вместе с JRE, уже будет доверять ему (потому что оно уже доверяет надежным центрам сертификации), поэтому вам не нужно создавать собственный или добавлять что-либо к нему. от JRE.
KeyStore
keyStore в Java хранит закрытый ключ и сертификаты, соответствующие их открытым ключам, и требует, если вы являетесь сервером SSL или SSL требует аутентификации клиента.
доверенные сертификаты
TrustStore хранит сертификаты от третьих лиц, ваше Java-приложение или сертификаты, подписанные CA (центрами сертификации, такими как Verisign, Thawte, Geotrust или GoDaddy), которые можно использовать для идентификации третьих лиц.
TrustManager
TrustManager определяет, следует ли доверять удаленному соединению, т. Е. Является ли удаленная сторона тем, на кого она претендует, и KeyManager решает, какие учетные данные для аутентификации следует отправить на удаленный хост для аутентификации во время SSL-квитирования.
Вас также может заинтересовать рецензия от Sun как часть стандартной документации JSSE:
Как правило, хранилище доверенных сертификатов используется для хранения только открытых ключей в целях проверки, например, при проверке подлинности X.509. Для удобства управления администраторы и разработчики часто просто объединяют их в одном магазине.
В Java, в чем разница между хранилищем ключей и хранилищем доверенных сертификатов?
Хранилище ключей / доверенное хранилище
Вообще говоря, информация о хранилище ключей может быть сгруппирована в две категории: записи ключей и записи доверенных сертификатов. Запись ключа состоит из идентификатора объекта и его закрытого ключа и может использоваться для различных криптографических целей. Напротив, запись доверенного сертификата содержит только открытый ключ в дополнение к идентификатору объекта. Таким образом, запись доверенного сертификата не может использоваться там, где требуется закрытый ключ, например, в javax.net.ssl.KeyManager. В реализации JKS JDK хранилище ключей может содержать как записи ключей, так и записи доверенных сертификатов.
Запись должна быть добавлена в доверенное хранилище, только если пользователь доверяет этой сущности. Генерируя пару ключей или импортируя сертификат, пользователь доверяет этой записи. Любая запись в хранилище доверенных сертификатов считается доверенной.
Первое и основное различие между trustStore и keyStore заключается в том, что trustStore используется TrustManager, чтобы определить, следует ли доверять удаленному соединению, keyStore используется из KeyManager, решая, какие учетные данные для аутентификации следует отправлять на удаленный хост для аутентификации во время рукопожатия SSL.
Другое отличие состоит в том, что keyStore теоретически содержит закрытые ключи, необходимые только в том случае, если вы запускаете сервер в соединении SSL или вы включили аутентификацию клиента на стороне сервера, а с другой стороны trustStore хранит открытый ключ или сертификаты от CA (Certificate Authorities), которые используются для доверяйте удаленной стороне или соединению SSL.
Keystore в Java
Что такое Java Keystore?
Keystore используется для хранения собственных приватных ключей и сертификатов сервера или клиента.
Для аутентификации клиента и сервера устанавливающих SSL соединение требуются приватные ключи и сертификаты. Если используется односторонняя аутентификация, то keystore нужен только на серверной стороне. При двусторонней аутентификации и клиент и сервер обмениваются сертификатами, соответственно и у сервера, и у клиента должен быть keystore с парой приватный ключ/публичный ключ + сертификат.
Т.е. иными словами Keystore используется для хранения ключей и сертификатов, использующихся для идентификации владельца ключа (клиента или сервера).
Trust Store
Второй тип keystore применяется для хранения trusted сертификатов. В него кладутся ключи trusted certificate authorities CA. При пользовании самоподписанными сертификатами, в trusted store может класться самоподписанный сертификат. Это тоже keystore, но в Java он называется trusted store.
Форматы Keystore поддерживаемые Java
Т.о., как описано выше, keystore — контейнер, используемый для хранения ключей и сертификатов. Java поддерживает два формата keystore:
Тип keystore, используемый по-умолчанию, задается в Java security properties файле свойством keystore.type. Если приложение обращается к key store файлу без явного указания его типа, используется JKS формат. Java security properties файл расположен в каталоге lib внутри инсталляционного директория с Java по пути: /lib/security/java.security
Для работы с keystore в java дистрибутиве есть специальная утилита keytool. Keytool вполне достаточно для операций с ключами в Java. Однако JKS формат является пропиетарным и закрытым. Поэтому часто для разнообразных конвертаций и взаимодействия со сторонними разработчиками могут использоваться утилиты, поставляемые в комплекте с библиотекой OpenSSL.
В тех случаях, когда планируется использовать ключи исключительно в Java keystore в формате JKS вполне подойдет.
Алиасы
Keystore (по крайней мере в JKS формате), позволяет хранить несколько пар ключей и сертификатов. Для идентификации каждой пары или отдельного сертификата используется алиас. Алиас указывается в исходном коде при доступе к соответствующему ключу или сертификату. Доступ к каждому алиасу ограничивается паролем.
Создание keystore
Процесс генерации keystore (JKS или PKS12) включает генерацию пары ключей (приватного и публичного). Затем получение от Certificate Authority (CA) подписи к публичному ключу и связанной с ним идентифицирующей информации в виде сертификата. Certificate authority генерирует сертификат на основе публичного ключа и идентификационной информации, переданной ему в виде CSR.
Wikipedia говорит, что CA выдает сертификат, привязывающий публичный ключ к указанному Distinguished Name (это может быть имя хоста (hostname, имя пользователя или название приложения). Шаги по созданию keystore представляющего пользователя, приложение или хост следующие:
В java при генерации пары ключей с помощью keytool сразу создается самоподписанный self-signed сертификат, который можно немедленно использовать для тестирования. Следующие шаги, таким образом, нужны только для создания полноценного официального сертификата.
Сгенерировать запрос на получение сертификата (Certificate Signing Request (CSR)).
Получить CSR, подписанный доверенным CA (output of this is a certificate)
Импортировать сертификат, сделанный CA в ваш key store.
Импортировать сертификат CA в ваш truststore как trusted certificate
Java’s Default Keystore
Java’s Default Truststore
Приложение может указать Java использовать определенный truststore файл установкой свойства javax.net.ssl.trustStore. Если приложение не указывает явно truststore, тогда truststore по-умолчанию загружается и используется. По-умолчанию java truststore находится в /lib/security/cacerts и его пароль по-умолчанию: ‘changeit’. Файлы truststore — обычные keystore файлы, содержащие один или более сертификатов trusted CA (Certificate Authorities).
Keytool
Для облегчения создания и управления keystore файлами в дистрибутив Java входит утилита keytool, позволяющая создавать JKS файлы. Keytool позволяет управление сертификатами и парами публичных приватных ключей.
Сертификат создается в формате X.509. В этом формате в качестве идентификатора владельца используется Distinquished Name или просто DN в формате X.500. Точно такой же формат идентификации объектов используется, например в LDAP-протоколе или в SNMP. Distinquished Name задается в виде разделенных через запятую атрибутов: «CN=Andrey Chesnokov, OU=dev64, O=dev64-wordpress, L=Unknown, ST=Unknown, C=RU». Здесь отдельные атрибуты расшифровываются так:
Часть из атрибутов могут быть пропущены, в данном случае им присвоено значение Unknown. При генерации тестового keystore, значения можно присваивать любые. При получении официального сертификата, данные регламентируются и проверяются Certificate Authority организацией.
Внутри каждого сертификата в формате X.509 хранится пара Distinqueshed Names (DN), один DN принадлежит владельцу сертификата, а второй DN указывает идентификатор CA, подписавшей сертификат. В случае с self-signed сертификатом, оба эти DN указывают на владельца сертификата.
Т.о. с помощью одной команды получается keystore с парой ключей и сертификатом, остается этот keystore взять и подложить в нужный каталог к своей программе. Но это уже другая история.
Обязательно стоит почитать официальную документацию на keytool, она содержит много полезного.
Некоторые команды для работы с сертификатами:
Введение во взаимную аутентификацию сервисов на Java c TLS/SSL
Вопросы авторизации и аутентификации и в целом аспектов защиты информации все чаще возникают в процессе разработки приложений, и каждый с разной степенью фанатизма подходит к решению данных вопросов. С учетом того, что последние несколько лет сферой моей деятельности является разработка ПО в финансовом секторе, в частности, систем расчета рисков, я не мог пройти мимо этого, особенно учитывая соответствующее образование. Поэтому в рамках данной статьи решил осветить эту тему и рассказать, с чем мне пришлось столкнуться в процессе настройки наших приложений.
Введение
Если говорить о формате настройки сертификатов для безопасной передачи данных. Как правило, данные действия производят на каком-либо веб-сервере типа nginx или apache, стоящем на входе во внутреннюю сеть компании и dmz. Благодаря ему можно разделить защищенную внутреннюю сеть и внешнюю сеть интернет. Далее, внутри доверенной сети каждый поступает по-разному. Кто-то считает, что все внутренние сервисы могут взаимодействовать друг с другом без каких-то ограничений, и контроль пользователей управляется уже в GUI посредством логина и пароля для конкретного приложения с разграничением ролей в рамках приложения. Кто-то идет дальше, подключая LDAP и используя логин, пароль пользователя из общего хранилища.
Существуют различные протоколы и технологии типа RADIUS, Kerberos или OAuth/OpenID для работы с вопросами аутентификации. Кто-то использует схемы с базовой аунтефикацией, передавая логин и пароль в base64, кто-то использует JsonWebToken, еще существует возможность использования сертификатов для проверки не только сервера и клиента. В результате получается ситуация, что мы формируем защищенное соединение клиента и сервера, в котором шифруем передаваемые данные и доверяем не только серверу, с которого эти данные забираем, но и знаем о том, кто именно забирает эти данные с нашего сервера, так как он предоставляет клиентский сертификат.
В рамках моей работы в ТехЦентре Дойче Банка мы в обязательном порядке для всех межсервисных взаимодействий используем SSL-сертификаты — даже в UAT окружении. В Java используем JKS, как более привычный контейнер сертификатов и паролей для этой системы.
Причины, почему мы так делаем — большое количество регулирующих органов по всему миру, перед которыми мы должны отчитываться. С одной стороны, это добавляет надежности, но с другой — создает некоторые сложности в разработке и тестировании систем.
Для того чтобы продолжить раскрывать тему, я бы хотел немного вернуться к общей информации о протоколе и инструментах по управлению сертификатами и паролями, а потом уже перейти непосредственно к коду с разбором того, как можно использовать сертификаты для решения подобных задач.
Терминология
Формат сертификатов
В рамках работы с сертификатами обычно используется контейнер PKCS 12 для хранения ключей и сертификатов, но в рамках Java, в дополнение широко используется проприетарный формат JKS (Java KeyStore). Для работы с хранилищем JDK поставляется с консольной утилитой keytool.
Помимо команды, позволяющей создать ключи вместе с keystore, которая выглядит следующим образом:
Есть ряд других команд под катом, которые могут быть полезны в работе с JKS и просто с ключами и сертификатами в Java
KeyStore & TrustStore
Говоря о JKS, стоит отметить, что данные файлы могут использоваться как KeyStore так и TrustStore. Это два различных типа хранилищ, которые находятся в JKS файлах. Одно из них (KeyStore) содержит более чувствительную информацию типа приватного ключа, и поэтому требует пароля для доступа к этой информации. В противовес чему TrustStore хранит информацию о доверенных сертификатах, которые конечно же присутствуют в операционной системе. Например, для Linux систем мы сможем их найти в /usr/local/share/ca-certificates/
Но так же эти сертификаты идут в поставке Java в файле cacerts, который по умолчанию расположен в директории java.home\lib\security и имеет пароль по умолчанию changeit.
Данная информация может быть полезна в тех случаях, когда установка JDK/JRE осуществляется в компании централизовано из одного источника, и имеется возможность добавления туда своих доверенных сертификатов компании для prod/uat окружения.
Ниже приведена таблица с некоторыми различиями KeyStore & TrustStore.
Keystore | TrustStore |
---|---|
Хранятся ваши приватные ключи и сертификаты (клиентские или серверные) | Хранятся доверенные сертификаты (корневые самоподписанные CA root) |
Необходим для настойки SSL на сервере | Необходим для успешного подключения к серверу на клиентской стороне |
Клиент будет хранить свой приватный ключ и сертификат в keystore | Сервер будет валидировать клиента при двусторонней аутентификации на основании сертификатов в trustStore |
javax.net.ssl.keyStore используется для работы с keystore | javax.net.ssl.trustStore используется для работы с trustStore |
Подключение SSL к NettyServer
Для того что бы сформировать серверный и клиентский SSL-контекст можно использовать один единственный билдер — SslContextBuilder и его методы — forServer и forClient. У этого билдера надо заполнить ряд обязательных полей, такие как trustManager и keyManager. Эти менеджеры мы можем получить из соответствующий фабрик — TrustManagerFactory и KeyManagerFactory.
Синтаксис данных фабрик практически аналогичен с разницей в том, что для trustManager-а мы используем только пароль для самого jks файла,
а для KeyStore при инициализации нам необходимо дополнительно передать пароль от самого ключа.
И в целом это все, что необходимо для добавления SSL в NettyServer.
Подключение SSL в gRPC / RSocket
Если говорить о двунаправленном обмене бинарными данными, современных тенденциях к написанию реактивных приложений, стоит отметить gRPC и RSocket для создания подобных приложений. Но поскольку в основании этих протоколов можно использовать Netty как транспорт, логика конфигурирования останется. Поэтому я не буду уделять этому много внимания.
Подключение SSL в Spring Boot для RestController
Но в мире Java разработки Spring стал де факто стандартом для DI. А вместе с внедрением зависимости люди используют и другие технологии, которые удобно собрать в одном Spring Boot приложении, не расходуя множество времени на конфигурирование всего зоопарка технологий. Конечно же, это приводит к избыточности зависимостей и к увеличению времени загрузки, но упрощает разработку. Куда проще написать аннотацию RestController, чем самому разбираться с тем, как корректно хендлить запросы через сервлеты. А для того, чтобы перенаправить всё взаимодействие через сервлеты в защищённый канал с использованием сертификатов, в Spring Boot есть два пути проcтой и более сложный для кастомных решений.
В первом случае достаточно воспользоваться набором пропертей
И все будет сделано за вас. Либо, если требуется более кастомная конфигурация, поднятие коннекторов на разных портах с нестандартными настройками и так далее, тогда путь лежит в сторону использования интерфейса WebServerFactoryCustomizer, имплементации которого существуют для всех основных контейнеров будь то Jetty, Tomcat или Undertow.
Поскольку это функциональный интерфейс, его довольно просто можно описать через lambda c параметром типа Connector. Для него мы можем выставить флаг setSecure(true), затем заполнить необходимые параметры для ProtocolHandler-а, выставив ему пути до jks c keystore и trustStore и соответствующие пароли к ним. Например, для tomcat код будет выглядеть подобным образом:
И после этого мы отдаем на откуп «магии» спринга перехват всех веб-запросов к нашему сервису, для того чтобы обеспечить безопасность соединения.
Тестирование TLS/SSL
Для того чтобы провести тестирование реализованного безопасного подключения имеется возможность создать keystore программно, используя классы из пакета java.security.* Это даст возможность тестировать различное поведение системы в случае разных ситуаций типа истекших сертификатов, проверки корректной валидации доверенных сертификатов и так далее.
Чтобы грамотно проверить работоспобность придется пройти по всем составным частям jks и воссоздать программно внутри KeyStore пару ключей KeyPair, свой сертификат X509Certificate, цепочку родительских сертификатов, подпись и доверенные корневые сертификаты.
Для упрощения этой задачи можно воспользоваться библиотекой bouncyСastle, которая предоставляет ряд дополнительный возможностей в дополнение к стандартным классам в Java, посвященным криптографии из Java Cryptography Architecture (JCA) и Java Cryptography Extension (JCE).
Некоторые аспекты работы с этой библиотекой присутствуют для kotlin и Java в зеркале их репозитория на github (https://github.com/bcgit/bc-java и https://github.com/bcgit/bc-kotlin).
На верхнем уровне абстракции создание keyStore для целей тестирования может выглядеть следующим образом:
Здесь мы, соответственно, можем увидеть наш доверительный корневой сертификат CA, сертификат cert, который выпущен промежуточным звеном, и нашу пару ключей (приватный и публичный), которые хранятся вместе с сертификатом в поле KeyPair keyPair класса X509Certificate2, расширяющем X509Certificate.
Благодаря билдерам подобного вида, мы легко сможем собрать различные тесткейсы для покрытия всех возможностей подключения к нашей системе.
Соответственно, остается нюанс в непосредственном написании двух билдеров — X509Certificate2Builder и KeyStoreBuilder. Конечно же в java существует java.security.KeyStore.Builder, но он весьма общего плана и имеет единственный ценный метод — newInstance, а хочется чего-то более явного для добавления доверенных сертификатов и приватных ключей. По этой причине был написан свой билдер.
Свой билдер использует в конечном итоге метод setEntry класса KeyStore для единообразного добавления сущностей доверенных сертификатов и приватных ключей, используя различные имплементации типа Entry (TrustedCertificateEntry или PrivateKeyEntry).
И поскольку KeyStore#setEntry имеет сигнатуру setEntry(String alias, Entry entry, ProtectionParameter protParam) с 3 параметрами, мы их можем объединить в один класс item и в итоге в методе KeyStoreBuilder#build() останется лишь следующий код:
А при добавлении сущностей в entries мы будем использовать сигнатуру аналогичную KeyStore#setEntry, но публичным интерфейсом, использующим этот setEntry будут более понятные методы addPrivateKey
и метод addTrustedCertificate,
которые мы использовали выше при генерации keyStore.
C билдером X509 сертификата дела обстоят чуть сложнее, поскольку основная часть логики там будет сосредоточена в методе build(). Чтобы не загромождать статью болейрплейт кодом сеттеров, которые просто устанавливают значения полей билдера, я сразу перейду к реализации метода build() для X509Certificate2, опустив методы, связанные с установкой значений в билдер, и использую вместо них локальные переменные:
Все недостающие в стандартной библиотеке классы импортированы из bouncycastle.
В начале работы необходимо проинициализировать провайдер bouncycastle, если это еще не было сделано ранее.
Пара ключей генерируется с использованием java.security.KeyPairGenerator, который позволяет создать ключи с заданный алгоритмом и хеш-функцией. В данном примере был использован RSA c SHA1PRNG.
Далее мы объявляем поля, необходимые для сертификата, такие как даты начала и окончания, эмитент и серийный номер.
Затем мы добавляем расширения для сертификата, описывающие субъект и указание корневого сертификата, подписавшего его. В конце концов, получаем сертификат.
Инициализируя различным способом исходные параметры типа сроков действия сертификата, списка доверенных сертификатов и различных алгоритмов, мы сможем проверить корректность работы нашей системы в различных ситуациях.
Ценностью таких операций является более прозрачное понимание работы системы в случаях, когда проблемы возникают до фактического получения запроса сервером на этапе установки рукопожатия, как следствие мы сможем более оперативно разбираться с возникающими ситуациями.
В результате, например, для проверки безопасного соединения в Spring boot приложении без использования стандартного пути с пропертями достаточно будет создать шаблонное приложение с вебом, например, через Spring Initializr и
Определения Truststore и Keystore
Какая разница между хранилищем ключей и доверительным магазином?
ОТВЕТЫ
Ответ 1
Хранилище ключей содержит закрытые ключи и сертификаты с соответствующими открытыми ключами.
В Truststore содержатся сертификаты других сторон, с которыми вы собираетесь общаться, или от авторитетов сертификатов, которым вы доверяете, чтобы идентифицировать другие стороны.
Ответ 2
Ключевое слово содержит секретные ключи. Вам это нужно только в том случае, если вы сервер, или если сервер требует аутентификации клиента.
Доверенность содержит сертификаты CA для доверия. Если ваши серверы сертификат подписывается признанным ЦС, доверительным магазином по умолчанию что корабль с JRE уже будет ему доверять (потому что он уже доверяет заслуживающим доверия ЦС), поэтому вам не нужно создавать свои собственные, или добавить что-либо к одному из JRE.
Ответ 3
KeyStore
keyStore в Java хранит закрытый ключ и сертификаты, соответствующие их открытым ключам, и требует, чтобы SSL-сервер или SSL требовали аутентификации клиента.
доверенного
TrustStore хранит сертификаты от сторонних поставщиков, ваше приложение Java-приложения или сертификаты, подписанные CA (такими властями сертификатов, как Verisign, Thawte, Geotrust или GoDaddy), которые могут использоваться для идентификации третьей стороны.
TrustManager
TrustManager определяет, нужно ли доверять удаленное соединение или нет, то есть, является ли сторонняя сторона, к кому она относится, и KeyManager решает, какие учетные данные аутентификации должны быть отправлены на удаленный хост для аутентификации во время установления связи SSL.
Если вы являетесь сервером SSL, вы будете использовать закрытый ключ во время алгоритма обмена ключами и отправлять сертификаты, соответствующие вашим открытым ключам клиенту, этот сертификат будет получен из keyStore. На стороне клиента SSL, если он написан на Java, он будет использовать сертификаты, хранящиеся в trustStore, для проверки подлинности сервера. Сертификаты SSL чаще всего используются в качестве файла .cer, который добавляется в keyStore или trustStore с помощью любой утилиты управления ключами, например. Keytool.
Ответ 4
Вы также можете быть заинтересованы в записи от Sun, как часть стандартной документации JSSE:
Как правило, хранилище доверия используется для хранения только открытых ключей для целей проверки, таких как проверка подлинности X.509. Для целей управления достаточно для администраторов или разработчиков просто объединить их в один магазин.
Ответ 5
В Java, какая разница между хранилищем ключей и доверительным магазином?
Здесь описание из документов Java в Справочном руководстве по расширению Java Secure Socket Extension (JSSE). Я не думаю, что это говорит вам что-то отличное от того, что говорили другие. Но это дает официальную ссылку.
Хранилище ключей/доверенное хранилище
В общем случае информация о хранилище ключей может быть сгруппирована в две категории: ключевые записи и доверенные записи сертификатов. Ключевая запись состоит из идентификатора объекта и его закрытого ключа и может использоваться для различных криптографических целей. Напротив, доверенный запись сертификата содержит только открытый ключ в дополнение к идентичность сущности. Таким образом, доверенная запись сертификата не может быть использована где требуется закрытый ключ, например, в javax.net.ssl.KeyManager. В JDK реализации JKS, хранилище ключей может содержать как ключевые записи, так и доверенные записи сертификатов.
Запись должна быть добавлена только в доверительный магазин, если пользователь доверяет этому объекту. Путем создания пары ключей или путем импорта сертификат, пользователь доверяет этой записи. Любая запись в truststore считается доверенной записью.
Ответ 6
Первое и основное различие между trustStore и keyStore заключается в том, что TrustStore используется TrustManager для определения того, нужно ли доверять удаленному соединению, keyStore используется из KeyManager, определяя, какие учетные данные аутентификации должны быть отправлены на удаленный хост для аутентификации во время SSL рукопожатие.
Другое отличие состоит в том, что keyStore теоретически содержит закрытые ключи, необходимые только при запуске сервера в SSL-соединении или вы включили аутентификацию клиента на стороне сервера, а с другой стороны trustStore хранит открытый ключ или сертификаты из CA (сертификат Власти), которые используются, чтобы доверять удаленной стороне или SSL-соединению.
Фактически вы можете хранить в одном файле как личные, так и открытые ключи, что инструмент для управления этими файлами одинаковый (keytool), поэтому вы можете использовать один файл для обеих целей, но вы вероятно, не стоит.