OpCode.eu.org

Blog O autorze O serwisie
2020-06-25

Szyfrowanie, podpisywanie, sumy kontrolne, hasła, …

Funkcje haszujące (funkcje skrótu)

Są to funkcje które przyporządkowują dowolnym danym (np. treści pliku) liczbę o stałej długości, w taki sposób że dla tych samych danych liczba ta ma zawszą tą samą wartość. Funkcje takie znajdują zastosowanie m.in. w:

W zastosowaniach kryptograficznych od funkcji skrótu na ogół wymagana jest: * odporność na kolizje, przynajmniej dla konkretnych wiadomości – czyli brak możliwości wygenerowania wiadomości o podanej wartości funkcji skrótu * jednokierunkowość – czyli brak możliwości wnioskowania o wiadomości na podstawie jej skrótu

sumy kontrolne

Obliczanie (i porównywanie) sum kontrolnych danych (np. plików) pozwala na wykrywanie ich modyfikacji (zarówno celowych jak i przypadkowych). Pakiet coreutils dostarcza wielu narzędzi służących obliczaniu różnego rodzaju sum kontrolnych – są to m.in. md5sum, sha1sum, sha224sum, sha256sum, sha384sum, sha512sum, b2sum Należy pamiętać że ze względu na znalezione kolizje funkcje MD5 (md5sum) i SHA1 (sha1sum) nie powinny być używane w celu zabezpieczania przed celową modyfikacją danych.

hasła

Typowo hasła użytkowników systemie Linux przechowywane są w postaci zahaszowanej w pliku /etc/shadow. Każdy wiersz w tym pliku odpowiada pojedynczemu użytkownikowi a dane zapisane są w układzie kolumnowym rozdzielanym przy pomocy : – w pierwszym polu podana jest nazwa użytkownika, w drugim skrót jego hasła, itd. Linia tego pliku może wyglądać np. następująco:

root:$1$ABC$OKsUVOcxgVs5LZ4Vro0oM:15289:0:99999:7:::

Pole z hasłem jest postaci $1$ABC$OKsUVOcxgVs5LZ4Vro0oM i oznacza że użyto algorytmu haszującego nr. 1 (czyli md5), solą (czyli losowymi danymi dodanymi do hasła przez obliczeniem skrótu) było ABC a hash hasła z solą wynosi OKsUVOcxgVs5LZ4Vro0oM. Szczegóły oraz wykaz obsługiwanych funkcji skrótu wraz z ich numerami można znaleźć w man 3 crypt.

Do wygenerowania poprawnej zawartości pola z hasłem można użyć polecenia perlowego:

perl -e 'print crypt("HASLO", "\$6\$SALT");'

Jeżeli chcemy uzyskać losowy SALT możemy skorzystać np. z programu pwgen generującego losowe hasła w połączeniu z powyższą komendą:

perl -e 'print crypt("HASLO", "\$6\$'`pwgen 8 1`'");'

W przypadku pliku shadow hashowanie hasła służy utrudnieniu odgadnięcia hasła w przypadku podejrzenia tego pliku. Innym przypadkiem użycia funkcji skrótu do zabezpieczania hasła jest autoryzacja HTTP Digest, gdzie pomiędzy klientem a serwerem przesyłany jest hash hasła połączonego z informacjami dotyczącymi danej sesji.

Szyfrowanie i podpisywanie

Kryptografia klucza publicznego pozwala zarówno na szyfrowanie danych (zabezpieczanie ich przed nieuprawnionym odczytem), jak też podpisywanie ich cyfrowo (potwierdzenie autentyczności)

Dzięki zastosowaniu dwóch kluczy (publicznego i prywatnego) rozwiązuje ona problem wymiany kluczy szyfrujących pomiędzy stronami.

szyfrowanie

W przypadku szyfrowania odbiorca poufnych wiadomości generuje parę kluczy. Klucz prywatny zachowuje tylko do swojej wiadomości, a klucz publiczny ujawnia wszystkim. Nadawca chcący wysłać do niego poufną wiadomość szyfruje ją przy pomocy powszechnie znanego klucza publicznego (który jednocześnie nie pozwala na jej odszyfrowanie) i przesyła zaszyfrowaną wiadomość do odbiorcy. Odbiorca jest wstanie zdeszyfrować ją za pomocą swojego klucza prywatnego (którego nikt poza nim nie musi i nie powinien znać).

