Generowanie losowego hasła w php

190

Próbuję wygenerować losowe hasło w php.

Jednak dostaję wszystkie „a”, a zwracanym typem jest tablica typów i chciałbym, aby był to ciąg znaków. Wszelkie pomysły na poprawienie kodu?

Dzięki.

function randomPassword() {
    $alphabet = "abcdefghijklmnopqrstuwxyzABCDEFGHIJKLMNOPQRSTUWXYZ0123456789";
    for ($i = 0; $i < 8; $i++) {
        $n = rand(0, count($alphabet)-1);
        $pass[$i] = $alphabet[$n];
    }
    return $pass;
}
nunos
źródło
9
Żadna z odpowiedzi nie korzysta z bezpiecznego generatora liczb losowych , który jest potrzebny dla hasła.
Scott Arciszewski,
4
Odwiedzający powinni otrzymywać potencjalnie związane z bezpieczeństwem informacje ze źródła, które można odpowiednio aktualizować, a nie pytanie zamknięte na nowe odpowiedzi. Usuwam odpowiedzi na ten duplikat, aby odwiedzający przeczytali odpowiedzi na otwarte pytanie. (Jeśli to pytanie zostanie ponownie otwarte, odpowiedzi zostaną cofnięte.)
Jeremy Banks,
6
@JeremyBanks Nigdzie pytanie nie mówi, że wymagane jest bezpieczne hasło kryptograficzne . Dla niektórych osób /dev/randomwystarczające są odpowiedzi, ponieważ pytanie nie wymaga hasła „ bezpiecznego ” (i nie powinno być edytowane, aby je zawierało, ponieważ zmieniłoby to znaczenie pierwotnego pytania). Chociaż jestem za bezpieczeństwem, myślę, że ta dywanowa bomba nie została w pełni przemyślana. Podobnie jak przy użyciu mysql_*, odpowiedzi są nadal aktualne, ale należy je oznaczyć jako niepewne. Być może jest to coś, co SO musi uwzględnić jako dodatkowe oprogramowanie - możliwość ostrzegania przed niebezpiecznym kodem?
Jimbo,
6
@JeremyBanks Czy możesz przywrócić odpowiedzi na to pytanie? Tylko dlatego, że jest to duplikat, nie oznacza to, że odpowiedzi są błędne (przypadkowo głosowałem za ponownym otwarciem, zgadzam się, że jest to duplikat). Nie ma sensu usuwać odpowiedzi, rozważ zamiast tego usunięcie tego pytania i migrację odpowiedzi na inne pytanie (widziałem to już wcześniej).
Naftali alias Neal
7
@JeremyBanks, jeśli chcesz, aby coś nie zostało ponownie otwarte, zablokuj to. W przeciwnym razie 99% ludzi otworzy go ponownie i stworzy cały bałagan. Osobiście całkowicie nie zgadzam się z usunięciem tak wysoko ocenianych odpowiedzi, ale nie mogę z tym o to walczyć
Shadow Wizard is Ear For You

Odpowiedzi:

258

Ostrzeżenie bezpieczeństwa : rand()nie jest kryptograficznie bezpiecznym generatorem liczb pseudolosowych. Szukaj gdzie indziej, aby wygenerować kryptograficznie bezpieczny ciąg pseudolosowy w PHP .

Spróbuj tego (użyj strlenzamiast count, ponieważ countna ciąg jest zawsze 1):

function randomPassword() {
    $alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
    $pass = array(); //remember to declare $pass as an array
    $alphaLength = strlen($alphabet) - 1; //put the length -1 in cache
    for ($i = 0; $i < 8; $i++) {
        $n = rand(0, $alphaLength);
        $pass[] = $alphabet[$n];
    }
    return implode($pass); //turn the array into a string
}

Demo: http://codepad.org/UL8k4aYK

