Certyfikaty

Wprowadzenie

Co to jest certyfikat? Przedstawiając sprawę ogólnie można powiedzieć, że certyfikat to dokument elektroniczny, który pozwala potwierdzić tożsamość jego właściciela. Bardziej dokładnie, jest to klucz publiczny powiązany (podpisem elektronicznym) z tożsamością osoby lub organizacji, czyli danymi takimi jak nazwa, adres, itp. Istotnym elementem certyfikatu jest zaświadczenie jego autentyczności, czyli jakiś rodzaj potwierdzenia, że dane na nim umieszczone są autentyczne. Ten rodzaj potwierdzenia jest realizowany przez podpis cyfrowy i kluczowe staje się, kto podpisuje. Najczęściej spotykane są dwa rozwiązania tej materii:

  • PKI, który oparty jest o CA, czyli centrum autoryzacji. CA to jednostka, która potwierdza autentyczność certyfikatów (dokładniej: danych na nich umieszczonych) i która powinna być godna zaufania. Możemy mieć także sytuację, w której CA jest mniej znane, ale jego tożsamość została potwierdzona przez bardziej znane CA (mamy wtedy do czynienia z łańcuchami zaufania). O ile z dużą dozą pewnością można ufać znanym CA (VeriSign, Thawte) oraz firmom, których certyfikaty są umieszczone wśród zaufanych certyfikatów systemu Windows, to w przypadku łańcuchów CA warto być już bardziej czujnym. Na pewno z punktu widzenia technicznego rolę CA może pełnić ktokolwiek. Warto też dodać, że niektóre organizacje mające odpowiednie umocowanie prawne mogą wystawiać tzw. certyfikaty kwalifikowane, które krajach UE mogą służyć do składania podpisu elektronicznego, równoważnemu podpisowi własnoręcznemu (tzw. podpis kwalifikowany). W Polsce rolę głównego urzędu certyfikacji pełni Narodowe Centrum Certyfikacji i to ono określa, kto może wydawać certyfikaty kwalifikowne (sam NCCert nie wystawia certyfikatów).
  • Web of Trust. Idea WOT polega na tym, stajemy się zaufani dla innych, jeśli zaufa nam odpowiednia liczba osób z sieci WOT (dokładniej: zbiera się tam punkty i po przekroczeniu odpowiedniego progu, stajemy się zaufani). Łatwo tutaj wytknąć słabość polegającą na zaufaniu do innych ludzi, jednak z praktyce tego typu sieci sprawdzają się całkiem nieźle.

Zwykle certyfikaty są podpisane przez kogoś innego: CA w przypadku schematu PKI oraz innego użytkownika w przypadku WOT. Zdarza się jednak, że certyfikat jest samopodpisany (self-signed certificate) i ma to miejsce zarówno w WOT, jak i w PKI (główny urząd certyfikacji, np. VeriSign nie ma nadrzędnego CA, więc musi posiadać certyfikat typu self-signed). Także do potrzeb testowych też często generuje się tego typu certyfikaty z uwagi na łatwość ich generowania. Ważnym do odnotowania jest, że certyfikatów samopodpisanych nie można odwołać (unieważnić), natomiast certyfikaty wydane przez CA mogą być odwoływane. To istotny brak z punktu widzenia bezpieczeństwa infrastruktury opartej o certyfikaty.

Czasami zdarza, że certyfikat zostanie skompromitowany (np. przez upublicznienie klucza prywatnego), użytkownik, który go posiada, nie powinien dłużej mieć dostępu do pewnych zasobów, do których dostęp jest sterowany przez PKI, lub wydarzy się jeszcze coś innego, co powoduje, że certyfikat przestaje być zaufany. Wtedy z pomocą przychodzi nam dwa mechanizmy:

  • lista CRL — CA publikuje listę wystawionych przez siebie certyfikatów, które straciły ważność; sprawdzenie ważności certyfikatu polega na przeszukaniu takiej listy,
  • protokół OCSP — określa standard protokołu wymiany informacji, formatu komunikatów, ogólnie, usługi, która udziela informacji o statusie danego certyfikatu (status może być „poprawny”, „unieważniony”, „nieznany”); dużo wygodniejszy i praktyce częściej stosowany niż listy CRL.

