Regulární výraz bezpečné heslo, aneb jak testovat silná hesla

RegExp strong password je celkem běžnou záležitostí, ale přesto si s tím řada programátorů nedokáže poradit. Tady je jeden návrh mého řešení jak testovat heslo s jedním velkým písmenem, jedním číslem a minimálně 8 znaky. A také způsob jak takové heslo vytvořit.


Na tento článek mne přivedl jeden kolega a způsob jakým tento problém řešil. Jeho řešení ukazuji v následujícím příkladě.

Stanovené podmínky:

  1. minimálně 8 znaků
  2. minimálně jedno velké písmeno
  3. minimálně jedno číslo
  1. function checkPwd($pwd) {
  2. if (strlen($pwd)<8) return false; 
  3. if (!preg_match("~[a-z]+~", $pwd)) return false;
  4. if (!preg_match("~[A-Z]+~", $pwd)) return false;
  5. if (!preg_match("~[0-9]+~", $pwd)) return false;
  6. return true;
  7. }

Bohužel nechtěl mi věřit, že to lze zapsat jedním regexpem a tak musel vzniknout tento článek.

Moje Řešení

  1. $password=array("SuperSilneHeslo2009", "supersilneheslo2009", "supersilneheslo", "Supersilneheslo2009", "su2009", "Su2009");
  2. function checkPass($p) {
  3. $regexp="/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(.){8,}$/";
  4. if (preg_match($regexp, $p)) return true;
  5. else return false;
  6. }
  7. foreach($password as $p) {
  8. if (checkPass($p)) echo $p." ...OK";
  9. else echo $p." ...BAD";
  10. echo "<br/>";
  11. }

Vyzkoušejte funkčnost sami.

A jak takové heslo automaticky vytvořit?

  1. function createPassword($length) {
  2. $chars="234567890abcdefghijkmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
  3. $i=0;
  4. $password="";
  5. while ($i <= $length) {
  6. $password.=$chars{mt_rand(0,strlen($chars))};
  7. $i++;
  8. }
  9. return $password;
  10. }
  11. $password = createPassword(8);
  12. echo "Your 8 character password is: $password";

Pro další informace doporučuji seriál na intervalu, zejména tyto články Perl-compatible regulární výrazy v PHP - tvrzení v praxi, podmíněné subvýrazyPerl-compatible regulární výrazy v PHP - lokální modifikátory, tvrzení a manuál php preg_match.

UPDATE 22.1.2009

Cílem tohoto článku nebylo vytvořit generátor bezpečných hesel a nebyl na něj kladen důraz, avšak na základě příspěvků v diskusi je potřeba původní kód přehodnotit.

Výsledek generátoru nezaručuje splnění všech daných podmínek a je tedy nutné výsledné heslo ještě doplnit o tři dané podmínky.

  1. // funkce vytvoří pole o unikátních náhodných číslech v rozsahu $count
  2. function uniqueRand($min, $max, $count) {
  3. // nutno doplnit ochrany typu min>max, count>(max-min) apod. to neni v prikladu reseno
  4. $arr=array();
  5. for ($i=0;$i<$count;$i++) {
  6. do {
  7. $r=mt_rand($min, $max);
  8. } while(in_array($r, $arr));
  9. $arr[$i]=$r;
  10. }
  11. return $arr;
  12. }
  13. function createPassword($length) {
  14. $chars="1234567890abcdefghijkmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
  15. $i=0;
  16. $password="";
  17. while ($i <= $length) {
  18. $password.=$chars{mt_rand(0,strlen($chars))};
  19. $i++;
  20. }
  21. // a ještě náhodně nahradíme malé, velké písmeno a číslo v řetězci
  22. $arr=uniqueRand(0, $length, 3);
  23. $password{$arr[0]}=chr(mt_rand(48, 57));
  24. $password{$arr[1]}=chr(mt_rand(65, 90));
  25. $password{$arr[2]}=chr(mt_rand(97, 122));
  26. return $password;
  27. }
  28. $password = createPassword(8);
  29. echo "Your 8 character password is: $password";