Mikä koodissa mättää?
Selitän siis vielä:
1. crypt muuttujassa muutetaan input kenttään kirjoitettu salasana MD5 hashiksi.
2. avataan password muuttujaan salasana -tiedosto (joka sisältää kaikki hashit).
3. verrataan hashejä.
Alussa koodi toimi ja yhtäkkiä toiminta lakkasi... Suurin ongelma on se, että hashien tarkistus sanoo aina "Salasana ei täsmää!".
<?php $crypt = md5($pass); $password = file('pass.txt'); if ($crypt == $password[0]) echo "Salasana täsmää!"; else echo "Salasana ei täsmää!"; ?>
EDIT. Huomasin että kun pass.txt tiedostoon laitta kaksi hashiä, niin silloin se lakkaa toimista, ja kun sen poistaa ja asettaa myös sen toisen hashin sinne, niin silloin se taas toimii? Outoa?
Salasanatiedostossa useampi rivi? Trimmaa rivinvaihdot pois:
if ($crypt == trim($password[0]))...
Edit. Siis huomasitkin tuon rivinvaihdon... :)
No tulipas vastaus samaan aikaan kun lisäilin viestiini... Johtu siis juuri tuosta, että rivejä oli useampi...
No lisää tuli ongelmia... Eli nyt väsäsin tohon yllä olevaan koodiin vielä tunnuksen ja salasanan yhteistarkoituksen, sekä koodinpätkän joka vertaa teksti tiedostossa olevia salasana tunnus pareja keskenään. Mutta ei toimi kunnolla...
<?php $crypt = md5($pass); $password = file('pass.txt'); for($i = 0; $i < count($password); $i++) { $_pass = explode('<|>',$password[$i]); } for($i = 0; $i < count($_pass); $i++) { if ($crypt == trim($_pass[1+$i]) && $user == trim($_pass[0+$i])) echo "Salasana täsmää!"; } ?>
Edit. Huomasin taas jälkikäteen, että koodi tekee sellasta kun mitä useamman tunnus/salasana pareja tekee, niin ainoastaan se viimeisenä lisätty salasana pari toimii ja muut lakkaa toimimasta...
Looginen erhe, ylikirjoitat aina tuon $_pass (alaviivaa käytetään muuten yleensä private/protected-jäsenten merkkinä) loopissa.
Nyt en oikein ymmärtänyt, siis kumpaan looppia edes tarkoitat ylempää vai alempaa? Siis perus ideana tossa ylemmässä loopissa on jakaa jokainen rivi kahteen osaan tolla explode() funktiolla, ja sitten alemmassa oli tarkoitus lisätä niin kauan yksi indeksiin useriin sekä passiin kunnes rivit loppuvat.
Komentele var_dump($_pass);
ympäri koodia niin näet, että mitä muuttuja $_pass sisältää - taulukon tapauksessa indeksit ja arvot, joihin ne viittaavat.
Tässä hieman erilaisella tavalla toteutettuna.
<?php // hashi $password = md5($pass); // poista rivinvaihdoista mahdollinen Windows-lisäke $passwords = explode("\n", str_replace("\r", '', file_get_contents('pass.txt')) ); // käy lävitse kaikki käyttäjänimi- ja salasanaparit for($i = 0, $maxi = count($passwords); $i < $maxi; $i++) { // varmista että riviltä löytyy käyttäjä-salasana -pari if (strpos($passwords[$i], '<|>') !== false) { // ota käyttäjänimi ja vastaava salasanahashi list($user2, $password2) = explode('<|>', $passwords[$i]); // vertaile, jos täsmää niin hyppää ulos if ($password == trim($password2) && $user == trim($user2)) break; } } // keskeytyikö looppi kesken kaiken? if($i < $maxi) { echo 'Salasana täsmää!'; } else { echo 'Käyttäjää ei löytynyt tai salasana oli kirjoitettu väärin!'; } ?>
Muistakaa myös pelkällä md5:lla hashatun salasanan turvallisuus. Elävä esimerkki tapahtui juuri viime syksynä ~70.000 tunnukselle Suomessa.
<?php echo stripos( file_get_contents( 'userdb.txt' ), ( isset( $_POST[ 'user' ] ) ? $_POST[ 'user' ] : '' ) . '<|>' . ( isset( $_POST[ 'pass' ] ) ? md5( $_POST[ 'pass' ]) : '' ) ) !== false ? 'Logged in' : 'Username or password invalid or missing'; ?>
EDIT: Eikä oo ees hitaampi :3. Njoo ehkä sitä tiedostoa on turha lukia, jos noita arvoja eio edes lähetetty.. Vaan onko merkkijonojen yhdistäminen + 1 vertailu hitaampi operaatio kuin explode + 2 vertailua + trim? Trimmin voi pudottaa pois kun pistää ylimääräisen erotinmerkin rivien loppuun, se on ainakin muistaakseni nopeampi tapa.
No nyt sain toimimaan tai toimii ainakin tällä hetkellä... :D Lisäilin myös kommentit ja muuttelin muuttujien nimet paremmiksi. Kiitos kaikille avusta!
Koodi on tässä (Sanokaa mielipiteenne!):
<?php //kryptaa annetun salasanan $crypt = md5($pass); //avaa salasana tiedoston $passfile = file('pass.txt'); //Käy kaikki rivit läpi for($i = 0; $i < count($passfile); $i++) { //Jakaa rivit keskeltä kahtia $passline = explode('<|>',$passfile[$i]); //Vertaa tunnus/salasana pareja if ($crypt == trim($passline[1]) && $user == trim($passline[0])) echo "Tunnus ja salasana täsmäsivät!"; } ?>
Turha silmukkaa lienee kiertää enää sen jälkeen kuin täsmäävät tunnarit on löytynyt, eli break vaan kehiin tonne if-lohkoon (niinkuin tuossa Merrin esimerkissä näyttäisi olevan).
Edellisessä one-linerissani oli pikku erhe, strpos
eikä stripos
.
Huomioita: (ei missään järjestyksessä)
-Hae nuo arvot muuttujiin jostakin, webympäristössä oletettavasti $_GET-
tai $_POST
-taulukosta.
-Sisennä koodisi.
-Suojaathan salasanatiedoston. Webbiympäristössä Apassia käyttäessä htaccessilla tai pidät tiedoston ulkona webrootista.
-Anna file-funktiolle toisena parametrina FILE_IGNORE_NEW_LINES
ja exploden sijaan vertaile suoraan salasanan tiivisteen (hashin) ja käyttäjänimen yhdistettä.
-Käytä forin sijaan foreachia.
-md5 ei ole kryptaus- vaan tiivistefunktio, joten muuttujan nimi on edelleen vähintään hämäävä. Käytä mieluummin hash-funktiota vaikka SHA256-algoritmilla - kirjasto tulee nykyään PHP:n mukana vakiona. Tai mikäli nopeus huolettaa niin mhash on väitetysti nopeampi vaihtoehto.
-Se break.
Aihe on jo aika vanha, joten et voi enää vastata siihen.