Разбирая x.509 сертификат

от автора


Так уж вышло, что несмотря на относительно неплохое понимание инфраструктуры открытых ключей, содержимое *.crt файлов всегда оставалось для меня полнейшей загадкой.
Нет, не поймите неправильно. Я знаю, что x.509 сертификат содержит информацию о владельце, открытый ключ, сведения об удостоверяющем центре и электронную цифровую подпись. Но при установке очередного сертификата меня всегда мучило любопытство.
Чем отличается идентификатор ключа от отпечатка? Какие данные сертификата подписываются, а какие нет? И что за структура данных позволяет хранить всю эту информацию, сводя избыточность к минимуму.
Но вот наконец-то любопытство перебороло лень и в данном посте я постараюсь описать структуру x.509 сертификатов и ответить на эти и другие вопросы.

Часть 1. Самоподписанный сертификат

Для начала рассмотрим вариант самоподписанного сертификата корневого уровня.
Для упрощения задачи сгенерируем сертификат, который будет содержать только необходимые параметры:

  • Версия сертификата
  • Серийный номер
  • Алгоритм подписи
  • Сведения об издателе
  • Дата начала действия сертификата
  • Дата окончания действия сертификата
  • Сведения о владельце
  • Открытый ключ

Сделать это можно с помощью библиотеки Bouncy Castle, следующим образом:

private void button1_Click(object sender, EventArgs e)         {                          var KeyGenerate = new RsaKeyPairGenerator();              KeyGenerate.Init(new KeyGenerationParameters(new SecureRandom(new CryptoApiRandomGenerator()), 1024));              AsymmetricCipherKeyPair kp = KeyGenerate.GenerateKeyPair();              var gen = new X509V3CertificateGenerator();              var certName = new X509Name("CN=CA");             var serialNo = new BigInteger("1",10);                          gen.SetSerialNumber(serialNo);             gen.SetSubjectDN(certName);                         gen.SetIssuerDN(certName);             gen.SetNotAfter(DateTime.Now.AddYears(100));             gen.SetNotBefore(DateTime.Now);             gen.SetSignatureAlgorithm("SHA1WITHRSA");                         gen.SetPublicKey(kp.Public);                  var myCert = gen.Generate(kp.Private);             byte[] result = DotNetUtilities.ToX509Certificate(myCert).Export(X509ContentType.Cert);              FileStream fs = new FileStream("D:\\test1.crt", FileMode.CreateNew);             fs.Write(result, 0, result.Length);             fs.Flush();             fs.Close();         } 

В результате выполнения данной процедуры будет создан стандартный x.509 сертификат, который, будучи открытым с помощью hex-редактора, выглядит вот таким чудесным образом:

30 82 01 8F 30 81 F9 A0  03 02 01 02 02 01 01 30 0D 06 09 2A 86 48 86 F7  0D 01 01 05 05 00 30 0D 31 0B 30 09 06 03 55 04  03 0C 02 43 41 30 20 17 0D 31 33 30 39 31 35 31  35 33 35 30 32 5A 18 0F 32 31 31 33 30 39 32 32  31 35 33 35 30 32 5A 30 0D 31 0B 30 09 06 03 55  04 03 0C 02 43 41 30 81 9F 30 0D 06 09 2A 86 48  86 F7 0D 01 01 01 05 00 03 81 8D 00 30 81 89 02  81 81 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 02 03 01 00 01 30 0D 06 09 2A 86 48 86  F7 0D 01 01 05 05 00 03 81 81 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 

Тот же самый сертификат, но уже открытый с помощью стандартных средств windows:

