Pull to refresh

Comments 31

Достаточно интересно. Спасибо.
Моя статья есть и на Хабре: ASN.1 простыми словами.

Однако должен сказать, что Ваша статья IMHO достаточно странна. Либо она про X.509 сертификаты и тогда она очень поверхностна, либо она про некий пример ASN.1 структур на примере разбора X.509 сертификата. Но тогда для меня она тоже поверхностна.
Знаю, читал. Очень помогла кстати. Спасибо.
Теперь про ваш вопрос, или это не вопрос?) Я бы не стал называть это громким словом «статья», обычный пост в блоге. Было интересно поковырять собственноручно сгенерированный сертификат, нашел пару прикольных вещей, описал процесс в коллективном блоге.
Кому-то это покажется поверхностным, а кому-то (таким людям типа меня, которым было просто любопытно узнать что же это за зверь такой x.509) поможет удовлетворить любопытство.
Конечно, есть еще очень много всего, что в топик просто не уместилось. Если кому-то станут интересны подробности постараюсь ответить в комментариях. А не получится у меня, помогут умные люди типа вас, за это мы хабр и любим.)
Вот эту фразу не понял:
В TSB-сертификат входит последовательность SEQUENCE второго уровня со всеми вложенными данными.
Не могли бы вы это пояснить (и выделить в примере подписываемую часть болдом).
Смотрите, вот наш сертификат целиком:
Сертификат
SEQUENCE(3 elem)
    <TBS>SEQUENCE(7 elem)
        [0](1 elem)
            INTEGER 2
        INTEGER 1
        SEQUENCE(2 elem)
            OBJECT IDENTIFIER 1.2.840.113549.1.1.5
            NULL
        SEQUENCE(1 elem)
            SET(1 elem)
                SEQUENCE(2 elem)
                    OBJECT IDENTIFIER 2.5.4.3
                    UTF8String CA
        SEQUENCE(2 elem)
            UTCTime 13-09-15 15:35:02 UTC
            GeneralizedTime 2113-09-22 15:35:02 UTC
        SEQUENCE(1 elem)
            SET(1 elem)
                SEQUENCE(2 elem)
                    OBJECT IDENTIFIER 2.5.4.3
                    UTF8String CA
        SEQUENCE(2 elem)
            SEQUENCE(2 elem)
                OBJECT IDENTIFIER 1.2.840.113549.1.1.1
                NULL
            BIT STRING(1 elem)
                SEQUENCE(2 elem)
                    INTEGER 00: 8D 80 B5 8E 80 8E 94 D1 04 03 6A 45 1A 54 5E 7E
                                EE 6D 0C CB 0B 82 03 F1 7D C9 6F ED 52 02 B2 08
                                C3 48 D1 24 70 C3 50 C2 1C 40 BC B5 9D F8 E8 A8
                                41 16 7B 0B 34 1F 27 8D 32 2D 38 BA 18 A5 31 A9
                                E3 15 20 3D E4 0A DC D8 CD 42 B0 E3 66 53 85 21
                                7C 90 13 E9 F9 C9 26 5A F3 FF 8C A8 92 25 CD 23
                                08 69 F4 A2 F8 7B BF CD 45 E8 19 33 F1 AA E0 2B
                                92 31 22 34 60 27 2E D7 56 04 8B 1B 59 64 77 5F
                    INTEGER 65537</TBS>
        SEQUENCE(2 elem)
            OBJECT IDENTIFIER 1.2.840.113549.1.1.5
            NULL
    BIT STRING 00: 0A 1C ED 77 F4 79 D5 EC 73 51 32 25 09 61 F7 00
                   C4 64 74 29 86 5B 67 F2 3D A9 39 34 6B 3C A9 92
                   B8 BF 07 13 0B A0 9B DF 41 E2 8A F6 D3 17 53 E1
                   BA 7F C0 D0 BC 10 B7 9B 63 4F 06 D0 7B AC C6 FB
                   CE 95 F7 8A 72 AA 10 EA B0 D1 6D 74 69 5E 20 68
                   5D 1A 66 28 C5 59 33 43 DB EE DA 00 80 99 5E DD
                   17 AC 43 36 1E D0 5B 06 0F 8C 6C 82 D3 BB 3E 2B
                   A5 F1 94 FB 53 7B B0 54 22 6F F6 4C 18 1B 72 1C


Отступы в тексте описывают уровень вложения, т.е. SEQUENCE(3 elem) первый уровень вложения, все элементы сертификата входят в этот блок.
SEQUENCE(7 elem) — второй уровень вложения, и т.д.
Собственно элементы этого самого SEQUENCE(7 elem) и будут входить в TSB-сертификат. В блоке <source> тэги не работают, выделил часть TBS-сертификата «тэгом» <TBS>.
Для лучшего понимания (всеми участниками) следует сказать, что аббревиатура «TBS» расшифровывается как «To Be Signed». То есть фактически сертификат состоит только из трех полей: части «to be signed», идентификатора алгоритма подписи и собственно самой подписи. Следует трактовать «TBS certificate» как некий набор элементов, который удостоверяются подписью этого сертификата. TBS могло бы быть просто куском данных, но для сертификата правильнее иметь в TBS части имена выдающей и принимающих сторон, а также дополнительные атрибуты сертификата.
Это объясняется тем, что отпечаток представляет собой обычное хеш-значение SHA-1

