PKI – podstawy

Znajomi i współpracownicy wiedzą, że mam lekkiego jobla w temacie certyfikatów i pki. 😉 Wracam do tego tematu bardzo często od czasów studiów. Zawodowo można powiedzieć, że opiekuję się dwoma firmowymi infrastrukturami klucza publicznego – zarówno windowsowym (w ramach ad) jak i w oparciu o OpenSSL. Jednocześnie bardzo nie podobają mi się szeroko dostępne aplikacje GUI służące do zarządzania tymi. Narzędzia CLI są zaś mocno uciążliwe. 

Dlatego od bardzo dawna myślę o napisaniu czegoś przyjemniejszego w obyciu.

Ten dokument, mam nadzieje, otworzy serie wpisów o programowych zabawach pki z poziomu .net i C#. Nie wiem czy finalnie uda się napisać żyjącą aplikację, ale mam zamiar popełnić kilka testów i prototypów.

Na start trochę teorii omawiającej czym jest PKI i banalny program, żeby chociaż trochę kodu się pojawiło.

Alice, Bob i Charlie

W tym miejscu miała być opowieść o Alice i Bobie i ich zmaganiach ze złoczyńcą Charliem. Nawet zacząłem pisać, jednak to, co wyszło było zdecydowanie za długie jak na wpis na blogu. Zostawię zatem temat autorom książek. Zamiast tego postaram się skupić na konkretach dotyczących kryptografii asymetrycznej z kluczem publicznym, a o tej trójce wspominam, aby uhonorować ich wkład w rozwój bezpieczeństwa w IT ;-).

Klucze – publiczny i prywatny

W przypadku kryptografii symetrycznej klucz służy zarówno do szyfrowania jak i deszyfrowania wiadomości. Klucz taki powinien być znany tylko uczestnikom, każdy kto pozna klucz będzie mógł czytać i tworzyć szyfrowaną komunikację.

Przedstawiając koncepcję kryptografii asymetrycznej skupię się na RSA, obecnie jednym z najpopularniejszych algorytmów.

Zatem, w kryptografii asymetrycznej mowa jest o parze kluczy. W takim przypadku występują następujące zależności między kluczami:

  • jeden z kluczy jest kluczem prywatnym i znany jest tylko jego właścicielowi;
  • drugi z pary kluczy jest kluczem publicznym, jest powszechnie znany i może być użyty przez dowolną osobę;
  • wiadomość zaszyfrowana za pomocą klucza publicznego może być odszyfrowana jedynie za pomocą klucza prywatnego;
  • i analogicznie, wiadomość zaszyfrowana z wykorzystaniem klucza prywatnego może zostać odszyfrowana przez klucz publiczny.

Patrząc na to z innej perspektywy – jeżeli autor wiadomości zaszyfruje ją swoim kluczem prywatnym, osoby posiadające klucz publiczny mogą odszyfrować wiadomość, czyli (przy założeniu że klucz prywatny nie został wykradziony) mają pewność, kto jest autorem wiadomości.

W drogą stronę, chcąc wysłać wiadomość, którą będzie mógł odczytać tylko adresat, należy użyć do szyfrowania jego klucza publicznego.

Funkcja skrótu i podpis

Przedstawiony wcześniej pierwszy z przypadków służy do tzw. podpisywania. Zadaniem podpisu jest umożliwienie zweryfikowania autora oraz integralności wiadomości (ważne jest, żeby mieć pewność, że wiadomość dotarła w niezmienionej postaci). Przy czym sama wiadomość nie jest uznawana za tajną.

W przypadku podpisu wykorzystuje się tzw funkcję skrótu. Zadaniem takiej funkcji jest przekształcenie wejściowych danych o różnej długości w dużo krótszy „odcisk”, sumę kontrolną. Funkcja skrótu powinna charakteryzować się następującymi cechami:

  • musi być jednokierunkowa (na podstawie skrótu nie da się wygenerować oryginalnej wiadomości);
  • niewielkie zmiany w danych wejściowych powinny powodować duże zmiany w skrócie;
  • powinna być bezkolizyjna (nie powinno się dać wskazać dwóch różnych ciągów wejściowych dających taki sam skrót).

