Розбираємо кваліфіковані сертифікати X. 509 в пошуках ІПН, СНІЛС і ОГРН

«Колеги, нам необхідно вести реєстр виданих кваліфікованих сертифікатів з можливістю пошуку по ІПН, СНІЛС і ОГРН. Скільки днів потрібно для створення парсера сертифікатів і першого макета?» — з такого запитання начальника почалася чергова летючка.

Оскільки написанням програми було запропоновано зайнятися мені, довелося задуматися і покопатися в пам’яті, щоб оцінити трудомісткість задачі і зразкові терміни її виконання.

Колись я брав участь в невеликому проекті по моделюванню SSL MITM, де відповідав за генерацію ключів і сертифікатів для цього самого «людини посередині». Тому уявляв, що кваліфікований сертифікат ключа перевірки електронного підпису (далі — кваліфікаційний сертифікат) — це сертифікат X. 509, для опису внутрішньої структури якого використовується всіма улюблений ASN.1.

Ось тільки не пам’ятав я, щоб тоді на очі потрапляли ці Інни, СНИЛСы і ОГРНы. Тому відповів більш, ніж скромно: «Бос, два дні, не менше!», сподіваючись виконати завдання за кілька годин.

Нижче розповідь про те, наскільки сильно я помилився в розрахунках, а також готове рішення для парсингу сертифікатів X. 509 C# з можливістю вилучення полів і їх атрибутів з заданими об’єктними ідентифікаторами (OID).

Крок 1. Попередні дослідження і перевірка гіпотези

Ні, серйозно, це правда, що в сертифікаті X. 509 є СНІЛС? Для перевірки знайдемо зразок — просимо допомоги у Яндекса за запитом «реєстр виданих кваліфікованих сертифікатів», на першій же сторінці видачі знаходимо Реєстр виданих УЦ ЦКУ ЛО «ОЕП» сертифікатів, завантажуємо перший-ліпший сертифікат (під номером 10842) — Komarov_Aleksey_Petrovich_2017-03-31_a2ba20c4.cer.

