x509 tanúsítványok és mTLS: elmélet és gyakorlat OpenSSL-lel

Szimmetrikus és aszimmetrikus titkosítás, aláírás, hitelesítésszolgáltató, bizalmi lánc: az alapok az x509 tanúsítványok megértéséhez. Utána gyakorlat OpenSSL-lel: saját CA létrehozása, szerver- és klienstanúsítványok aláírása, és egy mTLS kapcsolat felépítése.

Bevezetés

Ezt a kurzust 2023 áprilisában gyakorlati óraként tartottam, a korábbi blogomon tárolt reveal.js diákkal. Most cikk formájában hozom vissza, frissítve, az eredeti diák pedig a cikk végén továbbra is elérhetők.

A cél: megérteni, mi az az x509 tanúsítvány és mi a hitelesítésszolgáltató (CA), saját tanúsítványokat generálni OpenSSL-lel, és felépíteni egy mTLS (kölcsönös TLS) kapcsolatot, ahol a kliens is tanúsítvánnyal azonosítja magát.

SSL vagy TLS?

Még mindig hallani „SSL tanúsítványról”, pedig az SSL és a TLS protokollok, nem tanúsítványok. A protokollok használnak tanúsítványokat.

Az SSL már régóta elavult: ma TLS-t használunk, és a francia kiberbiztonsági ügynökség, az ANSSI csak a TLS 1.2 és TLS 1.3 használatát javasolja. Az eladók történelmi okokból hívják még „SSL tanúsítványnak”: a nevet megtartották, hogy ne zavarják össze az ügyfeleket.

Kriptográfiai alapok

Szimmetrikus vs aszimmetrikus

Szimmetrikus titkosításnál Alice és Bob ugyanazt a titkos kulcsot használja a titkosításhoz és a visszafejtéshez. Gyors, nagy adatmennyiséghez ideális, de a kulcsot biztonságosan kell kicserélni.

Aszimmetrikus titkosításnál mindenkinek van egy kulcspárja:

  • egy nyilvános kulcs, amelyet bárkivel meg lehet osztani;
  • egy privát kulcs, amely soha nem hagyhatja el a tulajdonosát.

A mai tudásunk szerint a nyilvános kulcsból nem lehet visszaállítani a privát kulcsot. Ebből két felhasználás következik:

  • Titkosítás: Alice bizalmas üzenetet akar küldeni Bobnak, ezért Bob nyilvános kulcsával titkosítja. Csak Bob tudja elolvasni a saját privát kulcsával.
  • Aláírás: Alice a saját privát kulcsával írja alá az üzenetet. Bárki ellenőrizheti az aláírást Alice nyilvános kulcsával, így biztos lehet benne, hogy az üzenet tőle jön, és nem módosították.

Hash függvények

A hash függvény tetszőleges méretű adatból fix méretű lenyomatot készít (például SHA-256). Soha nem a teljes dokumentumot írjuk alá, hanem a lenyomatát.

Titkosítási csomagok (cipher suite)

Három eszközcsaládunk van tehát: a szimmetrikus a nagy adatmennyiség titkosításához, az aszimmetrikus a kulcscseréhez és a hitelesítéshez, a hash pedig az integritáshoz. Egy TLS kapcsolat mindhármat kombinálja, ezt a kombinációt cipher suite-nak hívjuk.

TLS 1.2 példa: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256

  • Kulcscsere: ECDHE
  • Hitelesítés: RSA
  • Titkosítás: AES 128, GCM módban
  • Hash: SHA-256

TLS 1.3-ban a csomagok egyszerűbbek (TLS_AES_128_GCM_SHA256): a kulcscsere mindig efemer, és külön kerül egyeztetésre. A csomagok felfedezéséhez és biztonságuk ellenőrzéséhez: ciphersuite.info.

Az x509 tanúsítvány

Egy X.509 tanúsítvány digitális aláírással köt össze egy identitást egy nyilvános kulccsal. Tartalmaz egy identitást (hosztnév, szervezet vagy személy) és egy nyilvános kulcsot, és vagy egy hitelesítésszolgáltató írja alá, vagy önaláírt.

A gyakorlatban egy tanúsítvány tartalmazza: az alanyt (CN, O…), a kibocsátót, az érvényességi időt, a nyilvános kulcsot, a kiterjesztéseket (engedélyezett felhasználások, alternatív nevek…) és a kibocsátó aláírását.

A hitelesítésszolgáltató (CA)

A CA garantálja a nyilvános kulcs és a tulajdonosa közötti kapcsolatot azzal, hogy a saját privát kulcsával aláírja a tanúsítványt. Ezt az aláírást bárki ellenőrizheti a CA nyilvános kulcsával. Ez egy PKI alapja.

A tanúsítványlánc

