Menghasilkan kata sandi acak dalam php


190

Saya mencoba membuat kata sandi acak di php.

Namun saya mendapatkan semua 'a dan tipe pengembaliannya adalah tipe array dan saya ingin itu menjadi string. Ada ide tentang cara memperbaiki kode?

Terima kasih.

function randomPassword() {
    $alphabet = "abcdefghijklmnopqrstuwxyzABCDEFGHIJKLMNOPQRSTUWXYZ0123456789";
    for ($i = 0; $i < 8; $i++) {
        $n = rand(0, count($alphabet)-1);
        $pass[$i] = $alphabet[$n];
    }
    return $pass;
}

9
Tidak ada jawaban yang menggunakan penghasil angka acak yang aman , yang Anda inginkan untuk kata sandi.
Scott Arciszewski

4
Pengunjung harus mendapatkan informasi yang berpotensi terkait keamanan dari sumber yang dapat diperbarui dengan benar, bukan pertanyaan yang tertutup untuk jawaban baru. Saya menghapus jawaban untuk duplikat ini sehingga pengunjung akan membaca jawaban atas pertanyaan terbuka. (Jika pertanyaan ini pernah dibuka kembali, jawaban akan dihapus.)
Jeremy Banks

6
@JeremyBanks Nowhere menyatakan bahwa kata sandi yang aman secara kriptografis diperlukan. Bagi sebagian orang, jawaban yang digunakan /dev/randomsudah cukup karena pertanyaannya tidak meminta kata sandi " aman " (dan tidak boleh diedit untuk memuatnya karena akan mengubah arti pertanyaan aslinya). Meskipun saya semua untuk keamanan, saya pikir bom karpet ini tidak dipikirkan sepenuhnya. Seperti menggunakan mysql_*, jawabannya masih valid, tetapi harus ditandai sebagai tidak aman. Mungkin ini adalah sesuatu yang SO perlu sertakan sebagai perangkat lunak tambahan - kemampuan untuk memperingatkan kode tidak aman?
Jimbo

6
@JeremyBanks Bisakah Anda mengembalikan jawaban untuk pertanyaan ini? Hanya karena itu adalah duplikat bukan berarti jawabannya salah (saya tidak sengaja memilih untuk membuka kembali, saya setuju itu duplikat). Tidak masuk akal untuk menghapus jawaban, Pertimbangkan untuk menghapus pertanyaan ini dan memigrasikan jawaban ke pertanyaan lain (saya telah melihatnya selesai sebelumnya).
Naftali alias Neal

7
@JeremyBanks jika Anda ingin sesuatu tidak dibuka kembali, kunci saja. Kalau tidak, 99% orang akan membukanya kembali dan membuat kekacauan total. Secara pribadi saya benar-benar tidak setuju dengan menghapus jawaban yang sangat tinggi hanya seperti itu, tetapi tidak dapat memperdebatkan Anda tentang hal ini
Shadow Wizard adalah Ear For You

Jawaban:


258

Peringatan keamanan : rand()bukan generator nomor pseudorandom yang aman secara kriptografis. Cari di tempat lain untuk membuat string pseudorandom yang aman secara kriptografis di PHP .

