Pull to refresh

Comments 15

У того самого asn1 editor, которым вы пользовались для просмотра сертификата есть обычный шарповый метод
Asn1Parser.GetNodeByOid(string oid)


А ещё можно обойтись коробочными решениями, там есть всё, чтобы прочитать сертификат\подпись целиком.
Согласен, альтернативных решений может быть много. BouncyCastle выбран по понятной причине — чаще попадался на StackOverflow во время погружения в задачу, при этом простые примеры нужного нам обхода дерева после нескольких попыток так и не обнаружились.

Одна из идей третьей части (разработка парсера) — показать, что базовыми средствами .NET не очень удобно (читай, просто и логично) «прогуливаться» по дереву в поисках нужного OID'а.
А что сложного тут вообще было?
И цикл в парсере выглядит как-то не очень.
Если честно, «сложного тут вообще» было немного: "… вместо запланированных нескольких часов пришлось разбираться весь день. И еще два дня на подготовку исследования для Хабра."

Статья писалась с простой целью — сэкономить время другим читателям Хабра на тот случай, если они столкнутся с подобной задачей (и я надеюсь, поисковики начнут выдавать этот пост для тех, кто ищет «парсинг сертификатов x.509 с#», рядом с публикацией Разбираем x.509 сертификат как хорошее дополнение). Так что, позвольте считать время, потраченное на поиск решения, показателем сложности.

Это конечно, когда уже во всем разобрался, все кажется логичным и понятным. Но когда только начинаешь погружаться в криптографию, то понимаешь, что это ЖОПА. Ведь как думаешь в начале? Да что там, ведь столько компаний вбухивают бабла в нее, такой хайп стоит, "нескольких часов хватит", чтобы разобраться.


На деле же криптография — это какая-то секта избранных. Во-первых, очень сложно понять, с чего начать, где тот якорь, с которого начать раскрутку. Пресловутые несколько часов могут уйти только на его поиски. Во-вторых, вольные трактовки понятий. Подите с первого раза разберитесь, почему описание сертификата из RFC 5280 (структура Certificate) не соответствует тому, что лежит в файлах. Ответ — потому что там лежит структура контейнера, внутри которого и находится структура Certificate, и весь этот контейнер тоже почему-то называется сертификатом. Обычно это структура PKCS#7 и описана она в RFC 2315 (и то, еще нужно догадаться, что в файле именно она, RFC же только формат описывает. Помочь разобраться в этом могут парсеры ASN.1, о них ниже), а ведь есть еще PKCS#12 и, как вы догадываетесь, пропущенные номера также не пустуют. Разобраться во всех этих хитросплетениях без подготовки крайне тяжело. Номера RFC-шек между собой если и связаны, то явно эта связь для мозга, функционирующего отлично от человеческого.


Пикантности ситуации добавляет тот факт, что, например в джаве, стандартным криптографическим API от Sun-овского криптопровайдера файл с сертификатом не прочитать, т.к. API требует именно структуру Certificate на входе, а вот BouncyCastle тут дает поблажку и может сам выпарсить ее из контейнера. Что на мой взгляд плохо, т.к. заставляет полагаться на неочевидное и негарантированное поведение конкретного криптопровайдера. И вот представьте, хотите вы структурировать для себя информацию, делаете демо пример, и с одним провайдером он работает, а с другим нет! И вот сиди думай, где тут ошибки — у тебя или в одной из библиотек, а если в библиотеке, то в какой именно и что гуглить.


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


Еще пару часов рыскаешь по гуглу, проникаешься разрухой. Хорошо, если к этому моменту удастся уже выйти на RFC (еще поди пойми, которое из них сейчас актуально!) с описанием всей этой криптографической мишуры. На этом этапе уже понимаешь, что BouncyCastle, в общем то, неплох — разбор ASN.1 структур там сделан неплохо. Собственно, пожалуй, только этим и можно нормально пользоваться, даже без документации, ее вышеприведенные RFC заменяет.


Автор в итоге и пришел к такому решению — используем хорошую часть библиотеки, забиваем на непонятную. Фактически при разборе сертификата нужно знать только его структуру, а она в RFC описана. Дальше только с помощью классов библиотеки парсим структуру и вытаскиваем нужное.


Ну и еще хотелось бы предостеречь читателей от статьи ASN.1 простыми словами (кодирование типа REAL). На мой взгляд, там не только простые слова, а героическое возведение и штурм укреплений, когда можно было пройти через ворота. Лучше ее не читать, только каши в голове добавит.


Да, и еще не могу не упомянуть замечательный сайт https://lapo.it/asn1js/ (у него есть и автономный режим работы — скачиваете html-ку) для декодирования ASN.1. Можно как вставлять как base64 так и hex, пробелы выкусываются автоматически

Только вот примерно все, описанное в топике, к криптографии не имеет ни малейшего отношения. Просто есть некий файл в ASN1/DER, который надо разобрать, понять, что внутри дерево, пройтись по нему и найти там нужное. Вместо ASN1 мог быть RIFF, TIFF, EBML, BSON, Protobuf, Apache Avro и т.д. — в общем, любой бинарный контейнер. Радикально ничего от этого не меняется.

Вместо ASN1 мог быть RIFF, TIFF, EBML, BSON, Protobuf, Apache Avro и т.д. — в общем, любой бинарный контейнер. Радикально ничего от этого не меняется.

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


Впрочем, соглашусь, что к академической криптографии описанное в посте действительно никак не относится. В академической криптографии вообще никаких контейнеров нет. Однако мы все же говорим о практическом применении. И форматы файлов — это тоже часть практической криптографии. Можете назвать еще хоть одну массовую, не нишевую, область, где ASN.1 используется? Сомневаюсь. Так что с практической точки зрения работа с ASN.1 почти равно криптографии. Или даже так: работа с ASN.1 почти всегда подразумевает касание криптографии.


Вместо ASN1 мог быть RIFF, TIFF, EBML, BSON, Protobuf, Apache Avro и т.д. — в общем, любой бинарный контейнер.

Это не совсем так. Скажем, если вы захотите сгенерировать подпись с помощью какой-то железки, которой на вход подают массив байт и ид. ключа в этой железке, а на выходе зашифрованный приватной частью этого ключа массив этих байт, то что вы будите делать? Если вы наивно полагаете, что достаточно будет запихать в нее те данные, что вы хотите подписать и получившийся массив записать в "любой бинарный контейнер", то вы заблуждаетесь. Потому, что по RFC для вычисления подписи шифруется не ваш массив, и даже не хеш от него, а хеш от ASN.1 контейнера специального вида, куда засунут хеш от вашего массива + описание алгоритма взятия хеша, параметры этого алгоритма и еще может быть чего. И шифруется уже этот контейнер, преобразованный в массив байт вполне конкретным способом.

Можете назвать еще хоть одну массовую, не нишевую, область, где ASN.1 используется?

Я могу назвать с десяток (вроде LDAP, SNMP, H.323, UMTS, LTE, WiMAX, 3GPP и вообще очень много всего в том, что касается телекомов и вокруг них), но вы удобно скажете, что это все "нишевые области". Впрочем, чем тогда "криптография" не нишевая?


Или даже так: работа с ASN.1 почти всегда подразумевает касание криптографии.

Если мы откроем какой-нибудь более-менее современный словарь, то прочитаем там что-то вроде: "Криптография — дисциплина, включающая принципы, средства и методы преобразования информации в целях сокрытия ее содержания, предотвращения видоизменения или несанкционированного использования."


И вот в посте ровно пример того, где работа с ASN.1 ну совсем никак не связана с использованием криптографии. Ничего не шифруется или подписывается с целью сокрытия содержания или защиты от изменений. Сертификат используется просто как источник данных. Если бы эти данные можно было получить, обратившись в какую-нибудь БД или веб-сервис — скорее всего так бы и сделали, а не разбирали сертификаты.

Телеком — это именно что нишевая область. Криптография не нишевая, потому что это чисто утилитарная область, само по себе она никому не сдалась, нужна только вместе с чем-то. И областей, требующих для себя криптографии, вполне много.


И вот в посте ровно пример того, где работа с ASN.1 ну совсем никак не связана с использованием криптографии

Ну да, ничего не шифруется и не проверяется. Согласен. Однако работать с ASN.1 приходится под соусом криптографии. Даже парсер ASN.1 является частью криптографической библиотеки, а не отдельной библиотекой. Потому что там он не абстрактный парсер контейнеров с информацией, а все-таки наделяет эти контейнеры каким-то смыслом. Вот здесь у нас ContentInfo, здесь SignedData, а здесь EnvelopedData. Это уже часть криптографической библиотеки. Можно эти структуры считать "средствами… преобразования информации" из приведенного вами определения?

Когда занимался такими же задачами, то вместо ASN1 Editor использовал asn1js. Который отлично работает со строками. В ASN1 есть несколько типов строк, и ASN1 Editor кириллицу отображает плохо. А доработать код на C++ для поддержки Unicode не так-то просто.


И сделал пару доработок для asn1js, чтобы отображать СНИЛС, ИНН,… и иметь удобный способ сравнивать сертификаты/подписи.


К комитам есть скриншоты, посмотрите, может пригодится:



image

print description — классная фича, жалко, что похоже автор pull request-ы почему-то не принимает, но отослать все равно надо бы

Only those users with full accounts are able to leave comments. Log in, please.