Jak zostało napisane na począku, certyfikat to klucz publiczny powiązany z danymi jego właściela. Jakie dokładnie są to dane jest określone przez odpowiednie standardy. Najczęściej obecnie używane są certyfikatu w standardzie X.509. to standard z szerszej rodziny standardów X.500, które opisują usługi katalogowe (np. LDAP bazuje na X.500). Poza samym formatem certyfikatu opisuje on także urząd certyfikacji, listy CRL, a także szereg innych powiązanych elementów. Certyfikat X.509 zawiera następujące składowe: (za wikipedią)

  • tbsCertificate - kontener zawierający właściwą treść certyfikatu, podlegający podpisaniu (to be signed) przez urząd certyfikacji
    • Version - wartość 0 dla X.509v1, wartość 2 dla obecnie obowiązującej wersji X.509v3
    • Serial Number - dodatnia liczba całkowita stanowiąca unikalny identyfikator certyfikatu wydany w ramach danego urzędu certyfikacji
    • Signature - algorytm kryptograficzny jakiego urząd certyfikacji użył do złożenia podpisu pod strukturą tbsCertificate; wartość ta jest powtórzeniem pola Signature Algorithm umieszczonego na zewnątrz struktury tbsCertificate gwarantując jego autentyczność
    • Issuer - opis urzędu certyfikacji w notacji X.500
    • Validity - data i czas GMT początku ważności certyfikatu oraz końca jego ważności
    • Subject - opis podmiotu (właściciela certyfikatu) w notacji X.500
    • Subject Public Key Info - struktura zawierająca ciąg bitów klucza publicznego podmiotu oraz opis algorytmu kryptograficznego zapisany jako jego OID
    • Extensions - rozszerzenia ograniczające sposób korzystania z certyfikatu oraz sposób weryfikacji ścieżki certyfikacji
  • Signature Algorithm - algorytm kryptograficzny jakiego urząd certyfikacji użył do złożenia podpisu pod strukturą tbsCertificate
  • Signature Value - ciąg bitów zawierający wartość podpisu cyfrowego

Dodatkowo firma VeriSign wprowadziła klasy certyfikatów na podstawie celu, do którego mają służyć: (za wikipedią)

  • Class 1 for individuals, intended for email.
  • Class 2 for organizations, for which proof of identity is required.
  • Class 3 for servers and software signing, for which independent verification and checking of identity and authority is done by the issuing certificate authority.
  • Class 4 for online business transactions between companies.
  • Class 5 for private organizations or governmental security.

Certyfikat może być zapisywany w kilku formatach:

  • .pem — zapis bazuje na Base64 i znajduje się pomiędzy znacznikami -----BEGIN CERTIFICATE----- i -----END CERTIFICATE-----
  • .cer, .crt, .der — zapis w pliku binarnym
  • .p7b, .p7c — dane w standardzie PKCS #7
  • .p12 — dane w standardzie PKCS #12 (najcześciej wykorzystywane do przechowywania certyfikatu z kluczem prywatnym)
  • .pfx — dane w standardzie PFX, poprzedniku PKCS #12 (również wykorzystywane do przechowywania certyfikatu wraz z kluczem prywatnym)

W kontekście certyfikatów nie sposób nie wspomnieć o grupie standardów PKCS. Opisuje ona szereg zadań związanych z ceryfikatami, kilka przykładowych:

  • PKCS#3 (Diffie-Hellman Key Agreement Standard) — wykorzystywany do bezpiecznej wymiany klucza (zwykle do kryptografii symetrycznej)
  • PKCS#7 (Cryptographic Message Syntax Standard) — wykorzystywany do podpisywania i/lub szyfrowania komunikatów w ramach PKI
  • PKCS#10 (Certification Request Standard) — określa format żądania (komunikatu) wysyłanego do CA; celem jest zwrotne otrzymanie od CA podpisanego przez to CA certyfikatu
  • PKCS#12 (Personal Information Exchange Syntax Standard) — określa format wykorzystywany do przechowywania klucza prywatnego wraz z certyfikatem. Całość jest zabezpieczona hasłem szyfrowania symetrycznego (PFX był poprzednikiem PKCS#12)