Coba ini (gunakan strlensebagai ganti count, karena countpada senar selalu 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


24
Tampaknya lebih mudah digunakan $pass .= $alphabet[$n].
Matius

33
Membuat kata sandi menggunakan rand adalah ide yang sangat buruk. Ini bukan PRNG yang aman. (dan tidak mt_randjuga tidak lebih baik)
CodesInChaos

19
Pertanyaannya adalah tentang menghasilkan kata sandi . Kode untuk menghasilkan kata sandi jelas perlu menggunakan nomor acak yang aman.
CodesInChaos

10
Untuk alasan yang sama karena ini adalah bukan pertanyaan duplikat, jawaban ini tidak benar, karena pertanyaannya adalah tentang menghasilkan password dan tidak seorang string acak . Jawaban ini memberikan pendekatan yang sangat tidak aman untuk menghasilkan kata sandi. Silakan gunakan jawaban @ user3260409 di bawah ini, di mana openssl_random_pseudo_bytes()digunakan sebagai gantirand()
Maaf-Im-a-N00b

35
Saya telah melihat kode tidak aman Anda dalam produksi dan ingin menghentikannya di sumbernya. Anda PERLU cryptographically mengamankan keacakan kata sandi.
Scott Arciszewski 6-15

122

TL; DR:

  • Gunakan random_int()dan diberikan di random_str()bawah ini.
  • Jika belum random_int(), gunakan random_compat .

Penjelasan:

Karena Anda membuat kata sandi , Anda perlu memastikan bahwa kata sandi yang Anda hasilkan tidak dapat diprediksi, dan satu-satunya cara untuk memastikan properti ini hadir dalam implementasi Anda adalah dengan menggunakan generator nomor pseudorandom (CSPRNG) yang aman secara kriptografi aman .

Persyaratan untuk CSPRNG dapat disesuaikan untuk kasus umum string acak, tetapi tidak ketika keamanan terlibat.

Jawaban sederhana, aman, dan benar untuk pembuatan kata sandi di PHP adalah dengan menggunakan RandomLib dan jangan menemukan kembali roda. Perpustakaan ini telah diaudit oleh para pakar keamanan industri, dan juga saya.

Untuk pengembang yang lebih suka menciptakan solusi Anda sendiri, PHP 7.0.0 akan menyediakan random_int()untuk tujuan ini. Jika Anda masih menggunakan PHP 5.x, kami menulis polyfill PHP 5random_int() agar Anda dapat menggunakan API baru sebelum PHP 7 dirilis. Menggunakan random_int()polyfill kami mungkin lebih aman daripada menulis implementasi Anda sendiri.

Dengan generator integer acak aman di tangan, menghasilkan string acak aman lebih mudah daripada pie:

<?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;
}

2
RandomLib belum diperbarui selama lebih dari dua tahun sekarang. Menggunakannya pada PHP build baru-baru ini (7.1.25 dalam kasus saya) melempar peringatan penghentian untuk berbagai mcrypt_*fungsi. Saya dapat melihat pada utas masalah bahwa Anda telah memotong perpustakaan karena tidak bisa mendapatkan @ircmaxell, tetapi garpu Anda mengatakan 'build gagal' di Travis. Apakah Anda ingin memperbarui jawaban ini (yang masih muncul cukup tinggi di Google)?
Janus Bahs Jacquet

1
Tangkapan yang bagus! Itu perlu dihapus.
Scott Arciszewski

113

Saya tahu Anda mencoba membuat kata sandi dengan cara tertentu, tetapi Anda mungkin ingin melihat metode ini juga ...

$bytes = openssl_random_pseudo_bytes(2);

$pwd = bin2hex($bytes);

Ini diambil dari situs php.net dan menciptakan string yang dua kali panjang dari angka yang Anda masukkan dalam fungsi openssl_random_pseudo_bytes. Jadi di atas akan membuat kata sandi sepanjang 4 karakter.

Pendeknya...

$pwd = bin2hex(openssl_random_pseudo_bytes(4));

Panjang kata sandi akan dibuat 8 karakter.

Namun perlu dicatat bahwa kata sandi hanya berisi angka 0-9 dan huruf kecil af!


13
Jika Anda ingin password yang huruf besar, huruf kecil, dan angka, coba ini: gist.github.com/zyphlar/7217f566fc83a9633959
willbradley

@ زياد Mengatakan siapa? Jika generator menggunakan byte 7-bit saya akan setuju dengan Anda, tetapi openssl_random_pseudo_bytes()merupakan generator keacakan byte biner penuh yang kuat dan tidak perlu pengocokan lebih lanjut. Saya juga akan mengambil kesempatan untuk menunjukkan bahwa berbahaya untuk mengasumsikan susun beberapa metode enkripsi akan membuat sesuatu yang lebih acak, dalam beberapa kasus justru bisa menjadi sebaliknya karena akumulasi tabrakan hashing.
Havenard

56

