Amikor titkosításról és biztonságról beszélünk, meg kell különböztetnünk a különféle eseteket, amelyek ellen védekezni szeretnénk, pl.:
- Véletlen, nem szándékos meghibásodás ellen
- Szándékos rongálás ellen
- Hamisítás ellen
- Illetéktelen hozzáféréssel szemben
- stb.
Az esettől függően különféle eszközök állnak a rendelkezésünkre.
A történetünknek legyen három szereplője:
- Alice: szeretne egy titkos üzenetet küldeni Bobnak
- Bob: az üzenet fogadója
- Eve: szeretné az üzenetet útközben megszerezni, elolvasni, és ha tudja, akár meg is hamisítani.
A probléma
Alice és Bob között a kapcsolat sajnos nem megbízható. Nem tudhatjuk, hogy épp ki hallgatja a telefonbeszélgetésüket, nem néznek-e bele az email-ekbe, a chat-ekbe.
Alice-nak és Bob-nak csak a saját eszközeikre (telefon, számítógép) van ráhatása.
- Telefonos beszélgetés:
- A rádióhullámokat bárki befoghatja
- Az adótornyokat a telefon-szolgáltató üzemelteti, ott összegyűjthetnek minden beszélgetést/SMS-t
- Internetes chat:
- Wifi-t befoghatja mindenki a közelben
- Az internetszolgáltató lát minden elküldött adatcsomagot
- Városok, országok közti kommunikáció esetében több szolgáltatón is keresztül megy minden adat
- Posta
- A postások bármelyik levélet kibonthatják
- A helyi postán minden helyi levél átfut
Ha csak egy láncszem is gyenge a fentiek közül, akkor Eve könnyedén meg tudja szerezni az üzenetet, pl. a postás lefizetésével.
Amikor biztonságról beszélünk, akkor két alapvető kritériumot kell teljesítenünk:
- A rendszernek akkor is biztonságosnak kell maradnia, ha az alatta élvő kommunikációs csatorna nem az: a postás minden levelet elolvas, a szolgáltató megvizsgál minden adatcsomagot stb.
- A rendszernek akkor is biztonságosnak kell maradnia, ha a támadó ismeri titkosítási algoritmust: a titkolózáson alapuló biztonság (security through obscurity) valójában nem biztonság, csak annak a látszatát kelti.
Hagyományos egykulcsos/szimmetrikus (jelszavas) titkosítás
Az ilyen jellegű titkosítási algoritmusokat azért nevezzük szimmetrikusnak, mert a titkosítási kulcs kell az üzenet visszafejtéséhez.
Az egyik legrégebb óta ismert titkosítási forma az ún. Caesar-kód, amelyben az üzenet betűit N darab karakterrel odébb toljuk (Z esetén az A betűtől indulunk újra).
Pl. ha N=3
Eredeti: HELLO Titkosított: KHOOR
Ebben az esetben, még ha Eve útközben megkaparintja a levelet, abban annyi fog szerepelni, hogy KHOOR, amely nem értelmes. Viszont ha Bob kézhez kapja a levelet, ő tudni fogja, hogy a betűk 3-mal el lettek tolva. Ha a műveletet elvégzi visszafelé (az ABC másik irányába tolja el a betűket 3-mal), akkor visszakapja az eredeti üzenetet.
Ez a konkrét algoritmus az ókorban még működhetett, ma már azoban az ilyen egyszerű, behelyettesítésen alapuló algoritmusokat nagyon könnyű visszafejteni. A ma használt szimmetrikus algoritmusok ennél összetettebbek, hogy a visszafejtést megelőzzék.
A szimmetrikus algoritmusok gyengéje, hogy a titkos kulcsot először valahogyan el kell juttatni Bobhoz. Ha Bob nem tudja, hogy 3-mal kell a betűket eltolni, ő sem fogja tudni elolvasni az üzenetet. Ha a titkos kulcsot Alice elküldi Bob-nak, azt Eve lehallgathatja, ami után már ő is el tudja olvasni az üzeneteket.
A leggyakrabban használt és ajánlott algoritmus: AES
Fontos! A szoftverfejlesztői OKJ tételek közt szerepel a DES/3DES algoritmus. Ezek mai szemmel már gyengék, elavultnak számítanak, új alkalmazásban ne használjuk őket!
Kétkulcsos/aszimmetrikus titkosítás
Tegyük fel, hogy Alice és Bob nem tudnak egy titkos kódban megegyezni előre, mégis szeretnének üzenetet váltani, lehallgatás nélkül.
Először is nézzünk egy kis gondolkodtató, találós kérdést. Alice-nak van egy doboza, amire rátehet egy lakatot. Ekkor nem tud más belenézni. De ha Bob megkapja a lezárt dobozt, ő sem tudja kinyitni.
Mi a megoldás?
Segítség: az alfejezet címe.
- Alice lezárja a dobozt, és elküldi Bobnak
- Bob megkapja a lezárt doboz, amit nem tud kinyitni, ezért ő is rátesz egy lakatot, majd visszaküldi Alice-nak
- Most útközben már két lakat is van rajta
- Alice leveszi a saját lakatját. Ő már nem tudja kinyitni, mert Bob lakatja rajta van
- Ismét elküldi Bobnak, aki most már a saját kulcsával ki tudja nyitni a dobozt
A módszer lényege, hogy egy időpillanatban sem volt olyan, hogy a doboz lakat nélkül utazott volna, és a kulcs sem hagyta el a tulajdonosait.
Eve persze használhatott volna erőt is, pl. levágja magát a lakatot, vagy darabokra szedi magát a dobozt - a gyakorlatban nem lesz használható. Ettől függetlenül ez a találós kérdés rávilágít arra, hogy nem muszáj megosztani a kulcsokat/jelszavakat a titkosításhoz, létezhet megoldás.
Az üzenet titkosítása
Az algoritmus nem egy titkosítási kulcsot használ, hanem egy ún. összetartozó kulcspárt:
- K1
- K2
Amit K1-gyel titkosítottunk, azt csak K2-vel lehet visszafejteni, és viszont: amit K2-vel titkosítottunk, azt csak K1-gyel lehet visszafejteni:
Eredeti üzenet → K1 → titkos → K2 → Eredeti üzenet
vagy
Eredeti üzenet → K2 → titkos → K1 → Eredeti üzenet
Ezt a tulajdonságát felhasználhatjuk a fenti probléma megoldására:
- Nevezzük ki K1-et publikus kulcsnak, és osszuk meg mindenkivel
- Legyen K2 privát kulcs, és tartsuk titokban, magunknál.
Ennek két haszna is lesz:
Publikus kulcsú titkosítás
Az alaphelyzet megint ugyanez: Alice megint üzenetet akar küldeni Bobnak, de most az interneten keresztül, így nincs fizikai doboz, amibe elrejthetné az üzenetet.
Viszont ismeri Bob publikus kulcsát.
- Alice titkosítja az üzenetét Bob publikus kulcsával
- Eve el tudja olvasni a titkosított üzenetet, de mivel nem tudja Bob privát kulcsát, nem tudja értelmezni
- Bob vissza tudja fejteni a saját kulcsával
Digitális aláírás
Mivel Eve-nek most már nincs lehetősége a leveleket elolvasni, más támadási formák után néz. Az alábbi üzenetet írja:
Kedves Bob!
Tudod, milyen jó barátok vagyunk, és segítünk egymásnak a bajban. Sajnos anyagilag megszorultam egy kissé. Ki tudnál segíteni egy kis összeggel? Erre a számlaszámra küldd légyszi: XXX-YYY-ZZZ
Köszi,
Alice
Bob honnan fogja tudni, hogy az üzenetet tényleg Alice küldte?
A kétkulcsú titkosítás ezt is meg tudja oldani.
Ha Alice egy hiteles üzenetet szeretne küldeni, akkor először titkosítja a saját privát kulcsával. De ennek mi értelme? A publikus kulcsot mindenki ismeri, bárki elolvashatja az üzenetet, nem?
A cél nem is ez. Ha valakinek sikerült visszafejteni az üzenetet Alice publikus kulcsával, akkor az üzenet csak tőle származhat: mert más nem tudta volna így titkosítani. Épp ezért ezt nem is titkosításnak szokták nevezni, hanem digitális aláírásnak.
Mivel Eve nem ismeri Alice privát kulcsát, ezért nem tud az ő nevében üzenetet küldeni.
A kettő együtt
Tehát ha Alice szeretne egy üzenet küldeni Bobnak, amit Eve se elolvasni, se meghamisítani nem tud, az alábbiakat kell tennie:
Eredeti üzenet → Alice privát kulcsa → Aláírt üzenet → Bob publikus kulcsa → Aláírt és titkosított üzenet
Bob pedig ezeket a lépéseket fogja végrehajtani:
Aláírt és titkosított üzenet → Bob privát kulcsa → Aláírt üzenet
Szóval az üzenet nekem szólt, más nem olvashatta el!
Aláírt üzenet → Alice publikus kulcsa → Eredeti üzenet
Szóval ez tényleg Alice-tól jött!
A lépéseket természetesen szoftver végzi, így történik a kommunikáció pl. a webszerver és a böngésző között (HTTPS), de pl. PGP segítségével tetszőleges dokumentumra, emailre is alkalmazható.
RSA, DSA
A két leggyakrabban használt algoritmus. A böngészőben, a lakat ikonra kattintva megnézhetjük, hogy ez az oldal is RSA titkosítást használ.
Saját kulcspárt generálhatunk pl. OpenSSH segítségével. Ha szeretnénk egy 4096 bites, RSA kulcsot:
ssh-keygen -t rsa -b 4096
Ha alapértelmezett fájlnéven hagyjuk, akkor két fájlt generál a “~/.ssh” mappában:
- id_rsa: ez a privát kulcs
- id_rsa.pub: ez a publikus kulcs
Windows alatt egy grafikus alkalmazás a PuTTY ssh klienshez mellékelt puttygen.exe, amivel szintén lehet kulcspárokat generálni.
Egyirányú titkosítás
Bizonyos szituációkban nem fontos, hogy a titkosítás visszafordítható legyen. Ilyen eset pl. a jelszavak tárolása. Ha van módszerünk a jelszavak egyezésének az ellenőrzésére, akkor a visszafejtésre nem is kell, hogy létezzen módszer. Sőt, ez biztonsági hibának számítana!
Azokat az algoritmusokat, amik erre alkalmasak, kriptográfiai hash függvényeknek nevezzük.
Emlékeztetőül, a hash függvény:
- Egyirányú, a hash-ből nem lehet visszaszerezni az eredeti adatot
- Fix intervallumra vetíti le az eredeti adatot, így nem derül ki, hogy az eredeti 1 bájt vagy 1 gigagbájt volt: a bcrypt eredménye mindig 184 bites lesz.
Nem minden hash függvény alkalmas jelszavak tárolására. A CRC32-t például véletlen hibák ellen találták ki, nagyon egyszerű kulcsütközést generálni.
A jelszó helyességének az ellenőrzéséhez az adatbázisban eltárolt jelszót nem kell visszafejteni, hanem elég a felhasználó begépelt jelszavát hash-elni. Ha a most kiszámolt, és az adatbázisban tárolt hash megegyezik, akkor a user eltalálta a jelszót.
Ha valaki pedig megszerezné az adatbázisban tárolt hash-eket, akkor nem menne velük sokra: a hash-ekből nem lehet visszaszerezni az eredeti jelszót.
Salt
A jelszót titkosítás előtt meg is “sózhatjuk”, ezt azt jelenti, hogy egy kis méretű, véletlenszerű adatot hozzáfűzünk. Ennek az a célja, hogy ha a rendszerben két user véletlenül ugyanazt a jelszót választja, ez ne derüljön ki a hash-ek egyezéséből.
Salt nélkül:
- User1:
- hash(jelszo1) = asdf1234
- User2:
- hash(jelszo1) = asdf1234
Viszont ha a jelszavakat megsózzuk:
- User1
- salt = ab
- hash(jelszo1ab) = a1223445
- User2
- salt = cd
- hash(jelszo1cd) = 89as5zb5
Ugyanaz a jelszó, de a hash különbözik.
PHP példakód
Regisztrációkor:
// Hash kiszámítása, ezt fogjuk az adatbázisba tenni
$db_hash = password_hash($_POST['password'], PASSWORD_DEFAULT);
Bejelentkezéskor:
$db_hash = ... // Ezt olvassuk ki az adatbázisból
if (password_verify($_POST['password'], $db_hash)) {
// Sikeres login
$_SESSION['user_id'] = $user_id;
} else {
$error_message = 'Sikertelen login';
}
Javasolt kriptográfiai hash algoritmusok:
- bcrypt (PHP alapértelmezett)
- Argon2 (PHP beépített):
- password_hash($pw, PASSWORD_ARGON2I);
- PBKDF2 + SHA-512
Ellenjavalt algoritmusok:
- MD5, SHA1
- bármilyen algoritmus, amit nem lehet paraméterezni az iterációk számával