Neal
źródło
24
Wydaje się być prostszy w użyciu $pass .= $alphabet[$n].
Matthew
33
Generowanie hasła przy użyciu rand jest naprawdę złym pomysłem. To nie jest bezpieczny PRNG. (i nie mt_randma też lepszego)
CodesInChaos
19
Pytanie dotyczy wygenerowania hasła . Kod do wygenerowania hasła wyraźnie wymaga użycia bezpiecznych liczb losowych.
CodesInChaos
10
Z tego samego powodu, ponieważ jest to nie duplikat pytanie, to odpowiedź jest błędna, ponieważ pytanie o generowanie hasło i nie jest losowy ciąg . Ta odpowiedź stanowi strasznie niepewne podejście do generowania hasła. Proszę użyć odpowiedzi @ user3260409 poniżej, gdzie openssl_random_pseudo_bytes()jest używana zamiastrand()
Przepraszamy-Im-a-N00b
35
Widziałem twój niepewny kod w produkcji i chcę go zatrzymać u źródła. Ty POTRZEBUJESZ kryptograficznego losowość haseł.
Scott Arciszewski,
122

TL; DR:

  • Użyj random_int()i podane random_str()poniżej.
  • Jeśli nie masz random_int(), użyj random_compat .

Wyjaśnienie:

Ponieważ generujesz hasło , musisz upewnić się, że hasło, które generujesz, jest nieprzewidywalne, a jedynym sposobem zapewnienia obecności tej właściwości w implementacji jest zastosowanie kryptograficznie bezpiecznego generatora liczb pseudolosowych (CSPRNG).

Wymóg dotyczący CSPRNG można złagodzić w ogólnym przypadku losowych ciągów, ale nie w przypadku zabezpieczeń.

Prostą, bezpieczną i poprawną odpowiedzią na generowanie haseł w PHP jest użycie RandomLib i nie wymyślanie koła na nowo. Ta biblioteka została zbadana przez ekspertów branży bezpieczeństwa, a także przeze mnie.

Dla programistów, którzy wolą wymyślić własne rozwiązanie, PHP 7.0.0 zapewni random_int()do tego celu. Jeśli nadal korzystasz z PHP 5.x, napisaliśmy polifill dla PHP 5random_int() , abyś mógł używać nowego API przed wydaniem PHP 7. Korzystanie z naszego random_int()wypełniacza jest prawdopodobnie bezpieczniejsze niż napisanie własnej implementacji.

Mając pod ręką bezpieczny generator losowych liczb całkowitych, wygenerowanie bezpiecznego ciągu losowego jest łatwiejsze niż ciasto:

<?php
/**
 * Generate a random string, using a cryptographically secure 
 * pseudorandom number generator (random_int)
 * 
 * For PHP 7, random_int is a PHP core function
 * For PHP 5.x, depends on https://github.com/paragonie/random_compat
 * 
 * @param int $length      How many characters do we want?
 * @param string $keyspace A string of all possible characters
 *                         to select from
 * @return string
 */
function random_str(
    $length,
    $keyspace = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
) {
    $str = '';
    $max = mb_strlen($keyspace, '8bit') - 1;
    if ($max < 1) {
        throw new Exception('$keyspace must be at least two characters long');
    }
    for ($i = 0; $i < $length; ++$i) {
        $str .= $keyspace[random_int(0, $max)];
    }
    return $str;
}
Scott Arciszewski
źródło
2
RandomLib nie był aktualizowany od ponad dwóch lat. Użycie go w najnowszej kompilacji PHP (w moim przypadku 7.1.25) generuje ostrzeżenia o wycofaniu dla różnych mcrypt_*funkcji. Widzę w wątku , że rozwidliłeś bibliotekę, ponieważ nie jesteś w stanie uzyskać @ircmaxell, ale twój widelec mówi „kompilacja nie powiodła się” na Travis. Czy chcesz zaktualizować tę odpowiedź (która wciąż pojawia się dość wysoko w Google)?
Janus Bahs Jacquet
1
Dobry chwyt! To musi zostać usunięte.
Scott Arciszewski
113

Wiem, że próbujesz wygenerować hasło w określony sposób, ale możesz również przyjrzeć się tej metodzie ...

$bytes = openssl_random_pseudo_bytes(2);

$pwd = bin2hex($bytes);

Jest pobierany ze strony php.net i tworzy ciąg, który jest dwa razy dłuższy niż liczba podana w funkcji openssl_random_pseudo_bytes. Tak więc powyższe utworzy hasło o długości 4 znaków.

W skrócie...

$pwd = bin2hex(openssl_random_pseudo_bytes(4));

Utworzy hasło o długości 8 znaków.

Pamiętaj jednak, że hasło zawiera tylko cyfry 0–9 i małe litery af!