Kode kecil dengan 2 baris.

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

function rand_string( $length ) {

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

}

echo rand_string(8);

dengan rand_string Anda dapat menentukan berapa banyak karakter yang akan dibuat.


21
Bagus, meskipun Anda tidak akan mendapatkan karakter berulang menggunakan pendekatan ini, yang mungkin tidak diinginkan.
Hobo

11
Fungsi ini mengerikan untuk menghasilkan kata sandi yang panjang. Pertama, jika $ length lebih panjang dari string $ chars, maka Anda tidak akan menerima string selama panjang yang Anda masukkan, tetapi panjang string chars. Juga, Anda dijamin hanya 1 dari setiap karakter tanpa duplikat. Ini juga tidak menjamin penggunaan huruf kapital atau angka yang cukup sering menjadi persyaratan (kecuali tentu saja jika panjang Anda lebih dari 26 karena kesalahan sebelumnya)
Programster

Bagaimana dengan @Programster dan @Hobo ini? substr(str_shuffle(str_repeat($chars,$length)),0,$length);
Charles-Édouard Coste

@ Charles-EdouardCoste tampaknya bekerja cukup baik (terutama jika Anda melempar beberapa karakter khusus). Meskipun masih tidak menjamin setidaknya satu dari setiap jenis karakter. Satu-satunya hal yang menggangguku adalah mengulang seluruh karakter yang ditentukan oleh panjang kata sandi yang diinginkan tetapi itu memastikan karakter pada kata sandi yang dihasilkan tidak harus unik dan tidak memiliki dampak kinerja yang nyata dalam sekali penggunaan.
Programster

Saya setuju. Mungkin lebih baik untuk tidak memilih algoritma pada jumlah barisnya. Ngomong-ngomong, jika tujuan utamanya hanya untuk menghasilkan kata sandi sementara ketika membuat pengguna baru di situs web, ini akan memenuhi kebutuhan, saya kira.
Charles-Édouard Coste

40

Jika Anda menggunakan PHP7, Anda bisa menggunakan random_int()fungsi ini:

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;
}

Jawaban lama di bawah:

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;
}

12
jangan gunakan mt_randuntuk menghasilkan kata sandi.
CodesInChaos

2
@CodesInChaos lebih baik daripada rand () yang digunakan oleh contoh di atas. openssl_random_pseudo_bytes () lebih disukai sesuai dengan manual PHP.
willbradley

4
@willbradley Kualitas benih sama buruknya mt_rand, jadi masih tidak cocok untuk penggunaan keamanan apa pun.
CodesInChaos

2
Anda melihat ini yang mengganggu saya + ChaosInCodes. Anda belum melihat pertanyaan, Anda baru saja membuat beberapa pernyataan umum mengulangi kepercayaan yang dipegang dengan buruk. Singkatnya: nasihat yang tepat untuk pertanyaan yang sama sekali berbeda. Kata sandi acak baik-baik saja. Mereka mungkin "x" hanya digunakan. Cukup jujur ​​jika Anda mendesain sistem Anda tanpa penguncian waktunya dan deteksi DOS dan "x mencoba -> terkunci" maka Anda salah melakukannya. TIDAK MUNGKIN untuk menebak kata sandi mt_rand dengan tindakan seperti itu di tempat. Sebaliknya menggunakan mt_rand tidak akan membuatnya LEBIH MUDAH untuk memaksa kata sandi. Itu tidak akan terjadi.
Tuan Heelis

1
Saya tidak akan menggunakan \ in$chars
CONvid19

36

Dalam satu baris:

substr(str_shuffle('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') , 0 , 10 )

11
Ini mencegah penggunaan kembali huruf yang sama seperti mereka hanya berputar-putar tetapi tidak muncul lebih dari satu kali.
nickdnk