Az operációs rendszer és a böngésző egy tanúsítványtárat tartalmaz a megbízható gyökér CA-kkal. Egy gyökér CA köztes CA-kat ír alá, amelyek aztán a weboldalak tanúsítványait írják alá. Egy tanúsítvány ellenőrzésekor a láncon felfelé haladunk egy ismert gyökérig.

1. gyakorlat: saját CA és tanúsítványok aláírása

Mindent az openssl paranccsal végzünk, egy munkakönyvtárban.

A CA

Generáljuk a CA privát kulcsát, majd az önaláírt tanúsítványát:

openssl genrsa -out ca.key 4096

openssl req -x509 -new -key ca.key -sha256 -days 3650 \
  -subj "/CN=Ilogus Lab CA" \
  -out ca.crt

A tanúsítvány megtekintése:

openssl x509 -in ca.crt -noout -text

A szervertanúsítvány

A szerver legenerálja a kulcsát és egy CSR-t (Certificate Signing Request): egy kérelmet, amely tartalmazza a nyilvános kulcsát és az identitását, és amelyet a CA-nak kell aláírnia.

openssl req -newkey rsa:2048 -nodes \
  -keyout server.key \
  -subj "/CN=localhost" \
  -out server.csr

A tanúsítvány felhasználási módjait kiterjesztések határozzák meg. Ahelyett, hogy az eredeti diákhoz hasonlóan a teljes openssl.cnf-et lemásolnánk, elég egy kis server.ext fájl:

basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = DNS:localhost, IP:127.0.0.1

A subjectAltName kötelező: a böngészők és a legtöbb kliens figyelmen kívül hagyja a CN-t, és csak az alternatív neveket ellenőrzi.

A CA aláírja a CSR-t:

openssl x509 -req -in server.csr \
  -CA ca.crt -CAkey ca.key -CAcreateserial \
  -days 365 -sha256 -extfile server.ext \
  -out server.crt

A klienstanúsítvány

Ugyanez az elv, egy client.ext fájllal, amely engedélyezi a kliens hitelesítést (és az e-mailek aláírását):

basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection
openssl req -newkey rsa:2048 -nodes \
  -keyout client.key \
  -subj "/CN=alice" \
  -out client.csr

openssl x509 -req -in client.csr \
  -CA ca.crt -CAkey ca.key -CAcreateserial \
  -days 365 -sha256 -extfile client.ext \
  -out client.crt

Ellenőrizzük, hogy mindent a CA-nk írt alá:

openssl verify -CAfile ca.crt server.crt client.crt

2. gyakorlat: mTLS kapcsolat

Hagyományos TLS-nél csak a szerver mutat be tanúsítványt. mTLS-nél a szerver a klienstől is tanúsítványt kér, amelyet egy általa ismert CA írt alá. Szolgáltatások között gyakran használják (belső API-k, IoT, adminisztrációs hozzáférés).

Indítsunk egy tesztszervert, amely megköveteli a klienstanúsítványt:

openssl s_server -accept 8443 \
  -cert server.crt -key server.key \
  -CAfile ca.crt -Verify 1 -www

Klienstanúsítvány nélkül a kézfogás sikertelen:

curl --cacert ca.crt https://localhost:8443/

A klienstanúsítvánnyal a kapcsolat létrejön, és a szerver visszaküldi a TLS munkamenet részleteit:

curl --cacert ca.crt --cert client.crt --key client.key https://localhost:8443/

Éles környezetben Nginx-szel ugyanez az elv:

ssl_client_certificate /etc/nginx/mtls/ca.crt;
ssl_verify_client on;

Az eredeti órán ugyanezt Postmannel csináltuk (Settings → Certificates), és Wiresharkban figyeltük a kézfogást, összehasonlítva a TLS verziókat. Remek gyakorlat ahhoz, hogy lássuk a tanúsítványok útját.

Továbblépés: Extended Key Usage

A keyUsage és az extendedKeyUsage kiterjesztések korlátozzák, mire használható a kulcs: egy serverAuth tanúsítvány ne tudjon klienst hitelesíteni, és fordítva. Ezt csináltuk a .ext fájlokkal.

A klienstanúsítvány böngészőbe vagy levelezőkliensbe (S/MIME aláírás) importálásához egy PKCS#12 fájlba csomagoljuk a kulcsot és a tanúsítványt:

openssl pkcs12 -export -out client.p12 \
  -inkey client.key -in client.crt -certfile ca.crt

A kurzus diái

Íme a kurzus eredeti diái (angolul). A nyilakkal vagy a szóközzel navigálhatsz, vagy megnyithatod teljes képernyőn.

Kattints a diákba, majd használd a nyílbillentyűket · Megnyitás teljes képernyőn ↗

Összegzés

Egy x509 tanúsítvány egy nyilvános kulcs, egy identitás és az őket összekötő aláírás. Ha ez az elv megvan, a CA, a bizalmi lánc és az mTLS már elég természetesnek tűnik. OpenSSL-lel és néhány .ext fájllal mindenünk megvan egy teljes helyi tesztkörnyezethez.