użytkownik3260409
źródło
13
Jeśli chcesz mieć wielkie litery, małe litery i cyfry, spróbuj tego: gist.github.com/zyphlar/7217f566fc83a9633959
willbradley
@ زياد Mówi kto? Jeśli generator używa 7-bitowych bajtów, zgodziłbym się z tobą, ale openssl_random_pseudo_bytes()jest potężnym generatorem losowości bajtów binarnych i nie wymaga dalszego tasowania. Zaryzykuję również wskazanie, że zakładanie, że stosowanie wielu metod szyfrowania sprawi, że wszystko stanie się bardziej losowe, w niektórych przypadkach może być wręcz przeciwnie z powodu kumulacji kolizji mieszających.
Havenard,
56

Mały kod z 2 liniami.

demo: http://codepad.org/5rHMHwnH

function rand_string( $length ) {

    $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    return substr(str_shuffle($chars),0,$length);

}

echo rand_string(8);

za pomocą rand_string możesz określić, ile znaków będzie tworzonych.

BSQ
źródło
21
Fajnie, chociaż przy takim podejściu nie otrzymasz powtarzających się postaci, co może być niepożądane.
Hobo,
11
Ta funkcja jest straszna przy generowaniu długich haseł. Po pierwsze, jeśli $ długość jest dłuższa niż ciąg $ chars, to nie otrzymasz ciągu tak długiego, jak wprowadzona długość, ale długość łańcucha znaków. Ponadto masz gwarancję tylko 1 każdej postaci bez duplikatów. Nie gwarantuje to również użycia dużej litery lub cyfry, co jest często wymogiem (z wyjątkiem oczywiście, jeśli twoja długość jest większa niż 26 z powodu poprzedniej usterki)
Programster
Co z tym @Programster i @Hobo? substr(str_shuffle(str_repeat($chars,$length)),0,$length);
Charles-Édouard Coste
@ Charles-EdouardCoste wydaje się działać wystarczająco dobrze (szczególnie jeśli dodajesz specjalne znaki). Chociaż nadal nie gwarantuje przynajmniej jednego z każdego rodzaju znaków. Jedyne, co mnie niepokoi, to powtarzanie całego zestawu znaków przez długość żądanego hasła, ale to zapewnia, że ​​znaki w wygenerowanym haśle nie muszą być unikalne i nie mają zauważalnego wpływu na wydajność przy jednym użyciu.
Programster
Zgadzam się. Prawdopodobnie lepiej nie wybierać algorytmu na podstawie jego liczby wierszy. Nawiasem mówiąc, jeśli głównym celem jest po prostu wygenerowanie tymczasowego hasła podczas tworzenia nowego użytkownika na stronie internetowej, to chyba spełniałoby potrzeby.
Charles-Édouard Coste
40

Jeśli korzystasz z PHP7, możesz użyć random_int()funkcji:

function generate_password($length = 20){
  $chars =  'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.
            '0123456789`-=~!@#$%^&*()_+,./<>?;:[]{}\|';

  $str = '';
  $max = strlen($chars) - 1;

  for ($i=0; $i < $length; $i++)
    $str .= $chars[random_int(0, $max)];

  return $str;
}

Stara odpowiedź poniżej:

function generate_password($length = 20){
  $chars =  'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.
            '0123456789`-=~!@#$%^&*()_+,./<>?;:[]{}\|';

  $str = '';
  $max = strlen($chars) - 1;

  for ($i=0; $i < $length; $i++)
    $str .= $chars[mt_rand(0, $max)];

  return $str;
}
PeeHaa
źródło
12
nie używaj mt_randdo generowania hasła.
CodesInChaos
2
@CodesInChaos jest lepszy niż rand (), czego używa powyższy przykład. openssl_random_pseudo_bytes () jest preferowany zgodnie z instrukcją PHP.
willbradley,
4
@willbradley Jakość nasion jest równie zła mt_rand, więc nadal nie nadaje się do celów bezpieczeństwa.
CodesInChaos
2
Widzisz, to mnie denerwuje + ChaosInCodes. Nie spojrzałeś na to pytanie, po prostu wypowiedziałeś kilka ogólnych stwierdzeń, powtarzając masę źle utrzymanych przekonań. W skrócie: odpowiednia rada na zupełnie inne pytanie. Losowe hasła są w porządku. Prawdopodobnie są to tylko znaki „x”. Szczerze mówiąc, jeśli projektujesz swój system bez czasowych blokad i wykrywania DOS i „x próbuje wtedy -> zablokowane”, robisz to źle. NIE MOŻNA odgadnąć hasła mt_rand przy zastosowaniu takich środków. I odwrotnie, użycie mt_rand nie sprawi, że brutalne wymuszenie hasła będzie łatwiejsze. Po prostu nie będzie.
Pan Heelis,
1
Nie $chars
użyłbym
36