Комаров Олексій Петрович: погляд зсередини—–BEGIN CERTIFICATE—–
MIIIzjCCCH2gAwIBAgIRAJ6w9zrKuNKX5xh+FfdJYxwwCAYGKoUDAgIDMIH4MRww
GgYJKoZIhvcNAQkBFg11ZGNAbGVucmVnlnj1mrgwfgyfkoudzaesdtexmjq3mdmw
MDAzMzMxGjAYBggqhQMDgQMBARIMMDA0nzazmti1otu2mqswcqydvqqgewjsvtes
MCoGA1UECAwjNzgg0LMu0KHQsNC90LrRgi3qn9c10ylqtdga0lhrg9ga0lmxjjak
BgNVBAcMHdCh0LDQvdC60YIt0J/QtdGC0LXRgNCx0YPRgNCzMR0wGwYDVQQkdbtq
k9Ca0KMg0JvQniAi0J7QrdCfIjEgMB4Ga1ueawwx0kpqpidqk9ca0kmg0jvqnidq
ntCt0J8wHhcNMTcwMzMxMTAyODEwWhcNmtgwmzmxmtayodewwjccao4xizahbgkq
hkiG9w0BCQEWFGFwX2tvbWFyb3ZAbGVucmvnlnj1mrowgayikouda4edaqesddaw
Nzg0MjM1NDk2NjEWMBQGBSqFA2QDEgswnzmxmtk5njy2odeymbygbsqfa2qbeg0x
MDc3ODQ3MTkyNjA5MSwwKgYDVQQMDCPQk9c70ldqstc90yvqusdrgdc/0LXRhtC4
0LDQu9C40YHRgjFBMD8GA1UECww40JTQtdc/0LDRgNGC0LDQvNC10L3RgiDQu9C1
0YHQvdC+0LPQviDQutC+0LzQv9C70LXQutGB0LAxajBoBgNVBAoMydca0l7qvnc4
0YLQtdGCINC/0L4g0L/RgNC40YDQvtC00L3Ri9C8INGA0LXRgdGd0ydrgdcw0lwg
0JvQtdC90LjQvdCz0YDQsNC00YHQutC+0Lkg0L7QsdC70LDRgdGC0LgxKjAoBgNV
BAkMIdGD0Lsu0KLQvtGA0LbQutC+0LLRgdC60LDRjywg0LQuNDEmMCQGA1UEbwwd
0KHQsNC90LrRgi3Qn9C10YLQtdGA0LHRg9ga0lmxldaqbgnvbagmizc4inczltch
0LDQvdC60YIt0J/QtdGC0LXRgNCx0YPRgNCzMQswCQYDVQQgewjsvteomcyga1ue
Kgwf0JDQu9C10LrRgdC10Lkg0J/QtdGC0YDQvtCy0LjRhzEXMBUGA1UEBAwo0jrq
vtC80LDRgNC+0LIxajBoBgNVBAMMYdCa0L7QvNC40YLQtdgcinc/0L4g0L/RgNC4
0YDQvtC00L3Ri9C8INGA0LXRgdGD0YDRgdcw0lwg0jvqtdc90ljqvdcz0ydqsnc0
0YHQutC+0Lkg0L7QsdC70LDRgdGC0LgwYzAcBgYqhqmcahmwegyhkoudagikaayh
KoUDAgIeAQNDAARA2jaQisiN++YQULAiW4b8Llik90VIKNPqUcEOVlrfplasb2w/
qc9giz+rP1/VvQXAmRKPaL3dM33MExypCJOlGaOCBEUwggrbma4ga1uddweb/wQE
AwIDqDAdBgNVHQ4EFgQU7SOIwRLKC8mDqv/q2KtCaTA06Q8wNQYJKwYBBAGCNxUH
BCgwJgYeKoUDAgIyAQmDx+sNh/eeXoXlhVqDn/dWgZtags1fAgEBAgEAMIIBYwYD
VR0jBIIBWjCCAVaAFNGDmDS2EE52TJ+tKf2SJRHjAFYJoYIBKaSCASUwggEhMRow
GAYIKoUDA4EDAQESDDAwNzcxMDQ3NDM3nteymbygbsqfa2qbeg0xmdq3nzaymdi2
NzAxMR4wHAYJKoZIhvcNAQkBFg9kaXRAbwluc3z5yxoucnuxpda6bgnvbakmmzey
NTM3NSDQsy4g0JzQvtGB0LrQstCwINGD0lsuinci0llqtdga0yhqutcw0y8g0lqu
NzEsMCoGA1UECgwj0JzQuNC90LrQvtC80yhqstgp0lfrjcdqonc+0YHRgdC40Lgx
FTATBgNVBAcMDNCc0L7RgdC60LLQsDEcmboga1uecawtnzcg0lmuincc0l7rgdc6
0LLQsDELMAkGA1UEBhMCUlUxGzAZBgNVbammetcj0kygmsdqmnchinct0kpqpoir
BKgeQAWpGF6C5hHB/EETxEYwOQYDVR0lBDIwMAYIKwYBBQUHAwigccsgaqufbwme
BggqhQMFARgCLAYIKoUDBQEYAgYGBiqFa2qcatbjbgkrbgeeayi3fqoepda6maog
CCsGAQUFBwMCMAoGCCsGAQUFBwMEMAoGccqfawubgaismaogccqfawubgaigmagg
BiqFA2QCATATBgNVHSAEDDAKMAgGBiqFa2rxatccaqygbsqfa2rwbih8mih5dcsi
0JrRgNC40L/RgtC+0J/RgNC+IENTUCIgKNCy0LXRgNGB0LjRjyA0LjApdcoi0jrr
gNC40L/RgtC+0J/QoNCeINCj0KYiINCy0LXRgNGB0LjQuCAyljamttch0lxrgngc
0LjRhNC40LrQsNGCINGB0L7QvtGC0LLQtdgc0yhrgtcy0ljrjydihjbqodcklzey
NC0zMDEwINC+0YIgMzAuMTIuMjAxNgxO0KHQtdGA0YLQunge0ljqutcw0yig0yhq
vtC+0YLQstC10YLRgdGC0LLQuNGPIOKEltCh0kqvmti4lti5odmg0l7rgiaxoc4x
MS4yMDE2MDgGBSqFA2RvBC8MLSLQmtGA0ljqv9gc0l7qn9ga0l4gq1nqiiao0llq
tdGA0YHQuNGPIDMuNi4xKTBWBgNVHR8Etzbnmcwgi6ahhh9odhrwoi8vy2eubgvu
b2JsLnJ1L2UtZ292LTUuY3JsMCSgIqAghh5odhrwoi8vdwnsby5zcgiucnuvzs1n
b3YtNS5jcmwwOwYIKwYBBQUHAQEELzAtmcsgccsgaqufbzachh9odhrwoi8vy2eu
bGVub2JsLnJ1L2UtZ292LTUuY2VyMAgGbiqfawicawnbaee1ikkhv4bqcdsbsaja
kWfh5tNaPIp/jFc+HZtpmgJoGU8CpOdX3I5YAgJTx9O+Q4ylHwJl68rfCD44s0Q4
wqE=
—–END CERTIFICATE—–