Алгоритм хеширования можно задавать при генерации, так что я бы не стал писать так однозначно про SHA1.

Как видите, единственное отличие от самоподписанного сертификата заключается в наличие дополнительного блока

Тоже не совсем согласен. Для сертификата нет никакой разницы, чем его подписывать — своим закрытым ключом или ключом издающего ЦС. То отличие, о котором вы написали, появилось из-за различных политик центра сертификации; во втором случае подписывающий ЦС просто добавил дополнительный блок в конечный сертификат. Но блок AKI никоим образом однозначно не указывает, что сертификат не самоподписанный. Я могу сгененить самоподписанный сертификат с AKI, при этом значение AKI будет совпадать со значением в поле SKI (Subject Key Identifier).

Существуют конечные сертификаты без AKI, тогда цепочка строится на основе поля Issuer, но в настоящее время такие сертификаты уже считаются плохим тоном. AKI дает точную ссылку на издающий сертификат.
Здравствуйте.
По первому пункту по-моему вы не совсем правы, если я вас правильно понял. То что отпечаток может вычисляться не только с помощью SHA-1 это вы верно подметили. А вот, то что алгоритм отпечатся можно задать при генерации этого я нигде не нашел. Насколько понял проверяющая программа сама выбирает хеш-функцию, а так как стандарт по умолчанию долгие годы был SHA-1, во многих реализациях используется именно эта функция.

А вот по второму пункту тут я с вами целиком согласен. Действительно, если сгенерировать сертификат 2-го уровня и не указать в нем дополнительные сведения об издателе сертификат все-равно найдет правильного издателя по наименованию. Я внес небольшие поправки в пост, чтобы не вводить читателей в заблуждение.
Я просто хотел немного вас дополнить и сказать, что такого рода поля, содержащие, например, сведения об издателеи называются расширениями. И возможность добавлять расширения доступна только для сертификатов версии 3.
Отвечу сразу на предыдущие два комментария.

Насчет отпечатка в SHA-1: он действительно должен быть только в SHA-1. Сделано это только для того, чтобы все без исключения программы смогли однозначно идентифицировать данный сертификат. То есть например в Windows сертификаты находятся в так называемых «хранилищах сертификатов» и чтобы быстро найти нужный частно прибегают к поиску по хэшу сертификату, который и вычисляется только с помощью SHA-1. И так как этот отпечаток нужен исключительно только для различения сертификатов у локального пользователя то совершенно все равно скомпрометирован ли алгоритм SHA-1 или нет — это просто «отпечаток», простой уникальный номер сертификата.

Насчет различия самоподписанных и не самоподписанных сертификатов. По сути этих различий нет никаких. То есть также есть только три части сертификата (TBS, алгоритм подписи и сама подпись), отличается только на каком закрытом ключе выполнена подпись сертификата. В случае самоподписанного сертификата подпись выполнена на закрытом ключе соответствующему открытому ключу (который находится в TBS-части). В случае же не самоподписанного сертификата подпись выполнена на закрытом ключе «удостоверяющего центра», который как-бы удостоверивает, что этот публичный ключ (упомянутый в TBS-части) действительно соответствует данному лицу. Конечно различия самоподписанного и не самоподписанного сертификата на это не кончаются (например в самоподписанном сертификате поля «Issuer» и «Subject» в TBS-части совпадают, на в не самоподписанном — всегда различны), но более рассмотрение более детальных различий приведет к очень раздутому комментарию.

Также следует упомянуть, что автор рассматривает не первичный стандарт ITU-T X.509, а «производный» стандарт RFC5280. Кстати было бы здорово дополнить статью ссылкой на действительный стандарт X.509 (тем более что он уже полностью переведен на русский язык, как минимум для версии стандарта от 2005-го года): ITU-T X.509 (+ русский перевод).
Не видел этот документ. Спасибо за ссылку. Добавил в пост.
Это первичный стандарт и он изначален. Однако все программные реализации опираются на RFC3280 (или RFC5280), так что этот первичный стардарт только вспомогателен. А ссылка полезна прежде всего тем, что есть русский перевод всего стандарта.
Поэтому, в целях экономии места, а также более удобной обработки хранимой в ASN.1-форме информации, был разработан специальный метод кодирования — DER.

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

Вот это вот в корне ошибочно.
На самом деле сам по себе стандарт ASN.1 содержит в себе как язык описания схем, так и правила кодирования. Правила кодирования действительно достаточно просты: все значения записываются в виде структур «TLV» (tag-length-value). Базовые требования к кодированию ASN.1 типов определяются в BER (Basic Encoding Rules). Именно эти правила являются основными для ASN.1. То что называется DER (Distinguished encoding rules) определяет не новые правила, а всего лишь накладывает ограничения на BER. Изначально DER был сделан из-за того, что с помощью BER один и тот же элемент данных мог быть закодирован различными способами. С помощью DER добавили ограничения и теперь каждый тип данных может быть закодироват одним способом В ограничения описываемые в DER входят:
1) Следует использовать явную форму кодирования длины структур данных;
2) Нельзя использовать конструктивную форму кодирования для типов BITSTRING, OCTETSTRING и для други строковых типов;
+ дополнительный набор правил-ограничений.