Na koniec naszego krótkiego wprowadzenia w świat certyfikatów warto wspomnieć, że większość różnych formatów bazuje na notacji ASN.1.

OpenSSL

Do tworzenia i zadządzania certfykatami będziemy używać darmowego programu openssl. Szereg możliwości tego oprogramowania jest znacznie większy, niż samo zarządzanie certyfikatami:

  • szyfrowanie symetryczne: algorytmy Blowfish, DES, IDEA, itd.,
  • szyfrowanie asymetryczne: algorytmy Diffiego-Helmana, DSA, RSA.,
  • obsługa certyfikatów: X509, X509v3, itd.,
  • generator liczba pseudolosowych,
  • sporo innych możliwości.

OpenSSL działa w dwóch trybach:

  • wsadowych, w którym wydajemy pełne polecenia,
  • interaktywnym, w którym uruchamiamy konsolę openssl i tam wydajemy kolejne polecenia.

Nas przede wszystkim openssl interesuje w punktu widzenia certyfikatów i te zadania openssl-a będzie głównie omawiać. W pierwszej kolejności utworzymy własne CA.

Zakładamy, że openssl jest już zainstalowany (zwykle z każdą dystrybucją dostarczany jest odpowiedni pakiet, tak też jest w przypadku SuSE Linux). Plikiem konfiguracyjnym jest plik

/etc/ssl/openssl.cnf
Jest w nim mnóstwo różnych ustawień, jednak nas będzie interesować tylko minimum do uruchomienia własnego CA. Znajdujemy zatem sekcję [ ca ], w której znajduje się wpis
default_ca = CA_default
Określa on sekcję, w której będzie opisane nasze CA. Znajdujemy tą sekcję i widzimy, że konfiguracja jest już w zasadzie przygotowana (są także komentarze co która zmienna opisuje):
[ CA_default ]
dir             = ./demoCA
certs           = $dir/certs
crl_dir         = $dir/crl
database        = $dir/index.txt
new_certs_dir   = $dir/newcerts
certificate     = $dir/cacert.pem
serial          = $dir/serial
crlnumber       = $dir/crlnumber
crl             = $dir/crl.pem
private_key     = $dir/private/cakey.pem
RANDFILE        = $dir/private/.rand
To co warto zmienić, to katalog gdzie wszystko jest przechowywane, np.:
dir             = /etc/ssl/CA
Następnie tworzymy strukturę katalogów i pamiętamy, że pliki index.txt i serial muszą istnieć, dodatkowo serial musi zawierać dwucyfrowy kolejny numer wygenerowanego certyfikatu, czyli wydajemy polecenia:
# touch /etc/ssl/CA/index.txt
# echo 00 > /etc/ssl/CA/serial
Kolejnym etapem jest wygenerowanie klucza prywatnego CA (przechodzimy najpierw do katalogu /etc/ssl/CA/)
# openssl genrsa -des3 -out private/cakey.pem
a kolejnym certyfikatu
# openssl req -new -x509 -days 365 -key private/cakey.pem -out cacert.pem

Warto odnotować, że jeśli zamiast -days 365 wpiszemy -days 7300 to mamy spokój z certyfikatem (jego ważnością) na 20 lat. Po wydaniu powyższego polecenia podajemy hasło do klucza prywatnego oraz dane o CA:

Country Name (2 letter code) [AU]:PL
State or Province Name (full name) [Some-State]:Dolnośląskie
Locality Name (eg, city) []:Wrocław
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Kogucik sp. z o.o.
Organizational Unit Name (eg, section) []: Górna Grzęda
Common Name (eg, YOUR name) []:firmakogucik.com.pl
Email Address []:

Tworzenie centrum autoryzacji (CA) mamy zakończone.

No koniec możemy sobie obejrzeć nasz certyfikat wydając polecenie:

# openssl x509 -in cacert.pem -text -noout

Na koniec krótki komentarz. Najkrótsze polecenie, które wygeneruje nam certyfikat dla CA jest następujące:

# openssl req -new -x509 -out cacert.pem