Відкриваємо сертифікат з допомогою стандартного засобу перегляду OC Windows і знаходимо в описі суб’єкта підозріло схожу рядок з об’єктним ідентифікатором 1.2.643.100.3, що складається з 11 цифр. СНІЛС?


Ліричний відступ

Про те, що таке об’єктний ідентифікатор (OID) взагалі, краще всього почитати тут. Як використовуються об’єктні ідентифікатори в описі структури сертифікатів X. 509 — дивимося Керівництво по виживанню — TLS/SSL сертифікати SSL (X. 509).
Відкриваємо сертифікат у віртуальній машині з встановленим криптопровайдером КриптоПРО CSP, який напевно знає вітчизняну специфіку, і підтверджуємо здогад.


Отже, поставлена задача потенційно здійсненна, СНІЛС кваліфікованого сертифікаті є. Йдемо далі.

Крок 2. Знайомство з нормативною базою

Природно, не в кожному сертифікаті X. 509 можна знайти ІПН, СНІЛС і ОГРН. Приміром, якщо в браузері клацнути по замочку поряд з адресним рядком «https://yandex.ru/» і експортувати сертифікат, то там ніяких довгих цифрових послідовностей не виявиться.


При цьому слід зауважити, що стандарт Х. 509 не обмежує набір атрибутів, які можуть бути вказані в ім’я видавця та/або суб’єкта. Стандарт лише рекомендує підтримувати ряд атрибутів, серед яких — країна, організація, регіон, загальноприйняте ім’я та ін., але про СНИЛСе та інше не сказано ні слова.

Читайте також  Загадка про пробоїни в «Союзі»

Нас цікавлять дані точно містяться в сертифікатах, які потрапляють у сферу дії Федерального закону «Про електронний підпис» від 06 квітня 2011 року № 63-ФЗ. Уважно вивчаємо статтю 17 і переконуємося, що ІПН, СНІЛС і ОГРН дійсно повинні міститися в кваліфікованих сертифікатах.

Тепер необхідно дізнатися, який OID відповідає значенню ІПН, а який — СНІЛС і ОГРН. З цим питанням допоможе огляд нормативної бази, де згадується Наказ ФСБ РФ від 27 грудня 2011 року № 795 «Про затвердження вимог до форми кваліфікованого сертифікату…». Відкриваємо наказ і знаходимо цікаву для нас інформацію:

18. До додаткових атрибутів імені, необхідність використання яких встановлюється у відповідності з Федеральним законом, відносяться:

1) OGRN (ОГРН).
Значенням атрибута OGRN є рядок, що складається з 13 цифр і представляє ОГРН власника кваліфікованого сертифікату — юридичної особи. Об’єктний ідентифікатор типу атрибута OGRN має вигляд 1.2.643.100.1, тип атрибута OGRN описується наступним чином: OGRN ::= NUMERIC STRING SIZE 13;

2) SNILS (СНІЛС).
Значенням атрибута SNILS є рядок, що складається з 11 цифр і представляє СНІЛС власника кваліфікованого сертифікату — фізичної особи. Об’єктний ідентифікатор типу атрибута SNILS має вигляд 1.2.643.100.3, тип атрибута SNILS описується наступним чином: SNILS ::= NUMERIC STRING SIZE 11;