W jednej linii:

substr(str_shuffle('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') , 0 , 10 )
Sandra
źródło
11
Zapobiega to ponownemu użyciu tych samych liter, ponieważ po prostu tasują, ale nie występują więcej niż jeden raz.
nickdnk
8
Nie trzeba dodawać, że nikt nie powinien optymalizować funkcji generowania hasła na podstawie liczby wierszy. Nawet jeśli używane RNG były bezpieczne (to nie jest), unikanie powtarzania znaków podczas generowania 10-znakowego hasła obniża cię z ~ 52 bitów entropii do ~ 50 bitów entropii (~ 4x szybciej do złamania). Jeśli rozszerzysz to do 20 znaków, brak powtarzalności obniży cię z ~ 103 bitów do ~ 94 bitów (~ 512x szybciej do złamania).
Jeremy Banks,
1
Ta metoda przypomina mi lukę w kodzie Enigmy Lol
hatef
4
substr(str_shuffle(str_repeat($chars,$length)),0,$length); Przywrócono Entropię
Charles-Édouard Coste
27

Twój najlepszy zakład to biblioteka RandomLib firmy ircmaxell .

Przykład użycia:

$factory = new RandomLib\Factory;
$generator = $factory->getGenerator(new SecurityLib\Strength(SecurityLib\Strength::MEDIUM));

$passwordLength = 8; // Or more
$randomPassword = $generator->generateString($passwordLength);

Tworzy ciągi, które są silniej losowe niż normalne funkcje losowości, takie jak shuffle()i rand()(to jest to, czego zazwyczaj potrzebujesz dla poufnych informacji, takich jak hasła, sole i klucze).

Duch Madary
źródło
4
To jest poprawna odpowiedź. Nie używaj rand()lub mt_rand().
Scott Arciszewski,
1
Może to być najbezpieczniejsza odpowiedź (nie wiem, jak się ma do porównania random_bytes), ale nie powoduje to, że randodpowiedzi są nieprawidłowe.
Cerbrus,
8
@Cerbrus: Upewnij się, że ta odpowiedź nie powoduje, że odpowiedzi są rand()nieprawidłowe. Wszystkie są nieprawidłowe same w sobie!
Deduplicator
14

Chcesz strlen($alphabet), a nie countstałej alphabet(odpowiednik 'alphabet').

Nie randjest to jednak odpowiednia funkcja losowa do tego celu. Jego wynik można łatwo przewidzieć, ponieważ jest domyślnie zaszczepiony bieżącym czasem. Ponadto randnie jest kryptograficznie bezpieczny; dlatego stosunkowo łatwo jest ustalić jego stan wewnętrzny na podstawie wyjścia.

Zamiast tego czytaj od, /dev/urandomaby uzyskać kryptograficznie losowe dane.

phihag
źródło
14

Zamierzam opublikować odpowiedź, ponieważ niektóre z istniejących odpowiedzi są bliskie, ale mają jedną z:

  • mniejsza przestrzeń znaków, niż chciałeś, aby wymuszenie brutalne było łatwiejsze lub hasło musi być dłuższe dla tej samej entropii
  • RNG , że nie uważa się za bezpieczne kryptograficznie
  • wymaganie dotyczące biblioteki innej firmy i pomyślałem, że może być interesujące, aby pokazać, co trzeba zrobić, aby to zrobić samodzielnie

Ta odpowiedź obejdzie count/strlen problem, ponieważ bezpieczeństwo wygenerowanego hasła, przynajmniej IMHO, wykracza poza to, jak się tam dostaniesz. Zakładam też, że PHP> 5.3.0.

