salt
Op een website las ik:
Quote:
If you salt 350 different passwords, you should have 350 different salts. If someone changes their password 293 times, you should generate 293 salts, one for each password.
Ik snap dit niet zo goed wat hier wordt bedoeld. Hoezo moet je voor ieder wachtwoord een andere salt maken? Die salt moet je dan per user toch ook weer opslaan, anders kun je het wachtwoord toch niet controleren? Mis ik iets? Wat is het nut als ik voor iedere user een unieke salt maak, en er in de database zoiets als dit staat:
Het idee achter een salt is dat wanneer twee personen hetzelfde wachtwoord hebben, de gecrypte versie ervan anders is. Het is anders heel eenvoudig om een dictionary attack op de wachtwoordenlijst uit te voeren. Door steeds een andere salt te gebruiken, moet je voor elke salt het complete woordenboek encrypten om te kijken of je een match hebt.
Willem, oké. Dat stukje is me duidelijk. Maar ik snap niet hoe je zo'n unieke salt dan moet genereren. En die salt moet je dan toch ook in de database opslaan? En dat laatste wil je toch niet lijkt mij? Als iemand dan je database hackt, dan staan alle salts erin. Of begrijp ik het niet goed?
Op zich is het geen probleem om de salt in de database op te slaan. Het gaat erom dat een computercrimineel niet van tevoren een lijst met vaak gebruikte wachtwoorden kan crypten/hashen en de gecrypte versies vergelijken met de waarde in de database. Door de salt moet hij nu voor elke gebruiker elk wachtwoord opnieuw crypten, en dat kost tijd. Veel tijd. En daar is het nou precies om te doen. ;-)
Gewijzigd op 31/03/2014 01:46:59 door Willem vp
Als ik de salt in de database opsla... laten we even zeggen dat de salt "foo" is... dan ziet de crimineel, ah... de salt is 'foo'.
Vervolgens kan de crimineel met deze salt zijn woordenboek doorlopen. Als de crimineel de salt niet weet, dan heeft ie toch een veel groter probleem?
Het is een illusie om te denken dat als iemand achter je lijst met gecrypte wachtwoorden kan komen, het hem niet lukt om ook de bijbehorende salts te vinden. Ga er maar vanuit dat dat lukt. Het beste wat je dus kan doen, is ervoor zorgen dat het in ieder geval vertragend werkt.
Laten we eens 30 jaar teruggaan in de tijd. Onder Unix had je toen gecrypte wachtwoorden met een salt van 2 tekens. Elk teken had 64 mogelijke waardes, zodat je dus 4096 verschillende salts had. Als je een systeem wilde kraken, kon je dus van tevoren de (bijvoorbeeld) 1000 meest populaire wachtwoorden crypten met elke mogelijke salt. Je had dan net iets meer dan 4 miljoen gecrypte wachtwoorden. Ik geloof dat een gecrypt wachtwoord destijds 15 tekens was (inclusief salt) en dus had je een tabel van 61 MB (destijds erg groot, trouwens). Zoiets wordt overigens een rainbow table genoemd.
Als het je was gelukt een lijst met gecrypte wachtwoorden te vinden, kon je met een script vrij snel je rainbow table matchen met de wachtwoordenlijst.
Stel nu dat je salt niet 2 tekens is, maar 12 tekens (van elk 64 mogelijkheden), dan heb je 4,7 triljard mogelijke salts. Het werken met een rainbow table kun je dan gevoeglijk op je buik schrijven. Je zult dan gebruiker voor gebruiker alle wachtwoorden moeten crypten met de voor die gebruiker ingestelde salt. Dat kost veel meer tijd dan het opzoeken van een gecrypt wachtwoord in een tabel. Wanneer twee gebruikers dezelfde salt zouden hebben, maak je het de boosdoener dus gemakkelijker, want dan kan hij de gecrypte versies checken tegen meerdere gebruikers.
Gewijzigd op 31/03/2014 02:34:44 door Willem vp
http://programmers.stackexchange.com/questions/234228/when-allowing-a-user-to-change-passwords-should-i-generate-a-new-salt
Een salt hoort uniek te zijn. Het liefst is de salt niet alleen uniek in het hier en nu, maar ook op elk ander moment in het verleden.
Een salt hoort random gegenereerd te worden waardoor je deze niet voorspelt kan worden.
Een salt is niet heel geheim, de salt opslaan in de database is geen enkel probleem. Het doel van een salt is dat een nieuwe rainbow table gegenereerd moet worden voor die salt. Dat lukt.
Je zou de salt nog kunnen encrypten, maar dan maak je het jezelf vooral lastig. Voor kwaadwillende is het al lastig genoeg.
PS. gebruik Bcrypt, dit algoritme slaat de salt in de hash op.
Antwoord op de oorspronkelijke vraag: Een salt hoort uniek te zijn. Het liefst is de salt niet alleen uniek in het hier en nu, maar ook op elk ander moment in het verleden.
Een salt hoort random gegenereerd te worden waardoor je deze niet voorspelt kan worden.
Een salt is niet heel geheim, de salt opslaan in de database is geen enkel probleem. Het doel van een salt is dat een nieuwe rainbow table gegenereerd moet worden voor die salt. Dat lukt.
Je zou de salt nog kunnen encrypten, maar dan maak je het jezelf vooral lastig. Voor kwaadwillende is het al lastig genoeg.
PS. gebruik Bcrypt, dit algoritme slaat de salt in de hash op.
Gewijzigd op 31/03/2014 08:18:55 door Dos Moonen
bcrypt class. Werkt net zo, ieder wachtwoord is iedere keer een andere hash.
Kijk anders eens naar Dus stel iemand heeft een lijst met mijn gehashte wachtwoorden, en ik heb een goed algoritme gebruikt, dan nog kunnen ze de salt vinden, ook als ik die salt bijv. "asd34*&âksjhdas';';alr(*&$%kjsdfkjwh5kjsfhi8wy4543ksdfkh" ?
>> Antwoord op de oorspronkelijke vraag: http://programmers.stackexchange.com/questions/234228/when-allowing-a-user-to-change-passwords-should-i-generate-a-new-salt
Even voor de goede orde... ik ben niet de steller van die vraag mocht je die indruk hebben.
>> PS. gebruik Bcrypt, dit algoritme slaat de salt in de hash op.
>> Kijk anders eens naar bcrypt class. Werkt net zo, ieder wachtwoord is iedere keer een andere hash.
Bedankt voor de tip. Ik zal er naar gaan kijken. Kan een potentiële hacker aan zo'n hash zien wat de salt is, of is dat niet duidelijk?
Hebben jullie dit trouwens al gezien? Is dat wat?
http://nl1.php.net/manual/en/function.password-hash.php
En om een wachtwoord te achterhalen ga je gewoon elke mogelijke optie af in het inlogformulier. En dan is een dynamische salt dus heel handig. Het is dan erg ingewikkeld om het wachtwoord te vinden.
Ah oké. Ik snap wat je bedoelt. Maar het is een hacker toch ook om wachtwoorden te doen? Tenminste dat is wat ik altijd lees waarom er gewaarschuwd wordt om de wachtwoorden als hashes op te slaan en niet als plain text. Mocht een hacker je database in handen krijgen dan zijn de wachtwoorden niet zichtbaar, zodat hij deze niet kan gebruiken om op andere sites in te loggen (mensen gebruiken vaak hetzelfde wachtwoord). Ik dacht dus dat dat ook een belangrijke reden was om wachtwoorden te hashen. En dan moet je dus zorgen dat het zo lastig mogelijk is om aan de hand van de hashes het wachtwoord terug te vinden. En daarom lijkt het mij dus raar om de salt erbij op te slaan. De hacker weet dan al 100% zeker dat hij de juiste salt heeft. Ja, dan moet ie nog steeds per salt een nieuwe hash-tabel maken, maar het maakt het wel makkelijker zou je denken.
Ik had beter "eerste" kunnen schrijven...
"maar het maakt het wel makkelijker zou je denken." Klopt, dat de salt geheim is is geen eis.
Het enige doel van een salt is dat het er voor zorgt dat je voor iedere hash opnieuw moet beginnen. Zo is het van de rekenkracht die het koste om alle vorige hashes te kraken niet herbruikbaar.
Dat je salt alleen in de database te vinden is en je er niet via de website achter kunt komen zou je voor een deel kunnen zien als security through obscurity.
Wat je kunt doen is bcrypt(hmac(password, pepper), salt)
Een salt is voor iedere hash uniek, een pepper is voor iedere hash het zelfde. Dat wint je ongeveer evenveel tijd als dat je de salts zou encrypten.
De enige onbekende voor het kraken van zijn eigen hash is namelijk de pepper aangezien de kwaadwillende zijn eigen wachtwoord en de uiteindelijke hash weet.
password_hash() is wat ik aanraad om je wachtwoorden mee te hashen (op het moment is alleen Bcrypt mogelijk)
Gewijzigd op 31/03/2014 13:44:31 door Dos Moonen
Oké. Dus alle moeite die je bij het eerste wachtwoord hebt moeten doen, moet je bij het 2e wachtwoord weer doen. Dit begrijp ik en is inderdaad een goed argument.
>> Klopt, dat de salt geheim is is geen eis.
Dit begrijp ik niet. Stel ik heb een rainbow table:
Op het moment dat een hacker de salt kent, wordt het toch veel makkelijker voor hem? Stel de salt is 'foo', dan krijg je:
Op het moment dat de hacker de salt niet kent, en ik gebruik een salt van 30 tekens, maak ik het hem dan niet veel lastiger?
>> password_hash() is wat ik aanraad om je wachtwoorden mee te hashen (op het moment is alleen Bcrypt mogelijk)
Waarom is password_hash niet mogelijk? Php 5.5 is toch al uit?
Moeilijker dan wanneer je geen salt gebruikt? Nee.
In tegenstelling tot het plaintext password moet je een salt zo opslaan dat je de plaintext versie weer kunt achterhalen.
Gebruik gewoon Bcrypt, deze slaat de salt op in de hash dus je hebt geen keus. Slechte wachtwoorden weren geeft meer veiligheid dan de salt proberen te verbergen.
"Waarom is password_hash niet mogelijk? Php 5.5 is toch al uit?"
Waar zeg ik precies dat het niet mogelijk is? :p
Voor PHP >= 5.3.7 is er zelfs een userland compatibility library die gelinkt staat op de documentatie van password_hash()
Ik zeg alleen dat voorlopig het enige hashing algoritme waarmee password_hash() overweg kan Bcrypt is.
Ozzie PHP op 31/03/2014 13:49:11:
Op het moment dat de hacker de salt niet kent, en ik gebruik een salt van 30 tekens, maak ik het hem dan niet veel lastiger?
Een salt is er niet zozeer om het achterhalen van 1 wachtwoord te bemoeilijken, maar om het achterhalen van een heleboel wachtwoorden te vertragen, doordat je de resultaten van eerdere kraakpogingen niet kunt hergebruiken.
Nee, moeilijker dan wanneer je een onbekende salt gebruikt.
Of zie ik dat verkeerd?
>> In tegenstelling tot het plaintext password moet je een salt zo opslaan dat je de plaintext versie weer kunt achterhalen.
Eenmaal gehasht kun je de plaintext versie van het password toch niet meer terugkrijgen? Of mis ik iets?
>> Gebruik gewoon Bcrypt, deze slaat de salt op in de hash dus je hebt geen keus.
Is Bcrypt een algoritme? Heeft het iets te maken met de class die Bas Kreleger hierboven noemt?
>> Waar zeg ik precies dat het niet mogelijk is? :p
Oooh, haha... verkeerd begrepen :D
Is dat Bcrypt algoritme goed? Beter dan SHA512 bijvoorbeeld?
>> Een salt is er niet zozeer om het achterhalen van 1 wachtwoord te bemoeilijken, maar om het achterhalen van een heleboel wachtwoorden te vertragen, doordat je de resultaten van eerdere kraakpogingen niet kunt hergebruiken.
Oké... deze gedachte snap ik inmiddels. Alleen stel dat een hacker je database te pakken krijgt, dan vind ik het wel raar dat de salts daar gewoon in staan. Het is bijna alsof je zegt: "hier, cadeautje, heb je alvast de goede salt!".
SHA512 is snel, Bcrypt is traag. Hoe traag hangt af van de cost die je instelt. Speel met de cost tot een hash tussen de 100 en 300 miliseconden cost om te berekenen. Snel genoeg dat wanneer een gebruiker inlogt er weinig last van heeft. Traag genoeg om kwaadwillende erg veel langer over te laten doen.
> Het is bijna alsof je zegt: "hier, cadeautje, heb je alvast de goede salt!".
Absoluut niet, je zegt juist "HAHAHAHA! Je moet voor iedere hash overnieuw beginnen! LEKKER PUH!"
Door te salten moet een attacker voor iedere hash overnieuw beginnen.
Door te hashen moet een attacker veel CPU/GPU kracht aan aanvallen besteden.
Ga uit van het slechte senario, de aanvaller weet alles wat jij weet, dus ook de salt.
http://security.stackexchange.com/questions/211/how-to-securely-hash-passwords
Gewijzigd op 31/03/2014 14:49:00 door Dos Moonen
Dus samengevat, op dit moment is de beste manier om een wachtwoord te beveiligen via password_hash?
En als ik simpelweg een string wil hashen (dus geen wachtwoord) en naderhand wil kunnen controleren of die string niet is veranderd, welke hash-methode raad jij dan aan?
Deze vraag heeft overigens betrekking op dit topic.
Ward raadde mij het md5 algoritme aan omdat dit erg snel is. Ik heb even gebenchmarked, en omdat ik maar 1 keer per pagina-aanroep de hash hoef te genereren, maakt het qua tijd niks uit. Zowel md5 als SHA512 zijn hartstikke snel. Alleen meen ik dat SHA512 minder kans heeft op collision? Ik zou ook nog SHA256 kunnen kiezen, maar ik weet niet waar ik mijn keuze op moet baseren eerlijk gezegd. Hoe bepaal je of je moet kiezen voor MD5, sha1, sha256 of sha512? Wat ik lees op internet zijn md5 en sha1 niet geheel veilig omdat er kans is op collision. Dan blijven sha256 en sha512 over. Maar wanneer kies je voor wat? het verschil in snelheid is verwaarloosbaar.
SHA2 is prima
Dat lijkt me een prima argument.
>> SHA2 is prima
En dan sha256 of sha512? Maakt dat iets uit?
Buiten md5 en sha staan op mijn server ook nog deze algoritmes. Zie je er hier nog een tussen die beter is dan sha? Of is sha gewoon het beste wat er is?
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
[8] => ripemd128
[9] => ripemd160
[10] => ripemd256
[11] => ripemd320
[12] => whirlpool
[13] => tiger128,3
[14] => tiger160,3
[15] => tiger192,3
[16] => tiger128,4
[17] => tiger160,4
[18] => tiger192,4
[19] => snefru
[20] => snefru256
[21] => gost
[22] => adler32
[23] => crc32
[24] => crc32b
[25] => fnv132
[26] => fnv164
[27] => joaat
[28] => haval128,3
[29] => haval160,3
[30] => haval192,3
[31] => haval224,3
[32] => haval256,3
[33] => haval128,4
[34] => haval160,4
[35] => haval192,4
[36] => haval224,4
[37] => haval256,4
[38] => haval128,5
[39] => haval160,5
[40] => haval192,5
[41] => haval224,5
[42] => haval256,5
[9] => ripemd160
[10] => ripemd256
[11] => ripemd320
[12] => whirlpool
[13] => tiger128,3
[14] => tiger160,3
[15] => tiger192,3
[16] => tiger128,4
[17] => tiger160,4
[18] => tiger192,4
[19] => snefru
[20] => snefru256
[21] => gost
[22] => adler32
[23] => crc32
[24] => crc32b
[25] => fnv132
[26] => fnv164
[27] => joaat
[28] => haval128,3
[29] => haval160,3
[30] => haval192,3
[31] => haval224,3
[32] => haval256,3
[33] => haval128,4
[34] => haval160,4
[35] => haval192,4
[36] => haval224,4
[37] => haval256,4
[38] => haval128,5
[39] => haval160,5
[40] => haval192,5
[41] => haval224,5
[42] => haval256,5
Je sleutelt aan schijnveiligheid.