3) INN (ІПН).
Значенням атрибута INN є рядок, що складається з 12 цифр і представляє ІПН власника кваліфікованого сертифікату. Об’єктний ідентифікатор типу атрибута INN має вигляд 1.2.643.3.131.1.1, тип атрибута INN описується наступним чином: INN ::= NUMERIC STRING SIZE 12.
Можна спробувати перевірити себе — знаючи OID, знайти описуваний ним об’єкт. Для прикладу візьмемо OID = 1.2.643.100.3 (СНІЛС). Звертаємося до офіційного реєстру ідентифікаторів і «прогулюємося» по дереву:

1 - International Organization for Standardization (ISO)
1.2 - ISO Member Bodies
1.2.643 - Russian federation

Значення 1.2.643.100 знайти вже не вдається, такий OID у списках офіційного каталогу не значиться. Переходимо по посиланню в національний реєстр, продовжуємо пошуки. Виявлені ідентифікатори, до яких вдалося «спуститися» по дереву:

1.2.643.100 (частина OID'а 1.2.643.100.1, відповідного ОГРНу, і OID'а 1.2.643.100.3, відповідного СНИЛСу) - Додаткові ідентифікатори
1.2.643.3.131 (частина OID'а 1.2.643.3.131.1.1, відповідного Інну) - ФГУП ГНІВЦ ФНС РОСІЇ

Перевірити себе не вийде, оскільки не всі яруси відображені на сайті національного реєстру об’єктних ідентифікаторів. Але надія вмирає останньою, пробуємо відправити офіційний запит оператору національного дерева – у ВАТ «Інфотекс Інтернет Траст». Цитуємо листування:

– Підкажіть, чи можливо на сайті oid.iitrust.ru уточнити, яким об’єктам відповідають OID’и: 1.2.643.3.131.1.1, 1.2.643.100.1, 1.2.643.100.3? У пошуку вони не перебувають, але ми припускаємо, що це ІПН, ОГРН і СНІЛС. Як можна отримати підтвердження цьому?

– Добрий День! Зазначені Вами OID затверджено наказом № 795 ФСБ Росії від 27.12.2011.

Коло замкнулося, вважаємо, що перевірка проведена успішно.

Продовжуємо вивчати Наказ ФСБ РФ від 27 грудня 2011 р. № 795 і звертаємо увагу на те, що заповнення полів та їх атрибутів залежить від власника кваліфікованого сертифікату — фізичної чи юридичної особи. Наприклад, опис заповнення атрибута commonName (загальна назва):

Читайте також  SEO в 2019 році не працює?

Як значення даного атрибуту імені слід використовувати текстовий рядок, що містить ім’я, прізвище та по батькові (якщо є) — для фізичної особи або найменування — для юридичної особи. Об’єктний ідентифікатор типу атрибута commonName має вигляд 2.5.4.3.
В нашому випадку (Komarov_Aleksey_Petrovich_2017-03-31_a2ba20c4.cer) значенням атрибута commonName є рядок «Комітет з природних ресурсів Ленінградської області», отже, власник сертифіката – юридична особа.

Для юридичної особи встановлюємо наступне відповідність об’єктних ідентифікаторів (не всіх, вибірково, цікавих нам) типів атрибутів:

2.5.4.3 – Найменування юридичної особи
2.5.4.8 - Найменування суб'єкта Російської Федерації 
1.2.643.3.131.1.1 – ІНН
1.2.643.100.1 – ОГРН
1.2.643.100.3 – СНІЛС представника юридичної особи
1.2.840.113549.1.9.1 Адресу електронної пошти

 

Крок 3. Розробка програми X. 509 сертифіката на С#

Так склалося, що розробка у нас ведеться на C#, тому й приклад програми на C#, нічого особистого і ніякого холивара.

Для простоти формалізуємо задачу наступним чином. Дано: файл кваліфікованого сертифікату в системі обмежень CER (Canonical encoding rules). Вимагається: розібрати (розпарсити) сертифікат та отримати значення ІПН, СНІЛС і ОГРН з поля суб’єкта (Subject).

Для перших начерків звертаємося до можливостей простору імен System.Security.Cryptography.X509Certificates:

using System.IO;
using System.Security.Cryptography.X509Certificates;
using System.Diagnostics;

namespace X509Parser
{
 class Program
{
 static void Main(string[] args)
{
 string fileName = @"c:Komarov_Aleksey_Petrovich_2017-03-31_a2ba20c4.cer";

 X509Certificate cert = new X509Certificate(File.ReadAllBytes(fileName));

 Debug.Print("Серійний номер: {0}", cert.GetSerialNumberString());
 Debug.Print("Дата закінчення дії кваліфікованого сертифікату: {0}", cert.GetExpirationDateString());
 Debug.Print("Суб'єкт: {0}", cert.Subject);
}
}
}

На виході отримуємо:

Серійний номер: 009EB0F73ACAB8D297E711FE15F749631C
Дата закінчення дії кваліфікованого сертифікату: 31.03.2018 13:28:10
Суб'єкт: CN=Комітет з природних ресурсів Ленінградської області, SN=Комарів, G=Олексій Петрович, C=RU, S=78 р. Санкт-Петербург, L=Санкт-Петербург, STREET="вул. Торжковська, д. 4", O=Комітет з природних ресурсів Ленінградської області, OU=Департамент лісового комплексу, T=Головний спеціаліст, OID.1.2.643.100.1=1077847192609, OID.1.2.643.100.3=07311996668, OID.1.2.643.3.131.1.1=007842354966, E=ap_komarov@lenreg.ru

Властивість X509Certificate.Subject повертає ім’я суб’єкта сертифіката типу string.

На перший погляд, можна зупинятися і нескладними регулярними виразами (приклад) вибрати з рядка нас цікавлять значення, знаючи їх OID’и і типи значень. Але погодьтеся, витонченості такого рішення явно не вистачає. Крім того, встановлений криптопровайдер може замінити коди OID’ів на символьні позначення, що призведе до зайвої ускладнення коду.

Пробуємо далі, уважно переглядаємо бібліотеку класів .NET у пошуках відповідного рішення. Після декількох спроб звернутися до поля суб’єкта як до послідовності байт стає зрозумілим, що стандартними засобами платформи .NET зовсім незручно реалізовувати перегляд структури сертифіката з можливістю пошуку по OID’ам.

StackOverflow дає підказку використовувати сторонні бібліотеки, вибираємо найбільш цитовану — BouncyCastle.

Бібліотека підключається в один клік додаванням reference в проект. Пропонований рівень абстракції дозволяє інтуїтивно зрозуміло переглядати дані у форматі ASN.1. Залишається тільки уточнити «зсув» нас цікавлять значень відносно початку файлу сертифіката, щоб правильно вказати позицію для парсера.

Відкриваємо сертифікат в редакторі ASN.1 Editor і встановлюємо відповідність зі структурою сертифіката:

(0, 2254) SEQUENCE – коренева послідовність у дужках тут і далі (зміщення, довжина)
 (4, 2173) SEQUENCE – сертифікат
 (8, 3) CONTEXT SPECIFIC – версія сертифіката
 (13, 17) INTEGER – серійний номер
 (32, 8) SEQUENCE – ідентифікатор алгоритму підпису
 (42, 248) SEQUENCE – ім'я видавця
 (293, 30) SEQUENCE – період дії
 (325, 654) SEQUENCE – ім'я суб'єкта

Нас цікавить полі «Ім’я суб’єкта», в якому і записуються значення ІПН, СНІЛС і ОГРН. Якщо уважно подивитися на малюнок, можна зробити наступний висновок: поле «Ім’я суб’єкта» (325, 654) SEQUENCE являє собою послідовність (SEQUENCE) множин (SET), що складаються з послідовностей (SEQUENCE) пар ключ/значення.

Читайте також  20 SEO-міфів, які повинні померти в 2020

Згідно з цією логікою реалізуємо парсер:

using System.Diagnostics;
using System.IO;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.X509;

namespace X509Parser
{
 class Program
{
 static void Main(string[] args)
{
 // Розбір сертифіката згідно з наказом ФСБ від 27.12.2011 №795
 string fileName = @"c:Komarov_Aleksey_Petrovich_2017-03-31_a2ba20c4.cer";

 X509CertificateParser parser = new X509CertificateParser();
 X509Certificate cert = parser.ReadCertificate(File.ReadAllBytes(fileName));

 Debug.Print("Серійний номер: {0}", cert.SerialNumber.ToString(16).ToUpper());
 Debug.Print("Дата закінчення дії кваліфікованого сертифікату: {0}", cert.NotAfter.ToString("dd.MM.yyyy"));

 // Розбір поля subject = SEQ of SET of SEQ of {OID/value}
 DerSequence subject = cert.SubjectDN.ToAsn1Object() as DerSequence;

 foreach (Asn1Encodable setItem in subject)
{
 DerSet subSet = setItem as DerSet;
 if (subSet == null)
continue;

 // Перший елемент множини SET - шукана послідовність SEQ of {OID/value}
 DerSequence subSeq = subSet[0] as DerSequence;

 foreach (Asn1Encodable subSeqItem in subSeq)
{
 DerObjectIdentifier oid = subSeqItem as DerObjectIdentifier;
 if (oid == null)
continue;

 string value = subSeq[1].ToString();

 if (oid.Id.Equals("2.5.4.3")) Debug.Print("ПІБ фізичної особи / Найменування юридичної особи: {0}", value);
 if (oid.Id.Equals("2.5.4.8")) Debug.Print("Найменування суб'єкта Російської Федерації: {0}", value);
 if (oid.Id.Equals("1.2.643.3.131.1.1")) Debug.Print("ІПН: {0}", value);
 if (oid.Id.Equals("1.2.643.100.1")) Debug.Print("ОГРН: {0}", value);
 if (oid.Id.Equals("1.2.643.100.3")) Debug.Print("СНІЛС: {0}", value);
 if (oid.Id.Equals("1.2.840.113549.1.9.1")) Debug.Print("Електронна пошта: {0}", value);
}
}
}
}
}

Дивимося висновок, погоджуємося:

Серійний номер: 9EB0F73ACAB8D297E711FE15F749631C
Дата закінчення дії кваліфікованого сертифікату: 31.03.2018
Електронна пошта: ap_komarov@lenreg.ru
ІПН: 007842354966
СНІЛС: 07311996668
ОГРН: 1077847192609
Найменування суб'єкта Російської Федерації: 78 р. Санкт-Петербург
ПІБ фізичної особи / Найменування юридичної особи: Комітет з природних ресурсів Ленінградської області 

Задача вирішена.

Підведення підсумків

Отже, підсумовуючи виконану роботу, ми:

  1. Розібралися зі структурою кваліфікованих сертифікатів X. 509, які потрапляють у сферу дії ФЗ «Про електронний підпис».
  2. Дізналися, що Наказ ФСБ РФ № 795 визначає додаткові атрибути — ІНН, СНІЛС, ОГРН та інші. Тут же вказуються відповідні об’єктні ідентифікатори (OID).
  3. Розробили парсер сертифікатів X. 509 C# з можливістю вилучення полів і їх атрибутів з заданими об’єктними ідентифікаторами. Бібліотека BouncyCastle додала рішенням простоти.

У розрахунках за часом сталася помилка — замість запланованих кількох годин довелося розбиратися весь день.

Спасибі за увагу!

Список джерел

 

  • Специфікація X. 509
  • Федеральний закон «Про електронний підпис» від 06 квітня 2011 року № 63-ФЗ
  • Наказ ФСБ РФ від 27 грудня 2011 року № 795 «Про затвердження вимог до форми кваліфікованого сертифікату ключа перевірки електронного підпису»
  • Офіційний реєстр об’єктних ідентифікаторів OID
  • Національний реєстр об’єктних ідентифікаторів OID
  • Керівництво по виживанню — TLS/SSL сертифікати SSL (X. 509)
  • ASN.1 простими словами (кодування типу REAL)
  • Розбираємо x.509 сертифікат
  • Електронний підпис простими словами
  • Бібліотека BouncyCastle

Степан Лютий

Обожнюю технології в сучасному світі. Хоча частенько і замислююся над тим, як далеко вони нас заведуть. Не те, щоб я прям і знаюся на ядрах, пікселях, коллайдерах і інших парсеках. Просто приходжу в захват від того, що може в творчому пориві вигадати людський розум.

You may also like...

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *