X 509 сертификат что это
Руководство. Общие сведения о сертификатах X.509 с открытым ключом
Сертификаты X.509 — это цифровые документы, которые представляют пользователя, компьютер, службу или устройство. Они могут выдаваться корневым или подчиненным центром сертификации (ЦС) либо центром регистрации и содержат открытый ключ субъекта сертификата. Они не содержат закрытый ключ субъекта, который должен храниться безопасно. Сертификаты с открытым ключом определяются в документе RFC 5280. Они имеют цифровую подпись и обычно содержат следующую информацию:
Поля сертификата
Со временем появились три версии сертификата. В каждой из версий добавлялись новые поля. Версия 3, которая действует в настоящий момент, содержит все поля версий 1 и 2, дополненные полями версии 3. Версия 1 определяет следующие поля:
В версии 2 добавлены следующие поля с информацией об издателе сертификата, хотя эти поля редко используются:
В сертификатах версии 3 добавлены следующие расширения:
Форматы сертификатов
Сертификаты можно сохранить в нескольких форматах. Для проверки подлинности в Центре Интернета вещей Azure обычно используются форматы PEM и PFX.
Двоичный сертификат
Содержит двоичный сертификат в необработанном формате в кодировке DER ASN.1.
Формат ASCII PEM
Ключ ASCII (PEM)
Содержит ключ DER в кодировке Base64 с добавлением необязательных метаданных со сведениями об алгоритме, используемом для защиты пароля.
Сертификат PKCS#7
Этот формат предназначен для передачи подписанных или зашифрованных данных. Он определяется стандартом RFC 2315. В нем может содержаться полная цепочка сертификатов.
Ключ PKCS#8
Этот формат предназначен для хранения закрытого ключа и определен в стандарте RFC 5208.
Ключ и сертификат PKCS#12
Дополнительные сведения
Дополнительные сведения см. в следующих разделах:
Дальнейшие действия
Если вы хотите создать тестовые сертификаты, которые можно использовать для проверки подлинности устройств в Центре Интернета вещей, изучите следующие разделы:
Если у вас есть сертификат корневого или подчиненного центра сертификации (ЦС), который вы хотите отправить в центр Интернета вещей и подтвердить права владения, см. руководство Подтверждение принадлежности сертификата ЦС.
Зачем нужны сертификаты¶
Итак, сертификат (certificate) — это файл, содержащий информацию о персоне или организации и подписанный цифровой подписью, нечто вроде паспорта персоны или организации. Главное содержимое сертификата — это публичный ключ шифрования. У любого сертификата существует его автор-создатель и у этого автора есть секретный ключ шифрования. По сути сертификат — это всего лишь обёртка над публичным ключом, где помимо собственно ключа содержится разнообразная дополнительная информация: имя персоны или организации, страна, телефон, емейл и так далее.
Секретный и публичный ключи используются для асиметричной схемы шифрования: данные шифруются секретным ключом, а расшифровываются публичным. Или наоборот: шифруются публичным, а расшифровываются секретным. За подробностями традиционно отправляю в википедию, в статью Криптосистема с открытым ключом.
Помним главное: в паре с сертификатом всегда идёт секретный ключ. Когда мы в браузере открываем сайт через HTTPS, сервер отправляет нам сертификат, который мы должны использовать для установки дальнейшего безопасного соединения. В этом сертификате лежит публичный ключ, а также адрес сайта. Браузер проверяет, что адрес сайта соответствует запрошенному и разрешает установку соединения. Секретный ключ при этом находится на сервере сайта и пределы этого сервера никогда не покидает.
Но тут возникает вопрос: а где гарантия, что этот сертификат (и соответственно публичный ключ) настоящий, что он действительно создан автором сайта, а не вклинившимся в сеть злоумышленником? Как проверить подлинность этого «удостоверения сайта»?
Есть два решения этой проблемы. Самое очевидное: на стороне браузера имеется хранилище сертификатов и для каждого сайта в нём уже существует сертификат, дальше мы просто сравниваем полученный сертификат и если он совпадает с имеющимся, устанавливаем соединение. Такая схема используется, например, в работе программы SSH, у неё имеется локальная база сертификатов, при установке соединения она проверяется, что полученный сертификат с этого адреса соответствует уже сохранённому в базе. Очевидный недостаток этой схемы: необходимо каким-то образом заполучить сертификаты заранее.
Если для SSH схема с заранее сохранённым сертификатом более-менее работает, то для HTTPS в браузере она уже не годится, абсолютно невозможно получить сертификаты для всех сайтов в интернете. Поэтому в HTTPS используется другая схема, называемая инфраструктурой публичных ключей или по-английски Public Key Infrastructure, сокращённо PKI.
Суть PKI очень простая: в браузере хранятся не сертификаты браузеров, а сертификаты так называемых удостоверяющих центров (по-английски Certificate Authority, сокращённо CA). Предназначение CA — это подписывание всех остальных сертификатов, это означает, что когда ваш браузер получает сертификат сайта при установке соединения, он видит помимо адреса сайта ещё и «адрес» удостоверяющего центра, а также цифровую подпись, которую сгенерировал удостоверяющий центр с использованием своего секретного ключа. Дальше браузер берёт из локального хранилища сертификат удостоверяющего центра, достаёт из него публичный ключ и с помощью него проверяет подпись в сертификате сайта. Если подпись правильная, соединение успешно устанавливается.
Естественно, удостоверяющие центры не подписывают сертификаты кому попало. Владелец сайта должен каким-то образом подтвердить свою личность и принадлежность к сайту, только после этого сертификат будет подписан. Естественно, всё это делается не бесплатно и удостоверяющие центры делают весьма много денег из воздуха.
Локальное хранилище сертификатов удостоверяющих центров меняется достаточно редко и контролируется создателями либо операционной системы, либо браузера.
Технические подробности¶
А теперь самое главное, ради чего эта статья и писалась — технические подробности, стандарты и особенности реализации системы сертификатов.
В основе всего лежит множество индустриальных стандартов, созданных очень давно — в конце восьмидесятых и начале девяностых годов XX века. Благодаря этим стандартам, мы сейчас имеет вполне успешно функционирующую систему, несмотря на то, что отдельные её компоненты созданы совершенно разными компаниями.
Секретный ключ¶
Главный компонент всего — криптография, точнее криптографические алгоритмы.
Всё начинается с генерации пары ключей: секретного и публичного. Сначала при помощи математической и компьютерной магии генерируется секретный ключ, а затем из него вычисляется публичный. Чаще всего для сертификатов используется алгоритм RSA, вот как это делается в консоли через программу openssl:
С подобным форматом представления криптографических данных вам предстоит сталкиваться постоянно, называется он PEM, что расшифровывается как Privacy-enhanced Electronic Mail. Его предназначение — кодировать бинарные криптографические данные в виде ASCII-текста. И фактически между маркерами из минусов находятся закодированные в base64 бинарные данные, в данном случае — секретный ключ.
Мы можем при помощи openssl сконвертировать секретный ключ из текстового формата PEM в изначальный бинарный, сохраним его в файл private.der:
Имя формата данных DER расшифровывается как Distinguished Encoding Rules и является частью стандарта ASN.1. В стандарте ASN.1 описываются правила и структуры для кодирования, раскодирования и передачи данных по телекоммуникационным и компьютерным сетям. По сути можно считать ASN.1 форматом для сериализации структурированных бинарных данных. Существует специальный компилятор, который из формальных спецификаций ASN.1 генерирует C-код для работы с бинарными данными такой структуры.
Вот так, например, выглядит дамп нашего созданного секретного ключа:
В нашем файле секретного ключа «упакованы» девять целых чисел, структура ключа для алгоритма RSA весьма простая и описана, например, в RFC 3447, в секции A.1.2 RSA private key syntax.
Ну и чтобы два раза не вставать, вытащим из секретного ключа публичный ключ в файл public.der, закодированный в бинарный формат DER, openssl умеет делать и это тоже:
И сразу же посмотрим на его структуру через dumpasn1:
Структура публичного ключа также описана в RFC3447, в секции A.1.1, если вы туда посмотрите, то увидите, что дамп файла public.der не соответствует этому описанию. Поздравляю с первыми граблями в openssl, с ними вам тоже придётся сталкиваться постоянно. В данном случае зачем-то добавляется заголовок, указывающий, что дальше будет RSA, и на этом заголовке многим библиотекам срывает крышу.
Для манипуляциями публичными и секретными ключами можно также использовать команду pkey, она позволяет работать с произвольными поддерживаемыми типами ключей. Вот как выглядит её вызов для вытаскивания публичного ключа из приватного:
Сертификат¶
Но хватит о ключах, поговорим теперь о сертификатах. Напомню, что сертификат — это обёртка над публичным ключом. Неформально файл сертификата состоит из двух частей: данных сертификата (DATA) и цифровой подписи (SIGNATURE).
В секции DATA содержится смысловая часть сертификата, главное поле там — Subject (он же Субъект), это владелец сертификата, именно его публичный ключ находится в поле Subject Public Key Info. Также в сертификат входят другие поля, о которых мы поговорим позже, когда будем рассматривать уточнённую схему.
В секции SIGNATURE содержится цифровая подпись всех данных из секции DATA. Напомню, что в модели PKI цифровую подпись генерирует центр авторизации, используя свой секретный ключ, удостоверяя подлинность данных сертификата.
Естественно, вся работа с сертификатами регламентируется международными стандартами, конкретно для наших сертификатов используется стандарт X.509, вот его официальный сайт: http://www.itu.int/rec/T-REC-X.509. X.509 описывает множество аспектов PKI, не только форматы данных, но ещё и алгоритмы.
Для описания структур данных используется уже знакомая нам нотация ASN.1, она достаточно простая и выразительная.
Вот так определяется сертификат (раздел 4.1. Basic Certificate Fields):
Это всё значит, что сертификат состоит из трёх компонентов: tbsCertificate, signatureAlgorithm и signatureValue
tbsCertificate собственно тело сертификата, его данные, буквы tbs в названии поля расшифровываются как «to be signed», то есть это блок данных, который будет подписан, описывается ASN.1 стуктурой TBSCertificate ; signatureAlgorithm в этом поле задаётся алгоритм подписи, определяется ASN.1 структурой AlgorithmIdentifier ; signatureValue а в этом поле находится бинарный неструктурированный блок с собственно подписью.
Перед тем как погружаться в структуру тела сертификата, рассмотрим поле signatureAlgorithm, в его описании фигурирует очень важный для дальнейшего понимания элемент, но сначала формальное ASN.1-описание (раздел 4.1.1.2. signatureAlgorithm):
Как и другие порождения ASN.1/X.509, OID имеет чётко заданную структуру, по которой можно однозначно идентифицировать тип и свойства объекта. Существуют разные способы представления OID. Рассмотрим их на простом примере. Для генерации цифровой подписи может использоваться алгоритм, который неформально можно описать так: посчитаем SHA256 тела сертификата и дальше зашифруем это значение приватным ключом центра авторизации. Для этого алгоритма существует OID, у этого OID есть несколько равнозначных способов представления:
Все эти способы отражают иерархичную сущность OID, по компонентам можно определить, например, кто внёс этот OID в реестр, какая страна, какая организация и так далее. Существует специальный сайт — http://www.oid-info.com, — на котором ведётся большой реестр всевозможных OID. В принципе, таких сайтов несколько, но этот самый популярный. Вот, например, страница OID для алгоритма sha256WithRSAEncryption: http://www.oid-info.com/get/1.2.840.113549.1.1.11.
Я не буду полностью описывать семантику этих полей, это всё приводится с подробностями в разделе 4.1. Basic Certificate Fields RFC 5280. Так, коротко пробежимся по основным полям.
В поле signature должно быть то же самое значение, что и в поле signatureAlgorithm, то есть алгоритм, которым CA подписывает сертификат.
В поле issuer находится имя центра авторизации, в поле subject — имя владельца сертификата. Оба этих имени также являются структурированными (ASN.1-структура Name) и должны быть непустыми, их тип определяется стандартом X.501 и носит название distinguished name, сокращённо DN. Это тот же самый DN, что и в LDAP.
Поля в структуре Name также задаются через OID. Вот небольшой пример, как поле issue «разворачивается» из текстового представления в строго формализованное. Возьмём DN-фрагмент реального сертификата (https://google.ru):
Небольшой хинт, как скачать сертификат с сайта и сразу конвертнуть его в DER в файл certificate.der:
А вот, в какую ASN.1-структуру «разворачивается» этот текст:
По факту это последовательность пар ключ-значение, где в роли ключа выступает OID. То есть кажущаяся обычным текстом строка оказывается одной из форм представления строго структурированного объекта. Каждая такая пара ключ-значение называется RelativeDistinguishedName, в роли ключа выступает OID.
Для дальнейшего изучения темы нам понадобится настоящий живой сертификат. Я взял сертификат c twitter.com, вы его можете скачать сами (если знаете, как это сделать вашим браузером) или взять сохранённую мной версию в виде DER-файла (скачать сохранённую версию).
Итак, сначала посмотрим, как сертификат выглядит в «человечном» формате, вот его полная распечатка (немного отформатированная, чтобы длинная строка не распирала экран):
Разберём последовательно поля сертификата.
Дальше я рекомендую выполнить команду dumpasn1 certificate-twitter.com.der и сравнить только что прочитанное с показанным в дампе, параллельно полезно держать открытыми RFC 5280 и RF 3280.
Цепочки удостоверяющих сертификатов¶
Удостоверяющий центр может выдать сертификат, в котором в поле X509v3 Basic Constraints разрешается его использование как удостоверяющего. Этим сертификатом тоже можно подписывать «доменные» сертификаты. Таким образом, все CA-сертификаты образуют цепочку, а в целом — дерево. В вершине этого дерева находится Самый Главный Сертификат, он называется корневым сертификатом (по-английски root certificate).
Система доверия PKI строится таким образом, что доверенным CA-сертификатом является тот, который подписан другим доверенным корневым CA-сертификатом. Вебсайт может вместе со своим сертификатом отдать браузеру также и CA-сертификат, которым он был подписан. И если этот CA-сертификат подписан кем-то из доверенных удостоверяющих центров, он автоматически становится доверенным.
Естественно, центры авторизации не выписывают CA-сертификаты кому попало, но крупная организация может этого добиться, например, у Google есть свой CA-сертификат.
Также в PKI существует механизм отзыва сертификатов, например, если кто-то из CA стал себя вести некорректно или у него украли секретный ключ, то вышестоящий удостоверяющий центр может отозвать сертификат провинившегося. Эта схема, к сожалению, на практике работает не так гладко, как это задумывалось.
Корневой сертификат является самоподписанным, то есть он подписан тем же самым ключом, публичный ключ для которого находится в теле сертификата. У корневого сертификата совпадают поля issuer и subject.
Сфера применения сертификатов не ограничивается браузером, конечно. В теории любой клиент может сам выбирать, кому он доверяет, а кому нет. В программу может быть жёстко вшит сертификат, которым она проверяет другие сертификаты, например.
Как вручную проверить цепочку сертификатов¶
Иногда возникает необходимость проверить, подписан ли один сертификат другим. Это можно сделать через openssl.
Возьмём три сертификата из Go Daddy, вот они: GD_root.pem (это корневой сертификат Go Daddy), GD_good.pem, GD_bad.pem. Нам нужно проверить, подписаны ли сертификаты GD_good.pem и GD_bad.pem корневым сертификатом Go Daddy.
И альтернативный вариант (предыдущий в новых версиях не работает):
И ещё о сертификатах¶
Небольшая демонстрация, как openssl работает с сертификатами, алгоритмов для которых он не знает. Возьмём вот этот сертификат, это корневой сертификат Казахстанского центра межбанковских расчётов национального банка Республики Казахстан.
Вот как выглядит попытка распечатать его как текст:
Обратите внимание на поле Signature Algorithm: 1.3.6.1.4.1.6801.1.2.2, openssl не смог распознать этот алгоритм, так как в его коде нет такого OID. Если мы попытаемся найти этот OID в репозитории http://www.oid-info.com/get/1.3.6.1.4.1.6801.1.2.2, то обнаружим, что им он неизвестен. Но зато им известен «родительский» OID (помним, что схема OID иерархичная), по адресу http://www.oid-info.com/get/1.3.6.1.4.1.6801 находим координаты владельца этой схемы — казахстанская фирма Gamma Technologies, OID предыдущего уровня (1.3.6.1.4.1.6801.1.2) выдаёт нам GOST28147, https://ru.wikipedia.org/wiki/ГОСТ_28147-89.
Как мы видим, фирма использует X.509 для хранения своих собственных сертификатов. Браузер его не сможет переварить, а вот специализированный софт — вполне. Например, dumpasn1 отлично показывает структуру ASN.1-объектов.
Следующий файл для препарирования — сертификат удостоверяющего центра Бурятии, скачайте файл ca-bur.der. Предлагаю вам самим его скачать и запустить команду:
А затем такую, для контраста:
Комментарии
клиент получил сертификат от сайта. Для проверки подлинности, он использует подпись из этого сертификата, используя публичный ключ удостоверяющего сертификата(центра). Как с помощью такого ключа можно проверить подпись?
Вот простой пример, сертификаты для него тут:
Но если вы хотите проверить валидность сертификата, используя только публичный ключ сертификата удостоверяющего центра, то простого способа я не знаю. Сложный — это извлечь публичный ключ из CA-сертификата, извлечь байты подписи из проверяемого сертификата, извлечь TBSCertificate и проверить соответствие подписи.
-CApath /dev/null указываю для гарантии, что не будет использоваться системное хранилище сертификатов.
Никаких промежуточных сертификатов в файле ca быть не должно. Только корневые, полученные от CA. Подпись каждого сертификата в цепочке (за исключением корневого) проверяется следующим по цепочке сертификатом (его открытым ключом). Подпись корневого считается верной по факту доверия к нему.
Это всё инфраструктурные вопросы, они вне области собственно сертификатов лежат.
Сама суть инфраструктуры публичных ключей (PKI) предполагает, что корневой сертификат попадает на машину клиента другим путём, не через сетевой коннект, поэтому нормального способа «запомнить» или «автоматически скачать» нет.
По пункту 2. ничего не могу сказать. Возможно, какое-то расширение для этого есть, но для этого нужно изучать конкретную систему распространения сертификатов.
«Понятное имя» в сертификате прописать нельзя.
Теоретически самоподписанный сертификат установить можно, но почти все программы его будут игнорировать.
Это не опечатка, просто эта опция есть не во всех версиях openssl. Спасибо за напоминание, обновлю текст.
Основы HTTPS, TLS, SSL. Создание собственных X.509 сертификатов. Пример настройки TLSv1.2 в Spring Boot
Привет, Хабр! В современном мире абсолютное большинство сайтов используют HTTPS (Google даже снижает рейтинг сайтов работающих по HTTP в поисковой выдаче), а подключение к различным системам происходит по протоколу TLS/SSL. Поэтому любой разработчик рано или поздно сталкивается с этими технологиями на практике. Данная статья призвана помочь разобраться, если вы совершенно не в курсе что это такое и как оно устроено. Мы разберем как работает соединение по протоколу TLS, как выпустить собственные сертификаты и настроем TLS в Spring Boot приложении. Поехали!
Что не так с HTTP?
Симметричное шифрование предполагает наличие общего ключа одновременно у отправителя и получателя, с помощью которого происходит шифровка и дешифровка данных. Данный тип не требователен к ресурсам, однако существенно страдает безопасность из-за опасности кражи ключа злоумышленником.
При использовании ассиметричного шифрования существует открытый ключ, который можно свободно распространять, и закрытый ключ, который держится в секрете у одной из сторон. Этот тип работает медленно, относительно симметричного шифрования, однако скомпрометировать закрытый ключ сложнее.
Что происходит на практике
Что такое Message Authentication Code или MAC? Это хэш, сгенерированный с использованием выбранной криптографической хэш-функции и разделяемого ключа, который добавляется сзади к сообщению. Перед отправкой данных отправитель вычисляет MAC для них, а получатель перед обработкой вычисляет MAC для принятого сообщения и сравнивает его с MAC этого принятого сообщения. Предназначен для проверки целостности, то есть что сообщение не было изменено при его передаче.
Для чего нужен идентификатор сессии? Как мы посмотрим далее, процесс установления TLS соединения затратен по времени и ресурсам. Предусмотрен механизм возобновления соединения с помощью отправки клиентом этого идентификатора. Если сервер тоже все еще хранит соответствующие настройки, то клиент и сервер смогут продолжить общение использую ранее выбранные алгоритмы и ключи.
Кем подписан сертификат корневого CA? А никем, нет инстанции выше корневого CA. Сертификат (открытый ключ) в этом случае подписан собственным закрытым ключом. Такие сертификаты называют самоподписанные (sefl-signed).
Сервер случайно генерирует число 6, передает клиенту числа p = 17, g = 3, Ys = 3 6 mod 17 = 15
Клиент случайно генерирует число 7 и возвращает серверу Yc = 3 7 mod 17 = 11
Сервер считает итоговое число 11 6 mod 17= 8, и клиент 15 7 mod 17 = 8
После этого соединение считается установленным, и происходит передача полезной информации
Двусторонний TLS
Двусторонний TLS или Two Way TLS или mutual TLS (mTLS) означает проверку сертификата клиента. Сервер после своего сообщения Certificate посылает запрос сертификата клиента CertificateRequest. Клиент в ответ отправляет Certificate, сервер производит проверку, аналогичную проверке сертификата сервера клиентом. Далее настройка TLS происходит в описанном выше порядке.
TLSv1.3
Стоит отметить, что все выше написанное относится к TLSv1.2, которая начинает понемногу устаревать. В 2018 году была разработана новая версия 1.3 в которой: были запрещены уже ненадежные алгоритмы, ускорен процесс соединения, переработан протокол рукопожатия и др. Интернет медленно но верно обновляется до TLSv1.3, однако все еще большинство сайтов работают по протоколу TLSv1.2. Поэтому информация в этой статье остается актуальной.
Выпускаем собственные сертификаты
Теперь, когда мы разобрали теорию, самое время приступить к практике! Нам понадобятся OpenSSL и keytool (входит в поставку JDK). Для начала создадим сертификат корневого CA, которым будем подписывать запросы на подпись сертификата клиента и сервера. Сгенерируем приватный ключ RSA зашифрованный AES 256 с паролем «password» длиной 4096 бит (меньше 1024 считается ненадежным) в файл CA-private-key.key:
Нет какого-то принятого стандарта расширений для файлов, связанных с сертификатами. Мы будем использовать:
Так как подписать сертификат другим сертификатом пока нельзя, подпишем запрос его же приватным ключом. Получившейся сертификат CA-self-signed-certificate.pem будет самоподписанным со сроком действия 1 день.
Теперь у нас есть сертификат, которому в будущем будут доверять наши клиент и сервер. Похожим образом сделаем приватные ключи и запросы на подпись сертификата для них:
После этого необходимо создать хранилище ключей с сертификатами (keystore) Server-keystore.p12 для использования в нашем приложении. Положим туда сертификат сервера, приватный ключ сервера и защитим хранилище паролем «password»:
Осталось только создать хранилище доверенных сертификатов (truststore): сервер будет доверять всем клиентам, в цепочке подписания которых есть сертификат из truststore. К сожалению, для Java сертификаты в truststore должны содержать специальный object identifier, а OpenSSL пока не поддерживает их добавление. Поэтому здесь мы прибегнем к поставляемому вместе с JDK keytool:
Для удобства, все описанные выше действия упакованы в bash script.
Настройка TLS в Spring Boot приложении
Основой для нашего проекта послужит шаблон с https://start.spring.io/ с одной лишь зависимостью Spring Web. Для включения TLS указываем в application.properties:
После этого указываем Spring тип keystore, путь к нему и пароль:
Для проверки доступа создадим минимальный контроллер:
Запускаем проект. Попробуем сделать запрос с помощью curl:
На этот раз все сработало, TLS в Spring Boot работает! Мы на этом не остановимся, добавим в приложение аутентификацию клиента (указываем truststore):
Запускаем и снова пытаемся выполнить запрос:
Очевидно, что сервер закрыл соединение, так как curl не предоставил никакого сертификата. Дополним запрос клиентским сертификатом и его закрытым ключом:
Итоги
В данной статье мы разобрались как работает протокол TLS и для чего он нужен. На практике научились создавать собственные сертификаты и использовать их в Java приложении на Spring Boot. Надеюсь, представленная информация оказалась Вам полезной. Спасибо за внимание!