2010-04-07 13 views
5

Stworzyłem sól używając; md5 (rand (0,10000000)); (jest prawdopodobnie lepszy sposób)?Unikalne pole tekstowe w MySQL i php

Nie wydaje się możliwe, aby pole tekstowe było unikalne w MYSQL. Jak więc sprawdzić, czy sól została już użyta dla poprzedniego użytkownika?

Czy powinienem wygenerować sól na podstawie aktualnej daty/czasu? ponieważ niemożliwe jest, aby 2 użytkownicy zarejestrowali się dokładnie w tym samym czasie, co jest prawidłowe?

+1

Możesz dodać unikalne ograniczenie na polu varchar - możesz użyć tego do sprawdzenia duplikatów soli. – thetaiko

Odpowiedz

1

Dla soli wyjątkowość jest ważniejsza niż długość i przewidywalność. Zakładasz, że atakujący ma sól.

Uniwersalnie unikalny identyfikator (UUID) byłby najlepszy, a istnieją przykłady generujące uniwersalnie unikalne identyfikatory na stronie dokumentu dla funkcji php uniqueid(). UUID ma tę przewagę nad losowym łańcuchem, że jest czytelny dla człowieka i ma stałą długość, dlatego możesz go przechowywać w polu varchar i używać unikalnego indeksu, aby zapewnić, że nigdy nie będzie duplikatów.

Hashowanie czasu z MD5 jest powszechną metodą generowania unikatowych wartości, ponieważ ma stałą długość i jest czytelna dla człowieka. Jednak bardziej sensowne jest wygenerowanie losowego ciągu o stałej długości i zakodowanie go w hex. Hashe nie są tak zaprojektowane, aby nie były odwracalne. Użycie funkcji mieszania gwarantuje kolizje, chociaż mniej będzie kolizji z SHA1 niż z MD5.

Długość soli jest tak naprawdę tylko czynnikiem, ponieważ im dłuższa sól, tym bardziej prawdopodobne jest, że jest uniwersalna.

+0

powinno być jakimś dziwacznym zbiegiem okoliczności 2 użytkowników, którzy zdarzają się, mają taką samą sól, decydują się na to samo hasło, następnie –

+0

@ Jonathan, jeśli istnieją powielone sole z różnymi skrótami hasła, najpierw zaatakuję te konta, ponieważ daje mi to większą szansę w znalezieniu udanej kolizji. Dwa konta z tą samą solą i hasłem dadzą atakującemu dwa w cenie jednego, ale atakujący nie dostanie żadnych przerw. –

0

md5() jest złamanym algorytmem i nigdy nie należy go dotykać.

rand() jest lekko uszkodzony, ponieważ jest oparty na zegarze systemowym.

Lepszym sposobem jest:

function generateRandomKey() 
{ 
    return base_convert(uniqid(mt_rand(), true), 16, 36); 
} 

Edit: Jeśli istnieje lepszy sposób, czy się mylę, proszę mi pokazać swój sposób to robić. Jestem naprawdę zainteresowany i chciałbym wiedzieć, czy jestem niepewny.

+1

Aby uzyskać inny, bardziej powszechnie akceptowany widok, zobacz http://stackoverflow.com/questions/2329609/is-it-safe-to-store-passwords-hashed-with-md5cryptoserviceprovider-in-c – dkretz

+0

@ collectorifier, link, który wysłałeś jest o hashowaniu haseł, bez generowania losowych soli. –

+1

i http://stackoverflow.com/questions/157998/whats-the-difference-between-sha-and-md5-in-php. Miałem na myśli "... nigdy się nie dotykaj". – dkretz

0

Generowanie soli przy użyciu SHA1 przy użyciu identyfikatora użytkownika i daty i godziny.

1

Indeksy MySQL są ograniczone do długości w polach tekstowych, nie przechodzą w całe pole automatycznie, tak jak robią to w polach char/varchar, więc nie ma praktycznego sposobu użycia "unikalnego" klucza w polach tekstowych.

Ale jeśli przechowywania skrótów generowanych przez MySQL, wtedy nie trzeba tekst - HAS wyniki są zwykły tekst, więc wystarczy użyć stałej długości char murawę:

mysql> select length(md5('a')), length(sha1('a')); 
+------------------+-------------------+ 
| length(md5('a')) | length(sha1('a')) | 
+------------------+-------------------+ 
|    32 |    40 | 
+------------------+-------------------+ 

a następnie możesz zastosować unikalne ograniczenie do tego pola.

0

Generalnie nie generuje się często ciągów soli. Więc kiedy po raz pierwszy je wygenerujesz, powinieneś zrobić dobrą robotę. Dłuższe i bardziej losowe ciągi są lepsze.

function generateSalt($length = null) 
{ 
    if (!is_int($length) || ($length < 1)) $length = 250; 
    do { 
    $salt[] = chr(mt_rand(0, 255)); 
    } while (--$length); 
    return implode('', $salt); 
} 

zapytanie o aktualizację do nowego hasła

update user set salt = :salt, password = sha1(concat(:password, :salt)) where id = :id limit 1; 

można sprawdzić, czy hasło jest poprawne i uzyskać dane użytkownika w tym samym czasie.

select * from user where id = :id and password = sha1(concat(:password, salt)) limit 1;