przy czym (1) klucz prywatny będzie zapisany w pliku privkey.pem oraz (2) certyfikat będzie ważny miesiąc (co zwykle jest trochę za krótko). Ale powyższe na pewno łatwiej zapamiętać.

W tym miejscu należy zwrócić uwagę na pewien szczegół. Otóż polecenie generowania certyfikatu utworzyło certyfikat samopodpisany. Dalej pokażemy kroki, jak wygenerować certyfikat podpisany przez nasze nowo utworzone CA.

  • Tworzymy klucz prywatny:
    # openssl genrsa -des3 -out private/clientkey.pem 1024
    
  • Tworzenie wniosek o wystawienie certyfikatu poleceniem:
    # openssl req -new -key private/clientkey.pem -out clientreq.pem
    

    Jesteśmy pytani o hasło do klucza prywatnego oraz o informacje, które będą potem zawarte w certyfikacie:

    Country Name (2 letter code) [AU]:PL
    State or Province Name (full name) [Some-State]:Dolnośląskie
    Locality Name (eg, city) []:Wrocław
    Organization Name (eg, company) [Internet Widgits Pty Ltd]:Kogucik sp. z o.o.
    Organizational Unit Name (eg, section) []:
    Common Name (eg, YOUR name) []:firmakogucik.com.pl
    Email Address []:
    
    Please enter the following 'extra' attributes
    to be sent with your certificate request
    A challenge password []:
    An optional company name []:
    

    W tym miejscu możem nasze żądanie obejrzeć poleceniem:

    # openssl req -in clientreq.pem -text -noout
    
  • Ostatni krok to utworzenie certyfikatu przez CA:
    # openssl ca -notext -in clientreq.pem -out clientcert.pem
    

    Uwaga: podczas tworzenia certyfikatu będziemy proszeni o hasło do klucza prywatnego CA.

  • (opcjonalnie) Jeśli certyfikat z kluczem prywatnym ma być wykorzystywany przez usługę (np. vpn lub serwer www), wygodnie jest ściągnąć hasło z klucza prywatnego:
    # openssl rsa -in private/clientkey.pem -out private/clientkey.pem.passless
    

Kilka innych zastosowań openssl-a, niekoniecznie związanych z PKI:

  • Obliczanie funkcji skrótu:
    # openssl dgst -sha256 plik.txt
    # openssl dgst -sha512 -out skrot.txt -hex -c plik.txt
    
  • Szyfrowanie symetryczne:
    # openssl enc -des3 -in plik.txt -out zaszyfrowane.bin
    
  • Szyfrowanie asymetryczne:
    # openssl genrsa -out key.pem -des3 1024
    # openssl rsautl -encrypt -inkey key.pem -in plik.txt -out zaszyfrowane.bin
    
    Dokładniej: wygenerowanie klucza do szyfrowania, a następnie zaszyfrowanie za jego pomocą asymetrycznie plik.txt.

Na koniec kwestia wygody związanej przy przekazywaniu haseł. Domyślnie, polecenie openssl pyta zawsze o hasło w sposób interaktywny. Z pewnością jest to bezpieczne, ale bardzo niewygodne przy generowaniu, np. 100 kluczy. Żeby sobie ułatwić życie mamy do dyspozycji dwie opcje:

  • -passin — gdy chcemy użyć czegoś zablokowanego hasłem oraz
  • -passout — gdy podajemy hasło w celu zabezpieczenia czegoś.

Dodatkowo podajemy parametr określający jak hasło będzie przekazane:

  • stdin — hasło zostanie przekazane z pliku za pomocą przekierowania <
  • pass:hasło — jawne przekazanie hasła
  • env:ZMIENNA — hasło będzie pobrane zmiennej o wskazanej nazwie
  • file:nazwapliku — hasło zostanie odczytane z pliku o podanej nazwie

Kilka przykładów:

# openssl genrsa –out key.pem –passout stdin –des3 1024 < pass.txt
# openssl genrsa –out key.pem –passout pass:xyz –des3 1024
# openssl rsa –in key.pem –passin env:SSL_PASS –pubout
# openssl rsa –in key.pem –passin file:pass.txt –pubout

Literatura