Jak w tym kontekście wygląda podpisywanie wiadomości? Nadawca tworzy wiadomość i wylicza jej skrót. Następnie ten skrót jest szyfrowany kluczem prywatnym nadawcy.

Odbiorca, aby zweryfikować wiadomość, również liczy skrót i porównuje go z tym odszyfrowanym kluczem publicznym nadawcy. Jeżeli wszystko się zgadza, znaczy to, że udało się potwierdzić tożsamość nadawcy (jest to właściciel klucza prywatnego) i pokazać, że wiadomość dotarła w niezmienionej postaci. Sama wiadomość nie jest zaszyfrowana.

Certyfikat klucza publicznego i zaufana strona trzecia

Klucze szyfrujące to tak na prawdę tylko liczby. Nie ma w nich informacji o tym do kogo należą. Zatem pozwalają potwierdzić tożsamość nadawcy, ale tak na prawdę nie wiadomo czyją. 😉 W niewielkiej skali będziemy w stanie to ogarnąć i zapamiętać do którego ze znajomych należy dany klucz publiczny. Jednak przy większej ilości stanie się to trudne. Potrzebne jest uzupełnienie kluczy o dodatkowe dane, które w sumie tworzą tzw. certyfikat.

W skład certyfikatu wchodzą: klucz publiczny podmiotu oraz dane o tożsamości tego podmiotu. Jednak nasuwa się pytanie – skąd wiadomo, że dany certyfikat jest prawdziwy i jeden z tych elementów nie został podrobiony?

Infrastruktura klucza publicznego (rozważam x.509) zakłada istnienie trzeciego składnika – tak zwanego urzędu certyfikującego. Taki urząd (CA) odpowiada za wystawianie certyfikatów i podpisywanie ich swoim kluczem. Koncepcja zakłada, że musi istnieć podmiot, co do którego tożsamości wszyscy z uczestników nie mają zastrzeżeń i mu ufają. Jest to tzw. zaufana trzecia strona.

W praktyce CA tworzą hierarchię – główne CA wystawia certyfikaty poświadczające tożsamość CA pośrednich. CA pośrednie poświadczają tożsamość albo CA pośrednich niższego poziomu, albo już użytkowników końcowych.

Zatem uzupełniając wcześniejszą informację – w skład certyfikatu wchodzą: klucz publiczny podmiotu, dane informujące o tożsamości podmiotu i podpis cyfrowy złożony przez zaufaną trzecia stronę.

Całość tworzy tzw. łańcuch certyfikacji. Znając certyfikat głównego urzędu, można zweryfikować certyfikat kolejnego w hierarchii aż dojdziemy do certyfikatu użytkownika końcowego.

Oczywiście nic nie stoi na przeszkodzie, aby główne CA tworzyło też certyfikaty końcowe, ale jest to często źle widziane przez oprogramowanie (np. przeglądarki www).

Przechowywanie kluczy i certyfikatów

Certyfikaty i klucze przechowywane są najczęściej w specjalnych kontenerach dostarczanych przez system operacyjny (ale mogą też być przechowywane w zwykłych, odpowiednio zabezpieczonych plikach). Takie kontenery często są dzielone na certyfikaty użytkownika (każdy z użytkowników systemu ma swoje prywatne miejsce do przechowywania certyfikatów) i systemowe. Czasami występuje dokładniejszy podział na np certyfikaty głównych urzędów, certyfikaty urzędów pośrednich czy prywatne certyfikaty i klucze użytkownika.

Poniżej banalny przykład tego, w jaki sposób można wyświetlić zawartość kontenera aktualnie zalogowanego użytkownika.

using System.Security.Cryptography.X509Certificates;

var store = new X509Store(StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
foreach (var cert in store.Certificates)
{
    Console.WriteLine("--------------------------------------------");
    Console.WriteLine($"        Subject: {cert.Subject}");
    Console.WriteLine($"         Issuer: {cert.Issuer}");
    Console.WriteLine($"          Valid: {cert.NotBefore} - {cert.NotAfter}");
    Console.WriteLine($"     Thumbprint: {cert.Thumbprint}");
    Console.WriteLine($"  Serial number: {cert.SerialNumber}");
}
store.Close();