8
Tidak perlu dikatakan, tidak ada yang harus mengoptimalkan fungsi pembuatan kata sandi mereka berdasarkan jumlah baris. Bahkan jika RNG yang digunakan ini aman (tidak), menghindari karakter yang berulang sambil menghasilkan kata sandi 10 karakter membawa Anda dari ~ 52 bit entropy ke ~ 50 bit entropy (~ 4x lebih cepat untuk di-crack). Jika Anda memperpanjang ini hingga 20 karakter, non-repetisi akan membawa Anda dari ~ 103 bit ke ~ 94 bit (~ 512x lebih cepat untuk di-crack).
Jeremy Banks

1
Metode ini mengingatkan saya pada cacat pada kode Enigma Lol
hatef

4
substr(str_shuffle(str_repeat($chars,$length)),0,$length); Entropy dipulihkan
Charles-Édouard Coste

27

Taruhan terbaik Anda adalah perpustakaan RandomLib oleh ircmaxell .

Contoh penggunaan:

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

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

Ini menghasilkan string yang lebih kuat acak daripada fungsi keacakan normal seperti shuffle()dan rand()(yang biasanya Anda inginkan untuk informasi sensitif seperti kata sandi, garam dan kunci).


4
Ini jawaban yang benar. Jangan gunakan rand()atau mt_rand().
Scott Arciszewski 6-15

1
Ini mungkin jawaban yang paling aman (tidak yakin bagaimana perbandingannya random_bytes), tetapi itu tidak membuat randjawaban salah.
Cerbrus


8
@ Cirrus: Tentu saja jawaban ini tidak membuat jawaban rand()salah. Mereka semua salah sendiri!
Deduplicator

14

Anda inginkan strlen($alphabet), bukan countdari konstanta alphabet(setara dengan 'alphabet').

Namun, randbukan fungsi acak yang cocok untuk tujuan ini. Hasilnya dapat dengan mudah diprediksi karena secara implisit diunggulkan dengan waktu saat ini. Selain itu, randtidak aman secara kriptografis; Oleh karena itu relatif mudah untuk menentukan keadaan internal dari output.

Sebagai gantinya, baca dari /dev/urandomuntuk mendapatkan data acak kriptografis.


14

Saya akan memposting jawaban karena beberapa jawaban yang ada sudah dekat tetapi ada satu:

  • ruang karakter yang lebih kecil daripada yang Anda inginkan sehingga memaksa kasar lebih mudah atau kata sandi harus lebih panjang untuk entropi yang sama
  • sebuah RNG yang tidak dianggap cryptographically aman
  • persyaratan untuk beberapa perpustakaan pihak ke-3 dan saya pikir mungkin menarik untuk menunjukkan apa yang diperlukan untuk melakukannya sendiri

Jawaban ini akan menghindari count/strlenmasalah karena keamanan kata sandi yang dihasilkan, setidaknya IMHO, melampaui cara Anda sampai di sana. Saya juga akan menganggap PHP> 5.3.0.

Mari kita pecahkan masalah menjadi beberapa bagian yaitu:

  1. gunakan beberapa sumber acak yang aman untuk mendapatkan data acak
  2. gunakan data itu dan nyatakan sebagai beberapa string yang dapat dicetak

Untuk bagian pertama, PHP> 5.3.0 menyediakan fungsi openssl_random_pseudo_bytes. Perhatikan bahwa sementara sebagian besar sistem menggunakan algoritma kriptografi yang kuat, Anda harus memeriksa sehingga kami akan menggunakan pembungkus:

/**
 * @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;
}

Untuk bagian kedua, kita akan menggunakan base64_encodekarena mengambil string byte dan akan menghasilkan serangkaian karakter yang memiliki alfabet yang sangat dekat dengan yang ditentukan dalam pertanyaan asli. Jika kami tidak keberatan memiliki +, /dan =karakter muncul di string terakhir dan kami ingin hasil setidaknya $npanjang karakter, kita bisa menggunakan:

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

The 3/4Faktor ini disebabkan oleh fakta bahwa base64 encoding menghasilkan string yang memiliki panjang setidaknya sepertiga lebih besar dari byte string yang. Hasilnya akan tepat untuk $nmenjadi kelipatan 4 dan hingga 3 karakter lebih lama. Karena karakter tambahan sebagian besar merupakan karakter padding =, jika kita karena suatu alasan memiliki batasan bahwa kata sandi menjadi panjang yang tepat, maka kita dapat memotongnya sesuai dengan panjang yang kita inginkan. Ini terutama karena untuk yang diberikan $n, semua kata sandi akan diakhiri dengan nomor yang sama, sehingga penyerang yang memiliki akses ke kata sandi hasil, akan memiliki hingga 2 karakter lebih sedikit untuk ditebak.


Untuk kredit tambahan, jika kami ingin memenuhi spesifikasi persis seperti dalam pertanyaan OP maka kami harus melakukan sedikit lebih banyak pekerjaan. Saya akan melupakan pendekatan konversi basis di sini dan pergi dengan yang cepat dan kotor. Keduanya harus menghasilkan lebih banyak keacakan daripada yang akan digunakan dalam hasil karena 62 alfabet panjang entri.

Untuk karakter tambahan dalam hasil, kita bisa membuangnya dari string yang dihasilkan. Jika kita mulai dengan 8 byte dalam string-byte kita, maka hingga sekitar 25% dari karakter base64 akan menjadi karakter yang "tidak diinginkan" ini, sehingga dengan hanya membuang karakter ini menghasilkan string yang tidak lebih pendek dari yang diinginkan OP. Kemudian kita cukup memotongnya untuk mencapai panjang yang tepat:

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

Jika Anda menghasilkan kata sandi yang lebih panjang, karakter padding =membentuk proporsi hasil perantara yang lebih kecil dan lebih kecil sehingga Anda dapat menerapkan pendekatan yang lebih ramping, jika mengeringkan kumpulan entropi yang digunakan untuk PRNG menjadi perhatian.


1
Terima kasih untuk tambahan ini. Tak satu pun dari jawaban yang ada mencatat bahwa openssl_random_pseudo_bytesbisa menghasilkan hasil yang lemah. Saya tidak menyadari bahwa itulah masalahnya.
Jeremy Banks

12

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

misalnya. e0m6ngefmj4

EDIT

Seperti yang saya sebutkan di komentar, panjangnya berarti bahwa serangan brute force akan bekerja lebih baik terhadapnya daripada serangan waktu sehingga tidak benar-benar relevan untuk khawatir tentang "seberapa aman generator acak itu." Keamanan, khusus untuk kasus penggunaan ini, perlu melengkapi kegunaan sehingga solusi di atas sebenarnya cukup baik untuk masalah yang diperlukan.

Namun, untuk berjaga-jaga jika Anda menemukan jawaban ini saat mencari generator string acak yang aman (seperti yang saya asumsikan sebagian orang berdasarkan pada tanggapannya), untuk sesuatu seperti membuat token, berikut adalah tampilan generator kode-kode tersebut:

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);
    }
}

1
PS - ini adalah PHP - hanya menggunakan \ untuk menunjukkan namespace global.
Bob Gregor

Kecuali bahwa uniqid tidak aman secara kriptografis. Gunakan rand () sebagai gantinya: base_convert (rand (78364164096, 2821109907455), 10, 36);
Benubird

7
@Benubird rand () juga tidak aman secara kriptografis, menurut manual PHP. Manual ini menyarankan openssl_random_pseudo_bytes () sebagai gantinya.
willbradley

Untuk sebagian besar kasus penggunaan, khususnya di mana penyerang tidak memiliki akses ke waktu yang tepat, ini baik-baik saja dan menghasilkan kata sandi "sementara" yang ramah atau kurang manusiawi. Jika kita menganggap ini ekstrim, panjang di sini jauh lebih merepotkan daripada fungsi apa yang digunakan untuk menghasilkan angka acak.
srcspider

Saya telah menambahkan contoh untuk menghasilkan string yang sepenuhnya aman, bagi mereka yang tertarik; tetapi sangat tidak menyarankan menggunakan ini saat membuat kata sandi sementara untuk pengguna. Bahkan menggunakan versi aman, masalah panjang masih berlaku.
srcspider

9

Satu lagi (hanya 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)), "=");
}

1
Membaca 1024 byte untuk mengompres menjadi hash kriptografi 128-bit dari entropi sedikit boros. Juga, fread()buffer ke 8192 byte secara default, jadi Anda akan selalu membaca sebanyak itu dari /dev/urandomdengan kode yang diberikan. Ini juga tidak akan berfungsi pada Windows. Kudos untuk menggunakan CSPRNG, meskipun.
Scott Arciszewski

9

Menjadi sedikit lebih pintar:

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

periksa di sini .


7

Gunakan kode sederhana ini untuk menghasilkan kata sandi yang kuat 12 panjang

$password_string = '!@#$%*&abcdefghijklmnpqrstuwxyzABCDEFGHJKLMNPQRSTUWXYZ23456789';
$password = substr(str_shuffle($password_string), 0, 12);

Ini sebenarnya (sangat?) Salah. Ini benar-benar menggunakan setiap char dari alfabet hanya sekali, sehingga sangat menyusut ruang semua nilai yang mungkin (relevan dengan cracking).
Radoslav Bodo

6

Coba ini dengan Huruf Besar, Huruf Kecil, Numerik dan Karakter Khusus

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
}

Katakanlah kita membutuhkan 10 Digit Pass

echo generatePassword(10);  

Output Contoh:

, IZCQ_IV \ 7

@wlqsfhT (d

1! 8 + 1 \ 4 @ uD


yang randfungsi sebenarnya tidak cryptographically mengamankan sehingga mungkin cukup berisiko untuk menghasilkan password menggunakannya
jeteon

3

Satu cepat Format sederhana, bersih dan konsisten jika itu yang Anda inginkan

$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);

3

Ini didasarkan pada jawaban lain pada halaman ini, https://stackoverflow.com/a/21498316/525649

Jawaban ini hanya menghasilkan karakter hex 0-9,a-f,. Untuk sesuatu yang tidak terlihat seperti hex, coba ini:

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 mengembalikan penyebaran karakter alfanumerik yang lebih luas
  • rtrimmenghapus =terkadang di akhir

Contoh:

  • 32eFVfGDg891Be5e7293e54z1D23110M3ZU3FMjb30Z9a740Ej0jz4
  • b280R72b48eOm77a25YCj093DE5d9549Gc73Jg8TdD9Z0Nj4b98760
  • 051b33654C0Eg201cfW0e6NA4b9614ze8D2FN49E12Y0zY557aUCb8
  • y67Q86ffd83G0z00M0Z152f7O2ADcY313gD7a774fc5FF069zdb5b7

Ini tidak dapat dikonfigurasi untuk membuat antarmuka untuk pengguna, tetapi untuk beberapa tujuan tidak apa-apa. Tambah jumlah karakter untuk menjelaskan kurangnya karakter khusus.


3
  1. Buat file dengan kode ini di dalamnya.
  2. Sebut saja seperti di komentar.

    <?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);
        }
    
    }
    
    ?>

2

Saya membuat skrip kata sandi yang lebih komprehensif dan aman. Ini akan membuat kombinasi dua huruf besar, dua huruf kecil, dua angka, dan dua karakter khusus. Total 8 karakter.

$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);

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

Ini sebenarnya (sangat?) Salah. Ini benar-benar menggunakan setiap char dari alfabet hanya sekali, sehingga sangat menyusut ruang semua nilai yang mungkin (relevan dengan cracking).
Radoslav Bodo

0

Menghasilkan kata sandi yang kuat dengan panjang 8 yang mengandung setidaknya satu huruf kecil, satu huruf besar, satu digit, dan satu karakter khusus. Anda dapat mengubah panjang kode juga.

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();

0

Fungsi ini akan menghasilkan kata sandi berdasarkan aturan dalam parameter

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;
}

0

Inilah pendapat saya tentang pembantu pembuatan kata sandi acak polos.

Ini memastikan bahwa kata sandi memiliki angka, huruf besar dan kecil serta minimal 3 karakter khusus.

Panjang kata sandi antara 11 dan 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);
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.