podpisywanie

Podpisy cyfrowe opierają się również na szyfrowaniu. Następuje tutaj jednak zamiana funkcji pełnionych przez klucze prywatny i publiczny – do zaszyfrowania używany jest (poufny) klucz prywatny a do deszyfracji (powszechnie znany) klucz publiczny.

Ze względu na fakt, iż (pomijając ew. kompresję) szyfrogram jest nie krótszy od oryginalnej wiadomości, zamiast szyfrowania podpisywanych danych szyfruje się ich funkcję strutu taka jak np. SHA512.

Podpisanie danych polega na obliczeniu ich sumy kontrolnej i zaszyfrowaniu jej (wraz z ew. dodatkowymi danymi jak data podpisu) przy pomocy klucza prywatnego. Jako że podpisane dane nie mogą być modyfikowane (gdyż unieważniłoby to podpis poprzez zmianę wartości sumy kontrolnej) podpis załącza się w osobnym pliku lub używa się kontenera który przechowuje w jakiejś strukturze (w ramach pojedynczego pliku) niezmienione podpisane dane i złożony podpis (jednak wtedy nie jest podpisywany cały plik z taką strukturą a jedynie jego odpowiednia część).

Potwierdzenie autentyczności podpisu opiera się na:

W zależności od stosowanego rozwiązania możliwe jest używanie tej samej pary kluczy do podpisu i szyfrowania (gdy każdy z kluczy może być użyty zarówno do zaszyfrowania jak i odszyfrowania wiadomości dla drugiego klucza z pary, np. RSA) lub mogą wymagać osobnych par kluczy do szyfrowania i podpisu (np. ElGamal). Istnieją też systemy dedykowane tylko podpisom (np. DSA).

klucze a certyfikaty

Wspomniana kwestia zaufania, że klucz X faktycznie reprezentuję osobę/insttycję Y (został przez nią wydany), jest chyba obecnie największą słabością kryptografi klucza publicznego. Generalnie istnieją dwa podejścia do tej kwesti

system kluczy (OpenPGP, SSH) i sieci zaufania

Decyzja o zaufaniu do poszczególnych kluczy leży całkowicie po stronie użytkownika i zaufanie to jest określane zasadniczo per klucz.

Najprostszym przykładem takiego podejścia może być SSH, gdzie .ssh/known_hosts jest listą kluczy publicznych serwerów ssh, którym ufa nasz klient, a .ssh/authorized_keys jest listą kluczy publicznych klientów którym ufa nasz serwer.

Podobnie jest w przypadku GnuPG, gdzie importując klucz określamy poziom zaufania dla tego klucza. Tutaj jednak system jest bardziej rozbudowany – klucze mogą być podpisywane przy pomocy innych kluczy (tworząc sieć zaufania) i poziom ten ma wpływ na automatycznie ustalany poziom kluczy podpisanych takim kluczem.

system certyfikatów (x509)

System certyfikatów w standardzie X.509 oparty jest na hierachicznym zaufaniu do urzędów certyfikujących (CA). Każdy system ufa pewnym urzędom certyfikacyjnym (root CA). W przypadku Debiana ich lista jest ustalana w pliku /etc/ca-certificates.conf, a ich certyfikaty dostarczane są w pakiecie ca-certificates (więcej informacji w /usr/share/doc/ca-certificates/README.Debian). System z automatu ufa także (w zakresie określonym w podpisanych certyfikatach) wszystkim certyfikatom podpisanym przez te root CA oraz kolejnym podpisanym przez tamte, itd.

W oparciu o certyfikaty X.509 i związaną z nimi hierarchię zaufania działa standard SSL/TLS, czyli w szczególności szyfrowanie i weryfikacja pochodzenia stron WWW w protokole HTTPS.

Narzędzia i przydatne polecenia

SSH

Narzędziem służącym do generowania kluczy SSH i operowania na nich jest ssh-keygen. W przypadku SSH z pliku klucza prywatnego możliwe jest wyeksportowanie klucza publiczny poprzez ssh-keygen -y -f $KLUCZ_PRYWATNY.

