Píšete o kryptovací funkci, ale myslíte funkci crypt() na unixových systémech (která je dostupná třeba i v PHP). Funkce crypt() ale není hashovací funkce, pouze hashování interně používá.
Funguje tak, že vezme heslo (nebo jeho část) a sůl (resp. její část), vytvoří hash, spojí sůl s hashem a to vrátí jako výsledek. Když pak chcete heslo ověřit, vezmete sůl z výsledku (ve skutečnosti můžete použít celý výsledek, protože se automaticky použije jenom část představující sůl) a heslo zadané uživatelem, znovu proženete funkcí crypt() a porovnáte s předchozím výsledkem. Pro stejnou sůl a stejné heslo musí ta funkce logicky dávat vždy stejný výsledek, jinak byste heslo nikdy neověřil. Pokud při prvním spuštění nezadáte žádnou sůl, funkce crypt() vygeneruje nějakou náhodnou. Díky tomu, že je sůl součástí výsledku, můžete příště heslo ověřit i s touto náhodnou solí.
Jinak výše uvedený popis platí pro standardní unixový crypt() s algoritmem DES, pro jiné implementace to může fungovat trochu jinak.
Hash není jednosměrné šifrování – pro šifrování je potřeba právě to, aby bylo možné zašifrovaný text rozšifrovat. Hash dělá něco jiného – libovolně velké číslo převede na číslo v zadaném intervalu. Je jasné, že existuje nekonečné množství čísel, která vedou na stejný hash – od hashovací funkce se ale vyžaduje, aby bylo současnými technickými prostředky nemožné najít dvě různá čísla, která budou mít hash.
Vytvoření hashe si můžete představit třeba tak, že vezmete z čísla jen poslední číslici – pak libovolné číslo zahashujete do některého z čísel 0–9. Nebo můžete použít ciferný součet, pak opět libovolné číslo zahashujete do 0–9. Nebo ciferný součet sudých pozic krát deset plus ciferný součet lichých pozic – tak dostanete hashe v rozsahu 0–99. Tyhle funkce by samozřejmě jako hashovací neobstály, protože zkonstruovat dvě čísla, která budou mít z těchto funkcí stejný hash, je triviální. Ale vidíte, že z hashe nelze rozšifrovat původní vstup.
Jiná věc je, že pro přihlášení ten původní vstup nepotřebujete, potřebujete jen takový vstup, který má stejný hash. K odhalení vstupu (třeba pro zneužití stejného hesla uživatele na jiném serveru) je potřeba ještě trocha pravděpodobnosti. Když máte hash třeba 03de6c570bfe24bfc328ccd7ca46b76eadaf4334 z databáze a v duhových tabulkách najdete, že přesně tenhle hash vznikne z hesla "abcde", máte téměř jistotu, že "abcde" je i heslo uživatele. Protože pravděpodobnost, že by stejný hash vznikl z nějakého jiného zapamatovatelného hesla, je extrémně nízká.
dovolil bych si nesouhlasit. Bezkoliznost je požadavek kvůli heslům ale hashovací funkce se rozhodně nepoužívají jen pro hesla ale pro miliony dalších účelů a tam jsou požadavky zcela jiné.
Například my běžně používáme/tvoříme hashe tak aby naopak kolize byla bylo jich velmi hodně ale byli rovnoměrně rozprostřeny do hashu. tj aby jeden obraz nemel jeden hash a druhých 100 obrazů taky jeden hash.
A neni to tak, ze se pri vynechani onoho parametru salt pridava nejaka implicitni hodnota, odvozena treba od aktualniho casu, jak tomu byvalo v /etc/passwd? Pokud by totiz davala stejna hesla ruzny hash, jakpak byste poznal, ktery je ten spravny? A jak se mohl radny uzivatel korektně prihlasit? Nehlede na to, ze by nefungovala zakladni teorie ;-).
omlouvam se za formulaci, ale pochopil jste to.
Prave tehdy, pokud se salt parametr vynecha u kryptovaci funkce maji pak dve stejna hesla ruzny hash.
Pokud se pridava sul a chce se dosahnout jineho hashe, tak se musi parametr salt menit podle nejakeho algoritmu, ktery jiz asi nebude prece kryptovaci...
A co je asi pak bezpecnejsi? Nechat kryptovaci funkci, aby sama delala hashe bez soli nebo ji rikat podle ceho je ma delat?
Nicmene jsem psal pravdu a odkaz na php funkci a priklad 3 to potvrzuje, ze kdyz se prida sul, ma to vzdy tendenci ovlivnovat vysledek a kdyz je sul staticka, tak ten vysledek je vzdy stejny.
Jj, já vím, v této diskusi nicméně primárně vníma pojem "bezkoliznost" tak, jak je vysvětlil autor článku ve svém díle ("Hash kódy na serverech LinkedIn a dalších dále těží z bezkoliznosti (odlišit lze různé úrovně), která připřípadné autentizaci porovnáním výsledných hash kódů dokáže zajistit, že heslo bude akceptováno právě tehdy, když je zadáno správně. Správný hash kód totiž díky bezkoliznosti mohl vzniknout pouze ze správného hesla."). T.j. s úplným vyloučením možnosti kolize.
K bezkoliznosti bych řekl jenom následující:
- Definice podle Prof. Dana Boneha (Stanford, jinak viz kurz http://www.crypto-class.org): Nechť H:M->T je hashovací funkce. Kolizí pro funkci H rozumíme pár m0, m1 z M takový, že H(m0)=H(m1) a m0<>m1. Řekneme, že H je bezkolizní*), pokud pro všechny explicitní účinné algoritmy A platí, že pravděpodobnost, že A vrátí kolizi pro H, je zanedbatelná**).
*) Boneh používá výraz "collision resistant", tj. "odolávající kolizím", ale česká literatura to vesměs překládá jako bezkoliznost.
**) Zanedbatelnost je definována jinde, pro tuto diskusi ji stačí chápat intuitivně.
- Definice podle Doc. Róberta Lórencze (ČVUT FIT):
-- Bezkoliznost 1. řádu := je odolnost proti kolizi a požaduje, aby bylo výpočetně nezvládnutelné nalezení libovolných dvou různých (byť nesmyslných) zpráv M a M' tak, že h(M) = h(M').
-- Bezkoliznost 2. řádu := Hašovací funkce h je odolná proti nalezení 2. vzoru, jestliže pro daný náhodný vzor x je výpočetně nezvládnutelné nalézt 2. vzor y <> x tak, že h(x ) = h(y ).
V další literatuře je to obdobně.
Závěr: "Bezkoliznost" v kryptografii není chápána jako absolutní nemožnost kolize (pro kterou by skutečně bylo potřeba, aby výstup hashovací funkce byl nejméně tak velký, aby se jím dala vyjádřit celá množina vstupů).
Skoro jako v ňákým ubuntu fóru... brrr... Celý den vyplýtvaný spoustou softcorových mistifikací a byť se tu žvatlá převážně o saltu a někdo tu už zmínil i použití šifrovacího klíče při hashování, tak zatím nikdo nikritizoval linkedin za to, že radši nepoužil HMAC, ani autora za to, že to nezkritizoval on sám.
Qou vadis, lupa.cz?
Doplňuju, že s tou bezkolizností je to ještě trošku jinak, (obecně na to, aby mohl být hash bezkolizní, musí být velikost hashe větší, než velikost vstupních dat, ze které je vypočítáván - pokud tedy linkedin podporuje hesla obsahující více než 160 bitů entropie, nemůže být SHA1 použit "bezkolizně").
Požadavky na kryptografickou hashovací funkci pak pro úplnost jsou:
1) Odolnost vůči získání předlohy. Pro daný hash c je obtížné spočítat x takové, že h(x)=c (hashovací funkce je jednosměrná.)
2) Odolnost vůči získání jiné předlohy. Pro daný vstup x je obtížné spočítat y takové, že h(x)=h(y).
3) Odolnost vůči nalezení kolize. Je obtížné systematicky najít dvojici vstupů (x,y), pro které h(x)=h(y).
Požadavek 3) má ovšem k bezkoliznosti hoodně daleko.
Sorry, ale co věta, to blbost:
- "Osolena hesla maji vzdy stejny hash a neosolena maji ruzny. Rikate to naopak!" -- Blbost. Stejná hesla mají vždy stejný hash, naopak dvě různá hesla se stejným hashem sice zcela jistě existují, ale nedokážeme je najít*). Sůl (salt) může sloužit mimo jiné k tomu, aby při stejném hesle (které si zvolil uživatel) byly různé hashe, a to tak, že ke každému heslu se přidá jiná sůl.
- "Kdyz se kryptuje v PHP a prida se do hashe prave parametr salt, tak budou vzdy hesla stejna" -- Blbost, viz výše.
- "muzete si to zkusit treba zde: http://php.net/manual/en/function.crypt.php viz priklad #3" -- Blbost, pokud vám výstupy příkladu #3 připadají všechny stejné, tak nutně potřebujete k očnímu.
- "Zaverem, kdyz vytvarim hashe, tak bych nemel solit, neni to zdrave." -- Blbost. Hashování nemá se zdravím nic společného, a pokud zdravím myslíte bezpečnost, tak je to přesně naopak, než píšete.
- "Takze kdyz byla hesla u vsech uctu stejna, tak se asi solilo hodne" - Blbost. To by nastalo pouze za předpokladu, že by všechna hesla byla stejná a současně byla pro všechna použita stejná sůl. Pokud se pro každé heslo použije jiná sůl, tak sice víme, že existují kombinace se stejným hashem, ale nedokážeme je najít*).
- "utocnik ma tak jednodussi praci a nemusi ani louskat podle dvou stejnych, pokud mel taky na linkedln ucet a mezi ucty se najde." -- Blbost. Jednodušší práci by měl za uvedených podmínek pouze v případě, že by se nesolilo nebo solilo všechno stejně.
*) Myšleno pro bezpečné hashe.
"Možnost rozšifrování" existuje vždy. Jednosměrnost zajišťuje "pouze" to, aby to nebylo výpočetně zvládnutelné (jinými slovy, "Víme přesně, jak by se to mělo dělat, ale nezvládneme to v požadovaném čase, například po dobu existence vesmíru").
"Bezkoliznost" je vlastnost, kterou musí mít dobrý hash. Pokud ji nemá, není to dobrý hash. O sečtení čísel na SPZ nikdo netvrdí, že to je dobrý hash, tudíž nemusí mít bezkoliznost - bylo to opět nabídnuto jako demonstrace principu jednosměrnosti, ne principu bezkoliznosti.
Mockrát děkuji _pepak & tdvorak.
Ale u obou vysvětlení narážíme na ty dva problémy, na kterých jsem se při přemýšlení sám zasekl.
_pepak uvádí, že "vynásobit dvě prvočísla je jednoduché, najít je je složité" => tím popírá to, že by neexistovala možnost rozšifrování
tdvorak naopak připouští "koliznost" dvou odlišných šifrovaných hesel => opět to nesouhlasí s teorií, kdy pro jeden vstup existuje jen jeden možný (unikátní) výstup
Takže jsem stále zaseklý na začátku.
Velmi jednoduchý příklad z reálného světa: představte si, že sčítáte čísla uvedená na poznávací značce auta. pro 2U3-4567 vám vyjde 27 (2+3+4+5+6+7). Z této hodnoty už ale nedovedete zpětně rekonstruovat původní značku. Jedním směrem je výpočet znám, naopak to nelze odvodit. Druhou věcí je to, že značka 1U34568 bude mít podle této 'hashovací funkce' také výsledek 27, pro dva různé vstupní řetězce máte shodný výstupní - kolizi.
citace: Tomu se dá snadno zabránit takzvaným solením, při němž se otisky počítají z hesel doplněných o nějakou další hodnotu (tedy právě takzvanou sůl), takže i když dva uživatelé budou mít stejné heslo, odpovídající otisky budou odlišné.
Osolena hesla maji vzdy stejny hash a neosolena maji ruzny. Rikate to naopak!
Kdyz se kryptuje v PHP a prida se do hashe prave parametr salt, tak budou vzdy hesla stejna a muzete si to zkusit treba zde: http://php.net/manual/en/function.crypt.php viz priklad #3
Zaverem, kdyz vytvarim hashe, tak bych nemel solit, neni to zdrave.
Takze kdyz byla hesla u vsech uctu stejna, tak se asi solilo hodne a utocnik ma tak jednodussi praci a nemusi ani louskat podle dvou stejnych, pokud mel taky na linkedln ucet a mezi ucty se najde.
Velmi zjednodušeně: Jednosměrnost je zajištěna tím, že spočítat určitou funkci je snadné, ale spočítat její inverzi je obtížné. Triviální příklad je vynásobit dvě prvočísla (jednoduché) a ze součinu dvou prvočísel najít ta prvočísla (velmi obtížné, pokud jsou ta prvočísla dost velká). Nematematický příklad: smíchat cukr, mouku a sůl je jednoduché, získat ze směsi cukru, mouky a soli samostatné suroviny je obtížné.
U hashovaných hesel to znamená, že porovnat shodu dvou hesel je jednoduché (jedno už mám zahašované, z druhého spočítám hash velmi jednoduše, porovnám hashe - to si mohu dovolit díky vlastnosti "bezkoliznost"), ale z hashe získat původní heslo je složité (více méně - musím vyzkoušet zahashovat všechna možná hesla, dokud nenajdu shodu).
Zajímalo by mě, jak funguje jednosměrné šifrování. Zaujalo mě, že již nelze proces obrátit a heslo rozšifrovat, přitom při ověřování lze zadané heslo zašifrovat tak, aby se získal stejný výstup. Takže šifrovací klíč musí být neustále stejný a nedochází mi, proč by to nešlo i obráceně - rozkódovat. Nemáte nějaký odkaz na článek toto vysvětlující?
Pokud by psal pro BFU, těžko by se pouštěl do bezkolizních hashů... i když nadruhou stranu je pravda, že tohle si nikdo jiný než BFU do hlavy narvat nenechá. Každopádně pokud by smyslem článku mělo být pouze pobavení autora plynoucí z mystifikace velkého počtu BFU, tak to nemá co dělat na Lupě...
> nerozumím tomu, proč nezavedli aspoň několikanásobný průchod.
Jj, s dnešním HW (výkonné GPU s vhodnými instrukcemi na počítaní hashů) se rainbow tables používají méně a méně. Sůl je pořád důležitá, ale sama o sobě nestačí.
Vícero průchodů (á la PBKDF2) musí být, protože hashovací funkce byly navrženy, aby běžely rychle i na hodně slabém (embedded) železe. Multiplikativní faktor vyplývající z počtu hash iterací je právě od toho, aby to útočníkovi bruteforcujicímu hesla zpomalil.
proč se člověk, který z výše uvedeného textu zjevně o problematice zabezpečení hesel nic neví, pustí do napsání takovéhoto článku. Ještě bych tomu rozuměl někde na iDnes, ale na Lupě? To si koleduje leda tak o posměch.
Hlavní důvod použití "náhodné" (to je dost důležité) soli není proto, aby dvě stejná hesla měla rozdílný hash (to je jen vedlejší efekt), ale právě proto, aby se zabránilo vámi zmiňovaným duhovým útokům. To totiž není nic magického, ale jen prosté spočítání hashe dopředu pro známé a často používané hesla. Takže pak stačí jen porovnávat otisky.
Osobně považuji za dost skandální, že taková společnost nepoužívá osolená hesla. A když už začali používat SHA1 (čemuž rozumím, když začali před x lety), tak nerozumím tomu, proč nezavedli aspoň několikanásobný průchod. Ale jasně, ono to stojí procesorový čas a peníze. Tak doufám, že se tenhle průšvih aspoň projeví na jejich příjmech a zisku, aby manažeři věděli, že to šetření taky není úplně zadarmo.
"Hash kódy na serverech LinkedIn a dalších dále těží z bezkoliznosti (odlišit lze různé úrovně), která připřípadné autentizaci porovnáním výsledných hash kódů dokáže zajistit, že heslo bude akceptováno právě tehdy, když je zadáno správně."
To už pak ovšem není hash ale šifra. :-)