Имя сертификата	CA Издатель	CA Версия сертификата	3 Серийный номер	0x1 Недействителен до...	15.09.2013 15:35:00 GMT Недействителен после...	22.09.2113 15:35:00 GMT Цифровая подпись (SHA-1)	F9 AD 58 B5 50 3D F6 36 5E B8 89 D4 DC C8 5F CC 25 4B 93 A2 Цифровая подпись (SHA-256)	42 02 24 20 4E 8F 3A 3E 31 38 88 E5 C5 E7 C3 03 14 3A A6 52 EA 78 B9 77 42 5B 99 EB 4B BA 23 82 Открытый ключ(1024 битный)		Алгоритм открытого ключа	rsaEncryption Модуль	 00: 8D 80 B5 8E 80 8E 94 D1 04 03 6A 45 1A 54 5E 7E 10: EE 6D 0C CB 0B 82 03 F1 7D C9 6F ED 52 02 B2 08 20: C3 48 D1 24 70 C3 50 C2 1C 40 BC B5 9D F8 E8 A8 30: 41 16 7B 0B 34 1F 27 8D 32 2D 38 BA 18 A5 31 A9 40: E3 15 20 3D E4 0A DC D8 CD 42 B0 E3 66 53 85 21 50: 7C 90 13 E9 F9 C9 26 5A F3 FF 8C A8 92 25 CD 23 60: 08 69 F4 A2 F8 7B BF CD 45 E8 19 33 F1 AA E0 2B 70: 92 31 22 34 60 27 2E D7 56 04 8B 1B 59 64 77 5F Экспонента	01 00 01                                         Подпись		Алгоритм подписи	sha1WithRSAEncryption Подпись	 00: 0A 1C ED 77 F4 79 D5 EC 73 51 32 25 09 61 F7 00 10: C4 64 74 29 86 5B 67 F2 3D A9 39 34 6B 3C A9 92 20: B8 BF 07 13 0B A0 9B DF 41 E2 8A F6 D3 17 53 E1 30: BA 7F C0 D0 BC 10 B7 9B 63 4F 06 D0 7B AC C6 FB 40: CE 95 F7 8A 72 AA 10 EA B0 D1 6D 74 69 5E 20 68 50: 5D 1A 66 28 C5 59 33 43 DB EE DA 00 80 99 5E DD 60: 17 AC 43 36 1E D0 5B 06 0F 8C 6C 82 D3 BB 3E 2B 70: A5 F1 94 FB 53 7B B0 54 22 6F F6 4C 18 1B 72 1C 

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

Прежде всего, нужно отметить, что файл *.crt хранит информацию о сертификате в закодированном виде. Для кодирования применяется особый язык, называемый ASN.1.

ASN.1 — стандарт записи, описывающий структуры данных для представления, кодирования, передачи и декодирования данных. © Wikipedia

С помощью языка ASN.1 можно описывать сложные структуры, состоящие из данных различных типов. Типичный пример ASN.1-файла выглядит как-то так:

ASN.1-файл

SEQUENCE(3 elem) 	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(1024 bit) 					INTEGER 65537 		SEQUENCE(2 elem) 			OBJECT IDENTIFIER 1.2.840.113549.1.1.5 			NULL 	BIT STRING(1024 bit) 

Однако ASN.1 разрабатывался в те светлые времена, когда «640 КБ должно было хватать каждому» и тратить место на такую громоздкую запись не было никакой возможности. Поэтому, в целях экономии места, а также более удобной обработки хранимой в ASN.1-форме информации, был разработан специальный метод кодирования — DER.

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

К примеру, для кодировки целого числа INTEGER 65537 используется следующая форма: 02 03 01 00 01.
Здесь первый байт 02, определяет тип INTEGER (полную таблицу типов вы можете найти например тут), второй байт 03 показывает длину блока. А следующие за этим байты 01 00 01, являются шестнадцатеричной записью нашего числа 65537.

В нашем случае, для описание простейшего самоподписаного сертификата, достаточно 9 типов данных. Приведем таблицу кодирования для этих типов:

Наименование типа Краткое описание Представление типа в DER-кодировке
SEQUENCE Используется для описания структуры данных, состоящей из различных типов. 30
INTEGER Целое число. 02
OBJECT IDENTIFIER Последовательность целых чисел. 06
UTCTime Временной тип, содержит 2 цифры для определения года 17
GeneralizedTime Расширенный временной тип, содержит 4 цифры для обозначения года. 18
SET Описывает структуру данных разных типов. 31
UTF8String Описывает строковые данные. 0C
NULL Собственно NULL 05
BIT STRING Тип для хранения последовательности бит. 03