Warto także wspomnieć że SSH pozwala również na używanie kluczy nie tylko w oparciu o dodanie ich do odpowiednich plików, ale także ze względu na fakt ich podpisania certyfikatem CA (który jest wskazany w konfiguracji serwera) – klient do serwera zamiast klucza publicznego przesyła certyfikat zawierający ten klucz i podpis CA, a serwer ufa kluczom podpisanym swoim CA (podobnie klient ufa serwerom których klucz publiczny jest podpisany CA wskaznym w konfiguracji klienta).

OpenPGP / GnuPG

W wszystkich poniższych przykładach IDENDYFIKATOR określa klucz do edycji, może to być adres e-mail podany w tym kluczu, pełna nazwa, itd.

zarządzanie kluczami

szyfrowanie

podpisy

poczta elektroniczna

OpenPGP może zostać użyty do szyfrowania i/lub podpisywania poczty elektronicznej na dwa sposoby – jako PGP Inline lub jako PGP/MIME.

Pierwszy z nich odpowiada umieszczeniu w tekstowej treści maila wyniku polecenia gpg -u 'IDENDYFIKATOR' --armor --clear-sig - (w przypadku podpisu) lub gpg --armor --encrypt --recipient IDENDYFIKATOR - (w przypadku szyfrowania) do którego przekazana została treść maila.

Drugi odpowiada utworzeniu maila złożonego z kilku części zgodnie ze standardem MIME. W przypadku podpisu będzie to Content-Type: multipart/signed; protocol="application/pgp-signature" zawierający podpisaną wiadomość np. jako Content-Type: text/plain; i podpis (w formacie tekstowym asc) jako Content-Type: application/pgp-signature. W przypadku zaszyfrowania wiadomości będzie to Content-Type: multipart/encrypted; protocol="application/pgp-encrypted" zawierający zaszyfrowaną wiadomość (w formacie tekstowym asc) jako Content-Type: application/octet-stream i sekcję Content-Type: application/pgp-encrypted określającą wersję.

certyfikaty x509

Istnieje kilka dróg generowania certyfikatów i kluczy tego typu. Możemy to zrobić np. w następujący sposób:

openssl req -new -x509 -days 4095 -newkey rsa:4096 -keyout ca_key.pem -out ca_cert.pem -nodes -subj "/C=EU/L=Warsaw/O=Example Organization For Example Cert/CN=example.org/CN=*.example.com"

Wygenerowany zostanie certyfikat podpisany przez samego siebie (opcja -x509), klucz prywatny nie byłby zabezpieczony hasłem (opcja -nodes, jest to przydatne przy generowaniu certyfikatów dla serwerów usług). W przypadku generowania certyfikatów dla serwerów usług w Common Name (CN) podajemy wszystkie obsługiwane domeny, ponadto możemy użyć tam *.domena aby certyfikat obsługiwał wszystkie poddomeny.

Wygenerowany w sposób opisany powyżej zestaw certyfikatu i klucza możemy używać od razu do szyfrowania bądź do podpisywania próśb o certyfikat generowanych komendą:

openssl req -new -keyout server.key -out server.key

Prośbę taką możemy przekazać do podpisu jakiemuś prawdziwemu CA lub podpisać sobie sami (wygenerowanym wcześniej kluczem):

openssl x509 -req -out server.crt -in server.key -CA ca_cert.pem -CAkey ca_key.pem -CAcreateserial -days 365.

Na koniec możemy usunąć hasło z klucza prywatnego (przydatne dla serwerów):

openssl rsa -in server.key -out server.key.

Na potrzeby wielu programów konieczne będzie wyeksportowanie zestawu klucza i certyfikatu do formatu PKCS#12:

openssl pkcs12 -export -in cert1_cert.pem -inkey cert1_key.pem -out cert1.p12.

Klucz taki możemy zaimportować np. do gpgsm, co pozwoli to na włączenie funkcjonalności S/MIME w programach pocztowych:

gpgsm --import cert1.p12

Samodzielne generowanie kluczy i certyfikatów x509 (np. na potrzeby OpenVPN, który używa właśnie tego rodzaju certyfikatów) może ułatwić narzędzie easy-rsa.

Zaufane (podpisane przez CA znajdujące się standardowo na liście zaufanych CA, a nie samo-podpisane) certyfikaty dla naszych serwerów można uzyskać za darmo dzięki np. Let's Encrypt przy pomocy pakietu certbot.

Tagi: debian kryptografia