Podzielmy problem na części składowe, które są:

  1. użyj bezpiecznego źródła losowości, aby uzyskać losowe dane
  2. użyj tych danych i przedstaw je jako ciąg znaków do wydrukowania

W pierwszej części PHP> 5.3.0 udostępnia tę funkcję openssl_random_pseudo_bytes. Zauważ, że chociaż większość systemów używa silnego algorytmu kryptograficznego, musisz to sprawdzić, abyśmy użyli opakowania:

/**
 * @param int $length
 */
function strong_random_bytes($length)
{
    $strong = false; // Flag for whether a strong algorithm was used
    $bytes = openssl_random_pseudo_bytes($length, $strong);

    if ( ! $strong)
    {
        // System did not use a cryptographically strong algorithm 
        throw new Exception('Strong algorithm not available for PRNG.');
    }        

    return $bytes;
}

W drugiej części wykorzystamy, base64_encodeponieważ zajmuje ona ciąg bajtów i tworzy serię znaków, których alfabet jest bardzo zbliżony do alfabetu podanego w pierwotnym pytaniu. Jeśli nie przeszkadza nam to +, /a =znaki pojawiają się w końcowym ciągu znaków i chcemy uzyskać wynik o $ndługości co najmniej znaków, możemy po prostu użyć:

base64_encode(strong_random_bytes(intval(ceil($n * 3 / 4))));

3/4Czynnikiem jest to spowodowane faktem, że base64 kodującego wyników w ciąg, który ma długość co najmniej jedną trzecią większy niż ciąg bajtów. Wynik będzie dokładny, ponieważ w przeciwnym $nrazie będzie wielokrotnością 4 i maksymalnie 3 znaków. Ponieważ dodatkowe znaki to głównie znak dopełniający =, jeśli z jakiegoś powodu mieliśmy ograniczenie, że hasło ma dokładną długość, możemy je skrócić do żądanej długości. Jest tak szczególnie dlatego, że dla danego $nhasła wszystkie hasła kończą się taką samą liczbą, aby osoba atakująca, która miała dostęp do hasła wynikowego, mogła zgadnąć maksymalnie 2 znaki.


Aby uzyskać dodatkowy kredyt, jeśli chcielibyśmy spełnić dokładną specyfikację jak w pytaniu PO, musielibyśmy wykonać trochę więcej pracy. Mam zamiar zrezygnować z podstawowego podejścia do konwersji i przejść do szybkiego i brudnego. Oba muszą generować więcej losowości, niż i tak zostanie użyte w wyniku z powodu alfabetu o długości 62 pozycji.

W przypadku dodatkowych znaków w wyniku możemy po prostu odrzucić je z powstałego ciągu. Jeśli zaczniemy od 8 bajtów w naszym łańcuchu bajtów, wówczas około 25% znaków base64 będzie tymi „niepożądanymi” znakami, więc po prostu odrzucenie tych znaków spowoduje, że łańcuch nie będzie krótszy niż oczekiwany PO. Następnie możemy po prostu go przyciąć, aby uzyskać dokładną długość:

$dirty_pass = base64_encode(strong_random_bytes(8)));
$pass = substr(str_replace(['/', '+', '='], ['', '', ''], $dirty_pass, 0, 8);

W przypadku generowania dłuższych haseł znak wypełniający =stanowi coraz mniejszą część wyniku pośredniego, dzięki czemu można zastosować bardziej uproszczone podejście, jeśli problem dotyczy wyczerpania puli entropii używanej przez PRNG.

jeteon
źródło
1
Dzięki za ten dodatek. W żadnej z istniejących odpowiedzi nie stwierdzono, że openssl_random_pseudo_bytesmoże to dać słaby wynik. Nie zdawałem sobie sprawy, że tak jest.
Jeremy Banks,
12

base_convert(uniqid('pass', true), 10, 36);

na przykład. e0m6ngefmj4

EDYTOWAĆ

Jak wspomniałem w komentarzach, długość oznacza, że ​​ataki z użyciem siły brutalnej działałyby przeciwko niemu lepiej niż ataki na czas, więc nie ma sensu martwić się o „jak bezpieczny był losowy generator”. Bezpieczeństwo, szczególnie w tym przypadku użycia, musi uzupełniać użyteczność, więc powyższe rozwiązanie jest w rzeczywistości wystarczające dla wymaganego problemu.

Jednak na wypadek, gdybyś natknął się na tę odpowiedź podczas wyszukiwania bezpiecznego generatora ciągów losowych (jak zakładam, niektórzy ludzie oparli się na odpowiedziach), na przykład w celu generowania tokenów, oto jak mógłby wyglądać generator takich kodów:

function base64urlEncode($data) {
    return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}

function secureId($length = 32) {

    if (function_exists('openssl_random_pseudo_bytes')) {
        $bytes = openssl_random_pseudo_bytes($length);
        return rtrim(strtr(base64_encode($bytes), '+/', '0a'), '=');
    }
    else { // fallback to system bytes

        error_log("Missing support for openssl_random_pseudo_bytes");

        $pr_bits = '';

        $fp = @fopen('/dev/urandom', 'rb');
        if ($fp !== false) {
            $pr_bits .= @fread($fp, $length);
            @fclose($fp);
        }

        if (strlen($pr_bits) < $length) {
            error_log('unable to read /dev/urandom');
            throw new \Exception('unable to read /dev/urandom');
        }

        return base64urlEncode($pr_bits);
    }
}
srcspider
źródło
1
PS - to jest PHP - wystarczy użyć \ do oznaczenia globalnej przestrzeni nazw.
Bob Gregor,
Tyle że uniqid nie jest bezpieczny kryptograficznie. Zamiast tego użyj rand (): base_convert (rand (78364164096, 2821109907455), 10, 36);
Benubird
7
@Benubird rand () również nie jest kryptograficznie bezpieczny, zgodnie z instrukcją PHP. Podręcznik sugeruje zamiast tego openssl_random_pseudo_bytes ().
willbradley,
W większości przypadków użycia, szczególnie gdy atakujący nie ma dostępu do dokładnego czasu, jest to całkowicie w porządku i tworzy ładne, mniej lub bardziej przyjazne dla człowieka „tymczasowe” hasło. Gdybyśmy doprowadzili to do skrajności, długość tutaj jest znacznie bardziej kłopotliwa niż to, jaka funkcja została użyta do wygenerowania liczby losowej.
srcspider
Dodałem przykład generowania w pełni bezpiecznych ciągów dla zainteresowanych; ale zdecydowanie nie zalecamy używania tego podczas generowania tymczasowych haseł dla użytkowników. Nawet przy korzystaniu z wersji bezpiecznej problem długości nadal obowiązuje.
srcspider
9

Kolejny (tylko Linux)

function randompassword()
{
    $fp = fopen ("/dev/urandom", 'r');
    if (!$fp) { die ("Can't access /dev/urandom to get random data. Aborting."); }
    $random = fread ($fp, 1024); # 1024 bytes should be enough
    fclose ($fp);
    return trim (base64_encode ( md5 ($random, true)), "=");
}
Askarel
źródło
1
Czytanie 1024 bajtów w celu skompresowania do 128-bitowego kryptograficznego skrótu entropii jest trochę marnotrawstwem. Ponadto fread()buforuje domyślnie 8192 bajtów, więc zawsze będziesz czytać tyle /dev/urandomz danego kodu. To również nie będzie działać w systemie Windows. Jednak pochwały za używanie CSPRNG.
Scott Arciszewski,
9

Być trochę mądrzejszym:

function strand($length){
  if($length > 0)
    return chr(rand(33, 126)) . strand($length - 1);
}

sprawdź tutaj .

Amir Fo
źródło
7

Użyj tego prostego kodu do wygenerowania med-strong hasła o długości 12

$password_string = '!@#$%*&abcdefghijklmnpqrstuwxyzABCDEFGHJKLMNPQRSTUWXYZ23456789';
$password = substr(str_shuffle($password_string), 0, 12);
Pablo Martinez
źródło
To jest rzeczywiście (bardzo?) Złe. W rzeczywistości używa każdego znaku z alfabetu tylko raz, co znacznie zmniejsza przestrzeń wszystkich możliwych wartości (związanych z pękaniem).
Radoslav Bodo
6

Spróbuj tego z wielkimi literami, małymi literami, cyframi i znakami specjalnymi

function generatePassword($_len) {

    $_alphaSmall = 'abcdefghijklmnopqrstuvwxyz';            // small letters
    $_alphaCaps  = strtoupper($_alphaSmall);                // CAPITAL LETTERS
    $_numerics   = '1234567890';                            // numerics
    $_specialChars = '`~!@#$%^&*()-_=+]}[{;:,<.>/?\'"\|';   // Special Characters

    $_container = $_alphaSmall.$_alphaCaps.$_numerics.$_specialChars;   // Contains all characters
    $password = '';         // will contain the desired pass

    for($i = 0; $i < $_len; $i++) {                                 // Loop till the length mentioned
        $_rand = rand(0, strlen($_container) - 1);                  // Get Randomized Length
        $password .= substr($_container, $_rand, 1);                // returns part of the string [ high tensile strength ;) ] 
    }

    return $password;       // Returns the generated Pass
}

Powiedzmy, że potrzebujemy 10 cyfr

echo generatePassword(10);  

Przykładowe dane wyjściowe:

, IZCQ_IV \ 7

@wlqsfhT (d

1! 8 + 1 \ 4 @ uD

Sanjeev
źródło
randfunkcja nie jest faktycznie kryptograficznego więc może to być całkiem ryzyko wygenerować hasło używając go
jeteon
3

Szybki. Prosty, czysty i spójny format, jeśli tego chcesz

$pw = chr(mt_rand(97,122)).mt_rand(0,9).chr(mt_rand(97,122)).mt_rand(10,99).chr(mt_rand(97,122)).mt_rand(100,999);
Cornelius Parkin
źródło
3

Jest to oparte na innej odpowiedzi na tej stronie, https://stackoverflow.com/a/21498316/525649

Ta odpowiedź generuje tylko znaki HEX, 0-9,a-f. Aby uzyskać coś, co nie wygląda jak hex, spróbuj tego:

str_shuffle(
  rtrim(
    base64_encode(bin2hex(openssl_random_pseudo_bytes(5))),
    '='
  ). 
  strtoupper(bin2hex(openssl_random_pseudo_bytes(7))).
  bin2hex(openssl_random_pseudo_bytes(13))
)
  • base64_encode zwraca szerszy zakres znaków alfanumerycznych
  • rtrimusuwa =czasem na końcu

Przykłady:

  • 32eFVfGDg891Be5e7293e54z1D23110M3ZU3FMjb30Z9a740Ej0jz4
  • b280R72b48eOm77a25YCj093DE5d9549Gc73Jg8TdD9Z0Nj4b98760
  • 051b33654C0Eg201cfW0e6NA4b9614ze8D2FN49E12Y0zY557aUCb8
  • y67Q86ffd83G0z00M0Z152f7O2ADcY313gD7a774fc5FF069zdb5b7

Nie jest to zbyt konfigurowalne do tworzenia interfejsu dla użytkowników, ale do niektórych celów jest to w porządku. Zwiększ liczbę znaków, aby uwzględnić brak znaków specjalnych.

Adam
źródło
3
  1. Utwórz plik z tym kodem.
  2. Nazwij to jak w komentarzach.

    <?php 
    
    /**
    * @usage  :
    *       include_once($path . '/Password.php');
    *       $Password = new Password;
    *       $pwd = $Password->createPassword(10);
    *       return $pwd;
    * 
    */
    
    class Password {
    
        public function createPassword($length = 15) {
            $response = [];
            $response['pwd'] = $this->generate($length);
            $response['hashPwd'] = $this->hashPwd( $response['pwd'] );
            return $response;
        }
    
        private function generate($length = 15) {
            $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*(){}/?,><";
            return substr(str_shuffle($chars),0,$length);
        }
    
        private function hashPwd($pwd) {
            return hash('sha256', $pwd);
        }
    
    }
    
    ?>
waz
źródło
2

Stworzyłem bardziej kompleksowy i bezpieczny skrypt hasła. Spowoduje to utworzenie kombinacji dwóch wielkich liter, dwóch małych liter, dwóch cyfr i dwóch znaków specjalnych. Łącznie 8 znaków.

$char = [range('A','Z'),range('a','z'),range(0,9),['*','%','$','#','@','!','+','?','.']];
$pw = '';
for($a = 0; $a < count($char); $a++)
{
    $randomkeys = array_rand($char[$a], 2);
    $pw .= $char[$a][$randomkeys[0]].$char[$a][$randomkeys[1]];
}
$userPassword = str_shuffle($pw);
monrejames
źródło
1
//define a function. It is only 3 lines!   
function generateRandomPassword($length = 5){
    $chars = "0123456789bcdfghjkmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ";
    return substr(str_shuffle($chars),0,$length);
}

//usage
echo generateRandomPassword(5); //random password legth: 5
echo generateRandomPassword(6); //random password legth: 6
echo generateRandomPassword(7); //random password legth: 7
hakiko
źródło
To jest rzeczywiście (bardzo?) Złe. W rzeczywistości używa każdego znaku z alfabetu tylko raz, co znacznie zmniejsza przestrzeń wszystkich możliwych wartości (związanych z pękaniem).
Radoslav Bodo
0

Generuje silne hasło o długości 8 zawierające co najmniej jedną małą literę, jedną wielką literę, jedną cyfrę i jeden znak specjalny. Możesz także zmienić długość w kodzie.

function checkForCharacterCondition($string) {
    return (bool) preg_match('/(?=.*([A-Z]))(?=.*([a-z]))(?=.*([0-9]))(?=.*([~`\!@#\$%\^&\*\(\)_\{\}\[\]]))/', $string);
}

$j = 1;

function generate_pass() {
    global $j;
    $allowedCharacters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~`!@#$%^&*()_{}[]';
    $pass = '';
    $length = 8;
    $max = mb_strlen($allowedCharacters, '8bit') - 1;
    for ($i = 0; $i < $length; ++$i) {
        $pass .= $allowedCharacters[random_int(0, $max)];
    }

    if (checkForCharacterCondition($pass)){
        return '<br><strong>Selected password: </strong>'.$pass;
    }else{
        echo 'Iteration '.$j.':  <strong>'.$pass.'</strong>  Rejected<br>';
        $j++;
        return generate_pass();
    }

}

echo generate_pass();
Zihad Ul Islam
źródło
0

Ta funkcja wygeneruje hasło na podstawie reguł w parametrach

function random_password( $length = 8, $characters = true, $numbers = true, $case_sensitive = true, $hash = true ) {

    $password = '';

    if($characters)
    {
        $charLength = $length;
        if($numbers) $charLength-=2;
        if($case_sensitive) $charLength-=2;
        if($hash) $charLength-=2;
        $chars = "abcdefghijklmnopqrstuvwxyz";
        $password.= substr( str_shuffle( $chars ), 0, $charLength );
    }

    if($numbers)
    {
        $numbersLength = $length;
        if($characters) $numbersLength-=2;
        if($case_sensitive) $numbersLength-=2;
        if($hash) $numbersLength-=2;
        $chars = "0123456789";
        $password.= substr( str_shuffle( $chars ), 0, $numbersLength );
    }

    if($case_sensitive)
    {
        $UpperCaseLength = $length;
        if($characters) $UpperCaseLength-=2;
        if($numbers) $UpperCaseLength-=2;
        if($hash) $UpperCaseLength-=2;
        $chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        $password.= substr( str_shuffle( $chars ), 0, $UpperCaseLength );
    }

    if($hash)
    {
        $hashLength = $length;
        if($characters) $hashLength-=2;
        if($numbers) $hashLength-=2;
        if($case_sensitive) $hashLength-=2;
        $chars = "!@#$%^&*()_-=+;:,.?";
        $password.= substr( str_shuffle( $chars ), 0, $hashLength );
    }

    $password = str_shuffle( $password );
    return $password;
}
Behiry
źródło
0

Oto mój przypadkowy pomocnik w generowaniu zwykłego hasła.

Zapewnia, że ​​hasło ma cyfry, wielkie i małe litery, a także co najmniej 3 znaki specjalne.

Długość hasła będzie wynosić od 11 do 30.

function plainPassword(): string
{
    $numbers = array_rand(range(0, 9), rand(3, 9));
    $uppercase = array_rand(array_flip(range('A', 'Z')), rand(2, 8));
    $lowercase = array_rand(array_flip(range('a', 'z')), rand(3, 8));
    $special = array_rand(array_flip(['@', '#', '$', '!', '%', '*', '?', '&']), rand(3, 5));

    $password = array_merge(
        $numbers,
        $uppercase,
        $lowercase,
        $special
    );

    shuffle($password);

    return implode($password);
}
Sebastian Sulinski
źródło