06. december 2007 - 23:01Der er
71 kommentarer og 2 løsninger
Hvorfor bruge MD5?
Hej Eksperter
Er der én her inde som gider forklare mig hvorfor man skal bruge MD5? - Som jeg forstår det så "omdøber" den nærmest bare det ord / kode som indsættes i MD5. et eksempel kunne være
1234 = 202cb962ac59075b964b07152d234b70
Hvis man havde koden 1234 - så ville den i databasen se ud som sådan: 202cb962ac59075b964b07152d234b70.. Men hvad er det præcis at det skulle hjælpe.. Men hvis en hacker kommer ind i ens database, så er det lige gyldig om han får fat i 1234 eller 202cb962ac59075b964b07152d234b70..
Men kan jo evt bare måde 202cb962ac59075b964b07152d234b70 ind på den her hjemmeside:
Med kunstig intelligens skaber HP’s nye OmniBook X 14 en unik og skræddersyet brugeroplevelse målrettet dem, der ønsker høj ydeevne og intelligente funktioner
Men de har jo kun reversed et vist antal strenge. Man kan ikke "reverse" en md5, man kan blot have forudberegnet en hel masse. Hvis du foran alle passwords tilføjer "this is a very long string that will be appended to every password: ", så vil password'et "1234" istedet blive til:
md5("this is a very long string that will be appended to every password: 1234") = 8daa8533afd03a1b0c6f008ce490b863
Og indtaster du den hash i ovenstående link, jamen så virker den sørme ikke længere ;)
Man kan ikke beregne det oprindelige ud fra en md5. Basic as that. Man kan have forudberegnet en hel masse, men det kan du jo snildt komme uden om ved at tilføje noget "salt" som det kaldes.
det er netop ikke ligegyldigt - findes koden 1234 i databasen kan dette misbruges til fx at logge ind med, men findes MD5 værdien kan denne ikke bruges til noget da værdien af den i et forsøg på at logge ind igen vil blive omformet vha MD5 og dermed skabe en værdi der ikke kan matches med en værdi i databasen.
ja okay.. Prøvede mig også lige frem på hans hjemmeside.. Og opdagede det samme som dig..
Men hvis man nu gør det på denne måde at man i stedet for at ligge 1234 ned på ens hjemmeside, vælger og kører MD5 så det bliver til: 202cb962ac59075b964b07152d234b70..
Hvad gør man så. - hvis en bruger har smidt sit password ud?? laver man så bare en konktion som opretter et nyt password til personen.. samt sletter det gamle?
Ideen med at gemme et hash fremfor det originale kodeord er at folk ofte bruger samme password til forskellige ting, saa hvis de hacker sig ind paa dit web site og stjaeler Olsens kodeord kan de dermed hacke sig ind paa Olsens netbank konto i BigBank. Det kan de ikke hvis de kun faar et envejs hash.
Imidlertid er MD5 ikke saa sikker laengere som du selv har fundet ud af. Jeg vil anbefale SHA-256 i.s.f..
Specifikt står der på ovenstående link, at de har forudberegnet 50mio md5/sha1 hashes. Men 50mio inputs er jo meget få. Lad os bare sige, at de kun beregner strenge med store og små bogstaver, tal og lidt whitespace, så giver det groft sagt 70 muligheder pr. tegn. Lige så snart vi er oppe på bare 5 tegn, jamen så er der jo over 170mio muligheder mulige strenge. Så hvis de kun har beregnet 50mio kombinationer, jamen så har de ikke engang beregnet alle strenge (bestående kun af bogstaver og tal) på 5 tegn.
Så du har ikke noget at være bekymret for, selvom sha1 eller endnu bedre sha256 eller sha512 er endnu sikrere alternativer.
Og ja, i en "glemt password" situation vil du enten sende ham et nyt password eller sende ham et "sikkert" link til, hvor brugeren kan gå ind og lave et nyt password selv. Du kan nemlig ikke sende ham hans oprindelige password (og tak for det).
Keysersoze: ja okay, sådan havde jeg self ikke lige tænkt over det. - Men der ud over så kan det da heller ikke være helt læt BARE SÅDAN og skaffe sig adgang til disse koder i ens database.
Man kan godt bare ligge denne MD5 krypterede versions af ens kode sammen med de andre oplysninger til ens bruger rigtht?
Der ud over kan jeg godt se hvad du mener med de 50 mio tegn osv barklund. Men går man ud fra at den almene bruger af ens side bare bruger koder som "porsche" , "minkode1234". Som næsten alle brugere benytter sig af på nettet. (går jeg ud fra). Så ville de alle sammen kunne omkodes på hans hjemmeside. :S
Men i ville ikke være bekrymret kan jeg næsten forstå? jeg kan bare holde mig til MD5?
1) Nej, man kan ikke bare kigge i din mysql-database, med mindre du har lavet en fejl.
2) Det kan du jo netop undgå ved at bruge noget "salt" foran det password, som brugeren indtaster. Så vil den værdi, som du rent faktisk hash'er jo ikke være et "sædvanligt" password.
3) Jeg ville ikke være bekymret, hvis du brugte et "salt" - og endnu bedre laver du et random salt, og gemmer det i databasen også. At bruge forskelligt salt gør det endnu sværere at reverse dine passwords (ved at brute-force sig til dem) - da man er nødt til at køre de samme forsøg for hver bruger - og ikke bare en gang for alle brugere.
4) Overhovedet ikke - i langt de fleste programmeringssprog er det bare at kalde en anden funktion som derudover virker på fuldstændig samme måde.
Hmm ja okay. Nu tror jeg bedre jeg forstår hvad i mener med "salt" foran password..
så i stedet for at indtaste hans kodeord 1234 - når han opretter brugeren. så indstaster han i virkeligheden:
blablabla1234 - Uden selv at vide det. Og på den måde gør man det umuligt for en hacker og gætte koden. Right?
Men hvordan skriver man det ind i selve ens kode?? - altså for at tilføje noget "salt" foran ens password? både ved oprettelse af bruger, samt ved login af bruger?
Og når du skal tjekke password så hiver du værdien i databasen ud sammen med værdien fra brugeren og skriver:
$value_in_database = fetchFromDB(); $user_input_hashed = hashPassword($value_input_from_user, $value_in_database); if ($user_input_hashed == $value_in_database) { // allright, go on in } else { // no can do }
Så bruger du faktisk de første 20 tegn af password-strengen i databasen på salt og de resterende 32 tegn på en hash. Så har du en ganske sikker database. Og hvis du bliver nervøs for at bruge md5, så kan du meget nemt i ovenstående skifte det til sha1 og i lidt flere linjer skifte det til sha256 eller sha512. Jeg skulle nu mene, at det er ganske sikkert som herover :)
Det er ikke fordi jeg er en idiot og ikke gider svare jer.. Men sidder og kigger på det sidste.. og prøver at få det til at fungere :) - But anyways.. I kan lige lave nogle svar imens jeg prøver at få det til at fungere..! :)
Kan bare ikke helt se hvordan det fungere? og specielt ikke det der salt? og det er umuligt og slå op på nettet.. så finder man bare alt mulgit om normalt køkken salt ;)
Er det muligt at du gad forklare mig hvordan det fungerede? sådan skrive hvad de enkelte ting gør?
<?php // PHP script start. require("connect.php"); // Variabler til mysql hentes
$opret = ($_POST['opret']);
if (empty($opret)) { echo "Du skal aktivere dette script vha. formen i opret.php."; ?> <br> <a href="opret.php">Klik her for at oprette en bruger</a> <?php } else { $brugernavn = ($_POST['brugernavn']); //Finder brugernavnet fra opret.php $password = ($_POST['password']); //Funder passwordet fra opret.php
if (empty($brugernavn) OR empty ($password)) { //Her tjekkes om ET af felterne er tomme. echo 'Et af felterne er tomme'; } else {
$result = mysql_query("select brugernavn from users where brugernavn = '$brugernavn'") or die (mysql_error());
$number = mysql_num_rows($result);
if ($number > 0) { echo 'Desværre brugernavnet er optager'; } else { mysql_query("insert into users (brugernavn, password) values ('$brugernavn','$password')") or die (mysql_error()); echo "brugernavn $brugernavn er oprettet!"; ?> <a href="login.php">Klik her for at logge ind</a> <?php } } } ?>
Hmm. Har nu siddet og læst det lidt igennem, og sprugt mig frem andre steder. Og kom frem til at man jo også bare kunne MD5 koden "hunde". og så MD5 den 32 kode man får ud af det. Og så igen MD5 den kode. osv osv. i alt ca. 5 gange. Så skulle det jo også være ret svært for en hacker at komme frem til den orginale kode!
Men hvorfor gøre det besværligere for dig selv? Det andet er skam fuldstændig lige så sikkert. Hvis du har en sikker, godkendt ruko-lås på din hoveddør, hvorfor så sætte 5 af dem på? Ja, det er "mere" sikkert, men det er godt nok også meget meget besværligere.
Generelt, man kan ikke "reverse" en md5-sum hvis man ikke har nogen chance for at gætte, hvad det er en sum af. Der findes biblioteker over alle ord i den engelske ordbog md5'et, over alle kombinationer af strenge og bogstaver op til 4 tegn md5'et og så videre - men laver du et random salt (et nyt salt for hver bruger) på 20 tegn og smider foran brugerens password, så kan ingen, INGEN, komme igennem inden for rimelig tid.
Man kan ikke gardere sig mod brugere, der vælger et "dårligt" password (såsom "password").
Hvis vi forestiller os, at dit site bliver cracket så alle dine scripts og hele din database bliver eksponereret, så vil en cracker (ikke en hacker!) have alt hvad han skal bruge, til at bruteforce sig frem til brugernes passwords. Og i den situation er din løsning med 5 gange md5 svagere end løsningen med random salt til hver bruger. Fordi jeg kan jo bare beregne 5 gange md5 af "password" - og så kan jeg kigge samtlige rækker i databasen igennem for at se, om det matcher nogle af deres passwords. Hvis du bruger et unikt salt per bruger, så kan jeg jo ikke beregne md5 af "salt+password" en gang og kigge på samtlige rækker - jeg er nødt til at gøre det én gang for hvert salt og for hvert muligt password - altså 1 gange per række per ordbogsord. Og det giver et meget meget stort job at skulle igennem.
Essentielt er der ingen forskel på at gemme md5($password) og md5(md5(md5(md5(md5($password))))) - hvis crackeren har adgang til databasen og al kildekode, jamen så bruger han jo bare den samme metode. Den sikre forskel ligger i, at bruge et nyt salt for hver bruger. Jeg håber du kan se forskellen?
Og jeg indrømmer at have rodet mig ud i noget i starten - 5 gange md5 er ikke lige så sikkert som random salt - det er lige så svagt som at bruge samme salt til alle brugere - men ikke lige så svagt som at beregne md5 direkte - hvilket igen ikke er lige så svagt som at gemme password direkte i plaintext. Jeg håber du kan se forskellen i sikkerhed på de 4 muligheder.
Jeg er lige ved at sige at multi MD5 er dårligere end fast salt.
Hvis ideen med multi MD5 er udbredt, så kunne der eksistere færdige tabeller til det.
Endvidere minder teknikken lidt for meget om den der bruges til rainbow tabeller, så jeg er lidt bekymret for om der også er en kryptografisk svaghed i metoden.
//Går ud fra at den her definere længden af ens salt til at være 9 tegn, right?
define('SALT_LENGTH', 9);
// Her oprettes en funktion som man selv laver, og som man vælger og kalde // generateHash. $PlainText er den "kode" som brugeren skriver, right? // Hvad betyder $salt = null her? normalt betyder det jo bare at salt skal være = // null right?
function generateHash($plainText, $salt = null) {
// Hvorfor bruger de "3 x =" bruger man normalt ikke kun "2 x =" - Hvis man // gerne vil sige (if salt = 0) så udførers handlingen i {}
if ($salt === null)
// Her tror jeg godt at jeg forstår substr - Det retunere noget inde for () // Har læst lidt om det på nettet. Kan bare ikke lige forklare det. // Men er det præcis at "uniqid(rand(), true))" gør? // "0, SALT_LENGTH);" Dette gør jo bare at den skal starte fra 0 og slutte ved // 9 tegn.
Den metode er nogenlunde identisk med den metode jeg postede tidligere - jeg brugte bare 20 tegns salt.
uniqid(rand(), true) giver dig blot en masse "tilfældig" data. Altså random bytes samlet forskellige steder fra - fra maskinens entropi (rand) og fra nuværende tidspunkt i mikrosekunder (uniqid), og det samles så i en md5 for at give nogle "tilfældige" hex-tegn. substr bruges blot til kun at tage de første 9 tegn af denne sekvens af tilfældige bogstaver.
Og triplelighedstegn er "striks lighed" - altså hvis værdierne er ens OG har samme type. I PHP er (0 == null) sandt, mens (0 === null) er falsk.
Og det første i metodedefinitionen med $salt=null betyder bare, at hvis $salt ikke er sat (hvis man kun kalder funktionen med én parameter), så vil $salt få "standard-værdien" null.
Men alt dette har intet med metoden og teknikken at gøre - det er bare php-implementation af det og det kan man implementere på mange andre måder også :)
Og når du skal tjekke password så hiver du værdien i databasen ud sammen med værdien fra brugeren og skriver:
$value_in_database = fetchFromDB(); $user_input_hashed = hashPassword($value_input_from_user, $value_in_database); if ($user_input_hashed == $value_in_database) { // allright, go on in } else { // no can do } "
Der ud over hvad er det præcis at: $salt.md5($salt.$password); gør?
Først indsætter den $salt værdien XXX og derefter tager den md5 af $salt.$password ? hvad gør dette "." igennem de to $salt & $password? så vidt jeg har forstået så er det, det samme som at "+" eller hva? Men hvordan kan man "+" bogstaver?!
OBS: Du skal lige vide at jeg sætter ekstrem stor pris på at du / i gider bruge jeres tid på at hjælpe mig igennem med forståelsen af det. Vil MEGET gerne give nogle flere point for det her spørgsmål (Hvis det er det som trækker). Men har fået lidt opfattelsen af det er mere taknemligheden som trækker. Så ville lige sige at jeg er dybt taknemlig for jeres hjælp :)
Bare i orden, du skriver bare tilbage når du har tid.
Okay. men hva så hvis man skriver md5(123.456) tager den så og MD5(132456) = QQQ eller MD5123 = XXX MD5 456 = YYY (til sammen XXXYYY) - Hvis du forstår hvad jeg mener?
Typisk..!!! (Mit internet har lige været nede i 5 dage. Men sådan er det jo)
Men for at komme tilbage til det hele igen. Hvilke noget af koden "$salt.md5($salt.$password);" skal retuneres / sendes hen til ens db? - Skal man sende ens $salt og $password ? eller ens $salt og selve hastPassword? eller hva skal sendes afsted?
//disse ting som man sender afsted skal man gemme samme med den pågældende bruger right?
Du skal gemme hele outputtet fra funktionen som det er. Du skal ikke ændre funktionen men blot gemme det du får tilbage fra den direkte. Og tark for points :)
Jeg kan jo godt se hvad selve funktionen kommer med af værdi:
echo hashpassword();
---
Har også prøver og gennem denne funtion / værdi i en session som jeg kaldte "kode". Dette kunne jeg dog ikke få til at virke. Gjorde det på dennne måde:
session_start();
$_SESSION['kode']="hashpassword();";
- Selv tak. Ville bare lige give dem, så i ikke troede at jeg lige pludselig los være med det..
Okay, fandt ud af hvordan man sendte ens funktion ind i denne SESSION som jeg kaldte kode. Gjorde man bare ved at slette "". Nu er problemet bare at den ikke sender den rigtig md5 afsted?! :S det er som om at han laver om på koden. Har sidder og lavet et lille eksempel med kodevisning og alt. Vil du ikke lige se om du kan se hvor fejlen ligger? og om du overhoved kan se hvad jeg mener?
jamen, hashpassword skal jo have et argument? Og det argument skal jo være det password, som brugeren har indtastet? altså hashpassword($_POST['password']) eller noget i den stil
I min test fil ligger problemet jo bare i af den ikke sender / gemmer det rigtig password hastpassword værdi.
Jamen i dette tilfælde er "brugeren / mig selv" indtastet "hund" som password.
Men ja okay, kan godt se lidt hva du mener. Men hvis man så skriver "hashpassword($_POST['password'])" og password er det password som den pågældende bruger. Hvad skal der så med det? Kan ikke helt forstå det kan du godt høre ik :D
Før havde du med garanti et insert-statement noget i stil med:
$sql = "INSERT INTO user(username, password) VALUES('".$_POST['user']."','".$_POST['password']."')";
Meget simplificeret, men det gjorde du før. Altså du satte brugernavn og password ind i databasen.
Det du skal gøre nu er:
$sql = "INSERT INTO user(username, password) VALUES('".$_POST['user']."','".hashPassword($_POST['password'])."')";
Igen meget simplificeret. Men det er alt hvad du skal gøre anderledes. Der hvor du førte gemte password direkte (eller måske md5(password)), der skal du istedet kalde hashPassword-funktionen :)
Men når så en bruger skal logge på systemet efter at have oprettet sig. Hvordan gør man så det? Mener, nu er denne helt tilfældige $salt værdi jo oprettet? Den må da også skulle gennem et sted hos brugeren, for at kunne logge ind ??? eller hva?
Arh.. Nu tror jeg måske at jeg præcis har forstået det der med "$plainText". "$plainText" er det som man sætter ind imellem () right?. - Altså hvis man skriver:
function hashPassword($plainText, $salt = '') {...};
Så ville plainText være det som du sadte ind imellem (), i dit eksempel: ($_POST['password']) - Den forstår altså selv at når der står plainText, så er det det som brugeren selv sætter ind imellem ().
Arh det er svært at forklare. - Men kan du se hvad det er som jeg mener?
Det er hele princippet i en funktion, der tager argumenter. Har du aldrig nogensinde skrevet en funktion i noget som helst programmeringssprog før? :)
Det er sådan et ret fundamentalt princip, så hvis du ikke er med så langt, så kan jeg godt forstå, at du er forvirret. Jeg tror en grundlæggende programmeringsbog ville hjælpe dig meget :)
Ja okay, har lige siddet og kigget lidt på det. Men det fungere på denne måde med $plainText right?:
---Fil test4.php---
<?php
session_start(); $_SESSION['kode']="hund";
?>
---Fil test5.php---
<?php session_start();
$plainText = "" . $_SESSION['kode'];
echo "$plainText"; //Bare lige for at vise selve PlainText før MD5
echo "<br><br>";
function hashPassword($plainText) {
return md5($plainText); }
echo hashPassword();
?>
---
Eller findes der en smartere og mere korrekt måde og gøre det på????
ps. Ved godt at jeg burde læse nogle bøger i stedet. Og det har jeg faktisk også prøvet på. Synes bare at jeg lærer mest ved bare og spørge mig "lidt" frem og så prøve mig frem.
Altså, vi er ude i, at du ikke ved hvad en php-funktion er. Eller faktisk hvad enhver funktion i ethvert programmeringssprog er. hashPassword() er det samme som md5(). Det er to funktioner. Man kalder en funktion med nogle argumenter, internt gør den noget ved sine argumenter og til sidst returnerer den en værdi:
Det er ret simpelt. Man kan bruge svaret til hvad som helst, man kan give hvad som helst som argumenter. Enhver variabel er "lige god" uanset hvad den hedder, hvor den ligger eller om den har noget som helst man navnet på variablen den puttes over i inden i funktionen.
Men med hensyn til det der med oprettelse af en bruger. Der SKAL man da også gemme ens salt værdi i databasen sammen med brugeren? for senere og kunne logge på brugeren? right?
Saltet er en del af det, som hashPassword-funktionen returnerer. Hvis du bruger den version af funktionen, som du postede 12/12-2007 09:53:36, så er salt'et de første 9 tegn og det hash'ede password og salt er de efterfølgende 32 tegn. Altså 41 tegn i alt som bare gemmes sammen.
I er alle enige om at man bør bruge salt (jeg er også enig), men hvordan vil i gemme dem? Det er da ikke særlig attraktivt at gemme et tilfældigt salt sammen med brugernavnet i databasen, hvis en uønsket person får adgang til databasen.
Et alternativ er at man gemmer saltene i en fil sammen med brugernavn, og så inkluderer den. Men hvis en uønsket person får adgang til filerne (og dermed kan han læse dem og kigge i databasen) er det lige så synligt som at lægge det i en db.
Hvor kan man så gemme saltene, eller måske snarere hvordan?
Du gemmer det bare lige ved siden af den hashede værdi. Meningen er blot at gøre det et pænt antal gange sværere at bryde, og det behøver ikke være hemmeligt for det. Desuden skal dit script jo have adgang, så det skal forefindes "i nærheden" af den hashede værdi.
Mit OK var til 06/06-2008 21:11:59, men foedselsdag giver 36000 muligheder ved 2 cifret aar og det hjaelper, dog ikke saa meget som 32 eller 64 random bit.
Det skulle så være for ikke at oplyse saltet direkte... På den måde kan han ikke 'oversætte' hele/dele af sin MD5 database. (Hvilket i forvejen er et stort arbejde)
Jah, men så har du jo 06/12-2007 23:14:22, som han ikke kan se, hvis han ikke kan se kildeteksten. Et salt bruges fordi: 06/06-2008 21:19:25 - den der gangen op med masser af milliarder muligheder er ret godt.
Derudover kan du jo bruge yderligere ting inden du hasher, fx personens efternavn. Blot du husker at ændre hash, hvis han skifter efternavn. Og så har du ikke det originale password, men skal be' om det igen.
Bøvlet skal stå mål med sikkerheden - nu er det vel ikke ligefrem Foghs Grundlovstaler du bevogter...
Det her er jo kun een del af det der med sikkerhed. Hvis du bliver ved med tærske langhalm på det, når du aldrig til de andre "bropiller". md5 med salt og "lang streng" - det er godt nok.
Er det ikke godt nok, må du komme med et argument for hvorfor det ikke er godt nok til dit brug.
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.