Так что DER — это не кодировка, а просто набор ограничений, наложенный на базовые правила кодирования (BER). Конечно я повсеместно вижу, как употребляют выражения вида «в DER-кодировке», и уже почти бросил обращать на это внимание, но все-таки заострю этот момент в данной статье.
Я так понял есть еще некий вариант CER. Не могли бы вы пояснить что это такое и чем он отличается от der?
CER (Canonical encoding rules) — несколько меньшие ограничения, чем в DER. Лучше бы сразу ознакомится со стандартом X.690 (основной современный стандарт ASN.1), там всё очень подробно расписано.
Понятно.
Спасибо большое за уточнения и разъяснения.
Спасибо, для общей информации мне хватает сведений из этой статьи. Как раз недавно впервые вплотную столкнулся с сертификатами. Но проблемой было не понимание содержимого сертификатов, а вообще сама их генерация и назначение. Все эти PEM, DER, base_64 и прочие. Неплохо бы обзорную статью о всяких видах и целях тех или иных ключей.
В частности, когда мне понадобилось вытащить приватный ключ из JavaKeyStore, пришлось неплохо покурить гугл, но в итоге таки вытащил его.
Неплохо бы обзорную статью о всяких видах и целях тех или иных ключей.

Не уловил о чем вы. Вы имеете в виду назначение сертификата? Например: шифрование файлов или электронная почта. Или вы о чем то другом?
Я о том, что один и тот же сертификат можно получить в DER-формате, в DER-Base64 формате, в PEM формате и ещё в бог весть скольки форматах. При чем визуально, DER-base64 и PEM очень похожи. Учитывая, что расширение у файла может быть каким угодно — вообще не очень ясно, как определить формат сертификата. И вопрос в том — какое назначение всех этих вариантов? А ещё есть выгрузка из keystore в формате PEM, но с такой вот странной конструкцией:
Bag Attributes
friendlyName: sso
localKeyID: 54 69 6D 65 20 31 33 37 39 32 35 39 30 35 37 39 38 30
Key Attributes: -----BEGIN RSA PRIVATE KEY-----

-----END RSA PRIVATE KEY-----
Bag Attributes
friendlyName: CN=Pravo Ru,OU=Pravo.ru,O=Pravo.ru,L=Moscow,ST=Moscow,C=RU
localKeyID: 54 69 6D 65 20 31 33 37 39 32 35 39 30 35 37 39 38 30
subject=/C=RU/ST=Moscow/L=Moscow/O=Pravo.ru/OU=Pravo.ru/CN=Pravo Ru
issuer=/C=RU/ST=Moscow/L=Moscow/O=Pravo.ru/OU=Pravo.ru/CN=Pravo Ru
-----BEGIN CERTIFICATE-----

-----END CERTIFICATE-----

Из этого странного файла я руками вырезал private key, чтобы сохранить его в PEM, конвертировать в DER и отдать своей системе для подписывания запросов.
Ну что касается PEM, тот тут все просто объясняется. Это действительно обычный DER сертификат в base64 кодировке.:)
Что касается использования, могу предположить, что PEM вероятно применяется в электронной почте, т.к. DER сертификат содержит бинарные данные и его нельзя отправить в теле письма.
А вот второй формат выгрузки действительно любопытен. Не встречался с такой формой записи.
Тем не менее, выгруженный DER в формате base64 у меня отличается от выгруженного PEM-сертификата. Как так может быть?
Странно. Какими средствами пользуетесь? Только что проверил в браузере, выгрузил DER сертификат и PEM. Конвертнул DER в base64, все совпало. Но я на этом не успокоился и из хранилища сертификатов windows выгрузил DER сертификат в base64, тоже самое значение получилось.
Точно не вспомню, но по-моему было так:
keytool -export -alias SSO -keystore keystore -rfc -file certificate.pem

Против виндосовского «копировать в файл» > «Файлы X.509 (.CER) в кодировке Base64.
В результате получил два файла с разным содержимым.
Стандарт X.509 определяет, что основная кодировка для сертификата — ASN.1 DER. Стандарт PEM (Privacy Enhancement for Internet Electronic Mail) был изначально придуман для передачи бинарных сообщений в составе S/MIME сообщений (то есть для передачи бинарных сообщений в обычной электронной почте). Действительно PEM — это простое применение BAS64 кодирования к начальному бинарному сообщению.

Для бОльшего знания в этом вопросе можно почитать стандарты RFC 1421-1424.
Точнее сначала был PEM, а сейчас S/MIME.
Печально, что отсутствует упоминание инструмента openssl, а там, кстати говоря, есть целый блок команд для работы с x509. IMHO, это было бы лучше, чем пример на .net.
А лучше взять и выбросить OpenSSL и написать что-то новое и нормальное.
«Проминусовал, залез посмотрел исходники openssl»
Sign up to leave a comment.

Articles