Poprzednio opisałem podstawowe pojęcia dotyczące infrastruktury klucza publicznego. Teraz chciałbym bliżej zająć się samym certyfikatem. Tym jaką on ma budowę, które elementy są ważne, a które opcjonalne.
Będzie to bardzo ogólny opis dotyczący podstawowych elementów certyfikatów. Po więcej mogę odesłać do RFC 5280. Natomiast w temacie rozszerzeń planuję dedykowany wpis.
Budowa certyfikatów zdefiniowana jest w RFC5280. Poniżej poglądowy schemat wraz z opisem pól.
- Wersja
- Liczba mówiąca o wersji certyfikatu – v1(0), v2(1), v3(2)
- Numer seryjny
- Dodatni numer całkowity, nadawany przez CA. Każdy certyfikat musi mieć unikalny numer w ramach CA.
- Podpis
- Pole zawiera nazwę algorytmu wykorzystanego do podpisu certyfikatu. Parametry są opcjonalne i będą się różnić w zależności od wskazanego algorytmu.
- Wydawca
- Nazwa wystawcy certyfikatu w postaci „distinguished name”.
- Termin ważności
- Czasy ważności „nie przed” i „nie po”. Zapisane w UTC bądź jako GeneralizedTime (od roku 2050).
- Właściciel
- Nazwa podmiotu, dla którego wydany jest certyfikat, w postaci „distinguished name”.
- Informacja o kluczu publicznym
- Pole służy do przechowywania klucza publicznego oraz informacji o algorytmie, z którym ten klucz może być wykorzystywany.
- Unikatowy ID wystawcy
- Unikalny ID właściciela
- Pola aktualnie nie są używane. Są to elementy opcjonalne, dozwolone od wersji v2.
- Rozszerzenia
- Dodatkowe atrybuty certyfikatów. Są to elementy opcjonalne, dozwolone od wersji v3.
Przykładowy certyfikat
Poniżej przykładowa struktura certyfikatu w wersji pierwszej. W taki sposób certyfikat przedstawiany jest przez narzędzie OpenSSL.
Certificate:
Data:
Version: 1 (0x0)
Serial Number: 4096 (0x1000)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=PL, ST=LODZKIE, O=pworwag.com.pl, CN=PWORWAG.COM.PL INTERMEDIATE CA
Validity
Not Before: Apr 8 11:37:55 2023 GMT
Not After : Apr 17 11:37:55 2024 GMT
Subject: C=PL, ST=LODZKIE, O=pworwag.com.pl, CN=DailyRoutine JWT
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
Modulus:
00:e6:6c:d5:18:ab:57:a5:71:96:78:67:00:d7:59:
e4:6e:df:2c:ee:a5:48:89:2c:10:e7:85:99:d0:81:
c4:b3:ba:ab:20:ea:2d:b1:44:fe:63:1a:61:80:c0:
e7:15:17:2b:78:f8:8c:04:a5:82:1a:a2:39:d1:ba:
6c:63:4c:82:67:ae:66:6b:b0:d1:ea:c7:cb:40:4f:
1e:8a:b0:82:6c:b6:0a:3c:f7:fb:c7:d3:ba:1e:8f:
5b:9a:a5:94:96:4f:8d:b6:58:af:fa:1d:c8:5e:57:
4f:d0:f5:80:9f:7d:3b:99:f5:9e:a1:6f:02:64:40:
eb:2c:ad:e3:a8:2f:a9:ad:72:0e:b8:d3:b6:b1:47:
1d:2f:b9:2b:b0:34:ed:36:f8:16:75:9d:12:7e:ff:
d6:1b:51:9a:f7:6f:b9:e5:e2:a6:c5:a7:1d:99:14:
3f:17:fb:07:ea:62:52:db:ef:29:b9:eb:14:4a:13:
fa:42:d9:b1:95:90:e1:4b:02:45:9d:53:c9:c4:0b:
76:a0:dc:ed:ed:f6:ff:37:2e:ef:bc:b4:e1:88:c7:
5a:d8:c3:a9:d1:9b:65:ca:49:be:66:25:23:e5:67:
7d:bf:32:11:f7:fa:90:f0:c2:64:25:6b:0f:3c:4e:
05:ed:5f:a9:ad:5f:e0:fe:57:51:9c:eb:c5:a5:16:
47:d3
Exponent: 65537 (0x10001)
Signature Algorithm: sha256WithRSAEncryption
39:48:a2:66:9c:ca:d2:9b:7c:10:99:bf:8e:39:91:d7:73:d2:
3b:75:14:5b:49:6b:bf:76:71:73:fe:d2:fd:3c:82:68:cb:e4:
15:44:ff:d6:c1:50:59:bc:51:6a:67:42:6a:bc:da:6e:d4:5e:
cc:e3:9d:30:38:9b:e8:6b:58:6b:6f:0d:ca:b8:a8:48:7f:ae:
f7:e7:dc:58:8f:eb:75:bb:f4:9d:04:7a:9c:5a:be:4b:4c:89:
7d:f3:ee:3d:50:66:8f:ba:e4:c6:6e:d4:96:8c:ee:2f:b5:b0:
11:57:cb:ad:8d:4c:6d:45:72:e2:34:2d:ae:34:37:5e:20:52:
78:11:03:96:35:78:71:d2:3e:01:b4:82:fa:9d:cf:cf:5f:cf:
9d:1c:8f:34:a0:21:38:f0:0a:56:fa:12:ce:51:82:56:ea:47:
2b:95:20:25:47:2d:bc:2b:45:7c:e3:49:0e:a5:09:74:7a:0d:
28:72:4c:d7:5f:02:57:a8:66:eb:f4:10:9d:f5:79:b5:77:f4:
95:3e:c7:05:29:90:16:e2:31:b8:06:99:c8:53:78:2d:d1:fd:
4e:f2:b7:ff:a0:b4:58:b9:f1:20:5f:6b:49:2a:0a:56:0a:ea:
e1:e5:b3:e1:6d:c3:94:f1:d7:07:62:4a:67:80:c8:06:f3:29:
16:64:ed:58:f1:c1:91:53:ce:62:66:43:ae:c6:c7:d5:da:db:
18:db:0f:ce:a3:19:65:79:3a:db:60:03:bf:6e:1a:dc:ae:e4:
df:4e:0c:01:ea:5b:b1:46:fe:c7:c8:bb:15:9b:1a:cd:0d:e8:
b1:44:3d:0d:12:73:1e:4e:2c:55:0b:97:57:61:26:e1:44:1b:
cb:5a:72:ee:fd:ba:94:ef:02:76:43:43:93:66:4b:e2:99:6f:
bb:fe:51:ee:67:37:8c:bf:32:d1:ac:1d:12:5d:1f:80:9e:9c:
e5:58:4a:30:5e:17:3a:0b:eb:4e:6b:75:42:34:a4:18:24:16:
9f:ed:ba:2b:c5:8a:91:a8:b7:e8:05:d6:77:dd:d3:48:f7:1e:
aa:84:e0:c4:c6:6d:bc:64:d9:58:31:f3:e4:f7:ff:4b:5f:f3:
ae:ef:c9:aa:63:09:a6:5e:5f:49:c4:27:87:ff:2d:93:4f:fb:
36:59:5d:14:3b:66:46:f4:3a:4d:5d:7a:c4:e6:a7:b9:4a:69:
32:bd:b0:6f:5a:29:66:3e:c9:7a:84:a2:7f:93:fb:9d:da:54:
81:d9:ef:c3:2c:f7:ee:06:22:52:99:95:f8:38:62:51:8b:aa:
83:1a:cc:06:5f:49:59:ae:01:ef:e9:3e:38:ba:3f:f3:0b:48:
df:d4:eb:1b:8d:87:d9:cf
Podstawowe parametry łatwo jest odczytać programowo. Przykład poniżej.
using System.Security.Cryptography.X509Certificates;
var store = new X509Store(StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
Console.WriteLine($" Certificates count: {store.Certificates.Count}\n\n");
var c = store.Certificates[0];
Console.WriteLine($" Version: {c.Version}");
Console.WriteLine($" SerialNumber: {c.SerialNumber}");
Console.WriteLine($"SignatureAlgorithm: {c.SignatureAlgorithm.FriendlyName}");
Console.WriteLine($" Issuer: {c.Issuer}");
Console.WriteLine($" NotBefore: {c.NotBefore}");
Console.WriteLine($" NotAfter: {c.NotAfter}");
Console.WriteLine($" Subject: {c.Subject}");
var pk = c.PublicKey;
Console.WriteLine($"PublicKeyAlgorithm: {c.PublicKey.Oid.FriendlyName}");
Console.WriteLine($" Extensions count: {c.Extensions.Count}");
store.Close();