Зная как кодируется каждый из этих типов, мы можем попытаться распарсить наш *.crt файл.

30 82 01 8F 30 81 F9 A0 03 02 01 02 02 01 01 30
0D 06 09 2A 86 48 86 F7 0D 01 01 05 05 00 30 0D
31 0B 30 09 06 03 55 04 03 0C 02 43 41 30 20 17
0D 31 33 30 39 31 35 31 35 33 35 30 32 5A 18 0F
32 31 31 33 30 39 32 32 31 35 33 35 30 32 5A 30
0D 31 0B 30 09 06 03 55 04 03 0C 02 43 41 30 81
9F 30 0D 06 09 2A 86 48 86 F7 0D 01 01 01 05 00
03 81 8D 00 30 81 89 02 81 81 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 02 03 01 00 01
30 0D 06 09 2A 86 48 86 F7 0D 01 01 05 05 00 03
81 81 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) 		[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 		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 

Это уже более похоже на то, что мы видим при открытии сертификатов в браузере или Windows. Пробежимся по каждому элементу:

  • INTEGER 2 — целое число, описывающее версию сертификата. Для сертификатов версии 1 равно 0.
  • INTEGER 1 — серийный номер нашего сертификата.
  • OBJECT IDENTIFIER 1.2.840.113549.1.1.5 — последовательность, описывающая алгоритм цифровой подписи. Данная последовательность описывает sha1WithRSAEncryption.
  • OBJECT IDENTIFIER 2.5.4.3 — служит индикатором того, что следующее поле описывает какое либо сведение об издателе. Последовательность 2.5.4.3, описывается свойство CN(common name) — общепринятое имя.
  • UTF8String CA — имя издателя.
  • UTCTime 13-09-15 15:35:02 UTC — дата начала действия сертификата.
  • GeneralizedTime 2113-09-22 15:35:02 UTC — дата окончания действия сертификата.
  • OBJECT IDENTIFIER 2.5.4.3 — описывает тип информации о владельце.
  • UTF8String CA — имя владельца.
  • OBJECT IDENTIFIER 1.2.840.113549.1.1.1 — характеризует алгоритм ключа, в данном случае rsaEncryption.
  • INTEGER 00: — открытый ключ сертификата.
  • BIT STRING 00: — подпись сертификата.

Важным моментом, о котором стоит особенно упомянуть являются данные, для которых вычисляется подпись. Интуитивно может показаться, что подписываются все данные идущие до последнего поля BIT STRING, содержащего подпись. Но на самом деле это не так. В стандарте x.509 подписывается определенная часть сертификата, называемая TBS-сертификат (to be sign). В TSB-сертификат входит последовательность SEQUENCE второго уровня со всеми вложенными данными.

	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 

Т.о. если перед вами будет стоять задача проверить ЭЦП x.509 сертификата, то для этого сперва необходимо извлечь TBS-сертификат.

Еще одно замечание относится к отпечатку сертификата. Как видите сам сертификат не содержит никаких сведений об отпечатке. Это объясняется тем, что отпечаток представляет собой обычное хеш-значение SHA-1 от всего файла сертификата, со всеми его полями, включая подпись издателя. Поэтому хранить отпечаток не обязательно, можно просто вычислять хеш при каждом просмотре сертификата.

Часть 2. Сертификат 2-го уровня

Мы с вами рассмотрели внутренности самоподписанного сертификата, и нам осталось понять чем отличается структура сертификатов более низкого уровня, от сертификата корневого центра.
Для этого, с помощью имеющегося у нас секретного ключа сертификата CA, создадим подчиненный ему сертификат user. И в этом нам снова поможет Bouncy Castle.

private void button2_Click(object sender, EventArgs e)         {                          var KeyGenerate = new RsaKeyPairGenerator();              KeyGenerate.Init(new KeyGenerationParameters(new SecureRandom(new CryptoApiRandomGenerator()), 1024));              AsymmetricCipherKeyPair kp2 = kpgen.GenerateKeyPair();              var gen2 = new X509V3CertificateGenerator();              var certName = new X509Name("CN=CA");             var serialNo = new BigInteger("1",10);                 var certName2 = new X509Name("CN=User");             var certNameOwner2 = new X509Name("CN=User");             var serialNo2 = new BigInteger("2", 10);                          gen2.SetSerialNumber(serialNo2);             gen2.SetSubjectDN(certName2);             gen2.SetIssuerDN(certName);             gen2.SetNotAfter(DateTime.Now.AddYears(100));             gen2.SetNotBefore(DateTime.Now.Subtract(new TimeSpan(7, 0, 0, 0)));             gen2.SetSignatureAlgorithm("SHA1WITHRSA");             gen2.SetPublicKey(kp2.Public);             gen2.AddExtension(                 X509Extensions.AuthorityKeyIdentifier.Id,                 false,                 new AuthorityKeyIdentifier(                     SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(kp.Public),                     new GeneralNames(new GeneralName(certName)),                     serialNo));              var newCert2 = gen2.Generate(kp.Private);             byte[] result = DotNetUtilities.ToX509Certificate(newCert2).Export(X509ContentType.Cert);             FileStream fs = new FileStream("D:\\FullTest.crt", FileMode.CreateNew);             fs.Write(result, 0, result.Length);             fs.Flush();             fs.Close();         } 

Распарсив наш сертификат и преобразовав его к читаемому виду, получим следующую красоту:

SEQUENCE(3 elem) 	SEQUENCE(8 elem) 		[0](1 elem) 			INTEGER2 		INTEGER2 		SEQUENCE(2 elem) 			OBJECT IDENTIFIER1.2.840.113549.1.1.5 			NULL 		SEQUENCE(1 elem) 			SET(1 elem) 				SEQUENCE(2 elem) 					OBJECT IDENTIFIER2.5.4.3 					UTF8StringCA 		SEQUENCE(2 elem) 			UTCTime13-09-15 15:35:02 UTC 			GeneralizedTime2113-09-22 15:35:02 UTC 		SEQUENCE(1 elem) 			SET(1 elem) 				SEQUENCE(2 elem) 					OBJECT IDENTIFIER2.5.4.3 					UTF8StringUser 		SEQUENCE(2 elem) 			SEQUENCE(2 elem) 				OBJECT IDENTIFIER1.2.840.113549.1.1.1 				NULL 			BIT STRING(1 elem) 				SEQUENCE(2 elem) 					INTEGER(1024 bit) 					INTEGER65537 		[3](1 elem) 			SEQUENCE(1 elem) 				SEQUENCE(2 elem) 					OBJECT IDENTIFIER2.5.29.35 					OCTET STRING(1 elem) 						SEQUENCE(3 elem) 							[0](20 byte) 6FBC9476035CB50061524C4ABE9064C9C4C32E6B 							[1](1 elem) 								[4](1 elem) 									SEQUENCE(1 elem) 										SET(1 elem) 											SEQUENCE(2 elem) 												OBJECT IDENTIFIER2.5.4.3 												UTF8StringCA 							[2](1 byte) 01 	SEQUENCE(2 elem) 		OBJECT IDENTIFIER1.2.840.113549.1.1.5 		NULL 	BIT STRING(1024 bit) 

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

[3](1 elem) 	SEQUENCE(1 elem) 		SEQUENCE(2 elem) 			OBJECT IDENTIFIER 2.5.29.35 			OCTET STRING(1 elem) 				SEQUENCE(3 elem) 					[0](20 byte) 6FBC9476035CB50061524C4ABE9064C9C4C32E6B 					[1](1 elem) 						[4](1 elem) 							SEQUENCE(1 elem) 								SET(1 elem) 									SEQUENCE(2 elem) 										OBJECT IDENTIFIER 2.5.4.3 										UTF8String CA 					[2](1 byte) 01 

который содержит сведения об издателе сертификата и его открытом ключе. Рассмотрим каждый элемент отдельно.

  • OBJECT IDENTIFIER 2.5.29.35 — набор цифр описывает какая информация хранится в блоке. Последовательность 2.5.29.35 означает, что перед нами информация о ключе подписанта.
  • [0](20 byte) 6FBC9476035CB50061524C4ABE9064C9C4C32E6B — идентификатор ключа издателя. SHA-1 хеш от закодированного с помощью DER открытого ключа.
  • OBJECT IDENTIFIER 2.5.4.3 — определяет, что следующее поле представляет имя издателя.
  • [2](1 byte) 01 — серийный номер сертификата издателя.

Напоследок откроем полученный сертификат с помощью стандартных средств и убедимся, что все необходимые данные на месте:

Имя сертификата	User Издатель	CA Версия сертификата	3 Серийный номер	0x2 Недействителен до...	15.09.2013 15:35:00 GMT Недействителен после...	22.09.2113 15:35:00 GMT Цифровая подпись (SHA-1)	A4 E7 9B AD E7 E2 67 B1 8A D6 6F F9 61 0D 42 A9 DB C3 A9 67 Цифровая подпись (SHA-256)	39 A2 D8 47 CE F7 E7 C3 81 62 8A 4A 65 F3 4A E8 6F 12 B7 8A 1A ED F9 94 6E 57 19 F6 39 DA B7 8F Открытый ключ(1024 битный)		Алгоритм открытого ключа	rsaEncryption Модуль	00: A7 BA 25 52 5F 0D 82 EE 2C B1 F0 E1 E2 0D 3F B2 10: 25 06 DB A2 5A B0 D3 00 D7 2C 1F 85 8C 71 73 95 20: 8A 06 6C 04 6D 4B AB 15 50 1E 53 92 9F BA 6E 04 30: 5D 71 6B C0 0A 8E 6C 51 51 2F 27 2E BB 8E C9 FF 40: 9C C2 E2 45 56 26 6B 61 C5 C1 67 0C 6F A9 8A 16 50: 76 8E 12 DB 38 A2 B3 09 6F B3 39 DD 9B EB 98 B7 60: 61 9F 9E 18 65 4F DB AB 74 72 79 AC 14 7C 24 D8 70: 47 16 5B 17 30 CB 6E FB 45 5E D1 04 37 FA 85 C3 Экспонента	01 00 01                                         Подпись		Алгоритм подписи	sha1WithRSAEncryption Подпись	00: 2C 1C D9 7F B4 F2 D0 10 16 7A B7 29 D6 89 A4 A1 10: 2B 4A 78 1B 85 38 53 83 4E 71 3C 81 C0 A5 AD A8 20: AB 16 59 F4 D3 A7 7E 83 2F AE 21 75 9E 91 F6 FC 30: 93 A3 AE F5 27 CF 5F 0B C9 5F DC E1 75 26 D5 39 40: 74 32 39 B9 BD 95 79 A7 EE 02 0C 56 0A A9 A5 83 50: F8 86 0D 6F B5 7F C5 FE 23 0B 4B 5C 65 A8 BC 89 60: 36 37 B3 53 74 BB 25 66 10 F8 53 AA EF 05 9E ED 70: 74 04 E9 3D F4 DF 85 71 37 57 5D E7 D8 C6 8E EA  Расширения		X509v3 Authority Key Identifier	keyid:6F:BC:94:76:03:5C:B5:00:61:52:4C:4A:BE:90:64:C9:C4:C3:2E:6B DirName:/CN=CA serial:01 

Заключение

Тех усидчивых людей, которые продрались сквозь все эти ASN.1 выражения и шестнадцатеричные наборы данных, я хотел бы поблагодарить за прочтение. Надеюсь вам было хоть немного интересно. И стало чуточку понятнее, что же такое на самом деле X.509 сертификат.

Ну и как всегда немного ссылок для тех, кому хочется больше подробностей.

  1. RFC5280 — спецификация x.509 сертификата и списка отзывов сертификатов.
  2. Руководство по выживанию — SSL/TLS и сертификаты X.509
  3. ASN.1 простыми словами
  4. on-line утилита для декодирования DER-файлов

ссылка на оригинал статьи http://habrahabr.ru/post/194664/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *