Tạo mật khẩu ngẫu nhiên trong php


190

Tôi đang cố gắng tạo một mật khẩu ngẫu nhiên trong php.

Tuy nhiên tôi đang nhận được tất cả 'a và kiểu trả về là kiểu mảng và tôi muốn nó là một chuỗi. Bất kỳ ý tưởng về cách sửa mã?

Cảm ơn.

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

9
Không có câu trả lời nào sử dụng trình tạo số ngẫu nhiên an toàn mà bạn muốn nhập mật khẩu.
Scott Arciszewski 04/07/2015

4
Khách truy cập nên nhận thông tin liên quan đến bảo mật tiềm năng từ một nguồn có thể được cập nhật chính xác, không phải là câu hỏi đóng cho câu trả lời mới. Tôi đang xóa các câu trả lời cho bản sao này để khách truy cập sẽ đọc câu trả lời cho câu hỏi mở thay thế. (Nếu câu hỏi này được mở lại, câu trả lời sẽ không bị xóa.)
Jeremy Banks

6
@JeremyBanks Không có câu hỏi nào nêu mật khẩu bảo mật bằng mật mã. Đối với một số người, câu trả lời sử dụng /dev/randomlà đủ vì câu hỏi không yêu cầu mật khẩu " an toàn " (và không nên chỉnh sửa để chứa thông tin đó vì nó sẽ thay đổi ý nghĩa của câu hỏi ban đầu). Mặc dù tôi là tất cả vì an ninh, tôi nghĩ rằng quả bom thảm này không được nghĩ đến đầy đủ. Giống như sử dụng mysql_*, các câu trả lời vẫn còn hiệu lực, nhưng nên được đánh dấu là không an toàn. Có lẽ đây là điều mà SO cần bao gồm như phần mềm bổ sung - khả năng cảnh báo mã không an toàn?
Jimbo

6
@JeremyBanks Bạn có thể vui lòng khôi phục câu trả lời cho câu hỏi này không? Chỉ vì nó là một bản sao, điều đó không có nghĩa là các câu trả lời sai (tôi vô tình bỏ phiếu để mở lại, tôi đồng ý rằng đó là một bản sao). Thật vô nghĩa khi xóa các câu trả lời, thay vào đó hãy xem xét loại bỏ câu hỏi này và di chuyển các câu trả lời sang câu hỏi khác (tôi đã thấy nó được thực hiện trước đó).
Naftali aka Neal

7
@JeremyBanks nếu bạn muốn một cái gì đó không được mở lại, hãy khóa nó. Nếu không, 99% mọi người sẽ mở lại nó và tạo ra một mớ hỗn độn. Cá nhân tôi hoàn toàn không đồng ý với việc xóa các câu trả lời được đánh giá cao như thế, nhưng không thể chống lại bạn về điều này
Shadow Wizard là Ear For You

Câu trả lời:


258

Cảnh báo bảo mật : rand()không phải là trình tạo số giả ngẫu nhiên an toàn bằng mật mã. Tìm nơi khác để tạo chuỗi giả ngẫu nhiên an toàn bằng mật mã trong PHP .

Hãy thử điều này (sử dụng strlen thay vì count, bởi vì counttrên một chuỗi luôn luôn 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
}

Bản giới thiệu: http://codepad.org/UL8k4aYK


24
Có vẻ đơn giản hơn để sử dụng $pass .= $alphabet[$n].
Matthew

33
Tạo mật khẩu bằng rand là một ý tưởng thực sự tồi tệ. Đó không phải là một PRNG an toàn. (và mt_randcũng không tốt hơn)
CodeInChaos

19
Câu hỏi là về việc tạo mật khẩu . Mã để tạo mật khẩu rõ ràng cần sử dụng các số ngẫu nhiên an toàn.
CodeInChaos

10
Đối với lý do tương tự như thế này là không một câu hỏi trùng lặp, câu trả lời này là không chính xác, vì câu hỏi là về tạo ra một mật khẩukhông một chuỗi ngẫu nhiên . Câu trả lời này cung cấp một cách tiếp cận không an toàn khủng khiếp để tạo mật khẩu. Vui lòng sử dụng câu trả lời của @ user3260409 bên dưới, nơi openssl_random_pseudo_bytes()được sử dụng thay vìrand()
Xin lỗi-Im-a-N00b

35
Tôi đã thấy mã không an toàn của bạn trong sản xuất và muốn dừng mã nguồn. Bạn CẦN ngẫu nhiên bảo mật bằng mật mã cho mật khẩu.
Scott Arciszewski 6/07/2015

120

TL; DR:

  • Sử dụng random_int()và chorandom_str() dưới đây.
  • Nếu bạn không có random_int(), hãy sử dụng Random_compat .

Giải trình:

Vì bạn đang tạo mật khẩu , bạn cần đảm bảo rằng mật khẩu bạn tạo không thể đoán trước được và cách duy nhất để đảm bảo thuộc tính này có trong triển khai của bạn là sử dụng trình tạo số giả ngẫu nhiên được bảo mật bằng mật mã (CSPRNG).

Yêu cầu đối với CSPRNG có thể được nới lỏng trong trường hợp chung của các chuỗi ngẫu nhiên, nhưng không phải khi có bảo mật.

Câu trả lời đơn giản, an toàn và chính xác để tạo mật khẩu trong PHP là sử dụng RandomLib và không phát minh lại bánh xe. Thư viện này đã được kiểm tra bởi các chuyên gia bảo mật công nghiệp, cũng như bản thân tôi.

Đối với các nhà phát triển thích phát minh ra giải pháp của riêng bạn, PHP 7.0.0 sẽ cung cấp random_int()cho mục đích này. Nếu bạn vẫn còn trên PHP 5.x, chúng tôi đã viết một polyfill PHP 5random_int() để bạn có thể sử dụng API mới trước khi PHP 7 được phát hành. Sử dụng random_int()polyfill của chúng tôi có thể an toàn hơn so với việc viết triển khai của riêng bạn.

Với một trình tạo số nguyên ngẫu nhiên an toàn trong tay, việc tạo một chuỗi ngẫu nhiên an toàn dễ dàng hơn so với 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 đã không được cập nhật trong hơn hai năm nay. Sử dụng nó trên một bản dựng PHP gần đây (7.1.25 trong trường hợp của tôi) đưa ra các cảnh báo không dùng cho các mcrypt_*chức năng khác nhau . Tôi có thể thấy trên một chủ đề vấn đề rằng bạn đã rẽ nhánh thư viện do không thể có được @ircmaxell, nhưng ngã ba của bạn nói 'xây dựng thất bại' trên Travis. Bạn có quan tâm để cập nhật câu trả lời này (vẫn còn hiển thị khá cao trên Google)?
Janus Bahs Jacquet

1
Nắm bắt tốt! Nó cần phải được loại bỏ.
Scott Arciszewski

113

Tôi biết bạn đang cố gắng tạo mật khẩu của mình theo một cách cụ thể, nhưng bạn cũng có thể muốn xem phương pháp này ...

$bytes = openssl_random_pseudo_bytes(2);

$pwd = bin2hex($bytes);

Nó được lấy từ trang php.net và nó tạo ra một chuỗi dài gấp đôi số bạn đặt trong hàm openssl_random_pseudo_bytes. Vì vậy, ở trên sẽ tạo ra một mật khẩu dài 4 ký tự.

Nói ngắn gọn...

$pwd = bin2hex(openssl_random_pseudo_bytes(4));

Sẽ tạo một mật khẩu dài 8 ký tự.

Tuy nhiên, xin lưu ý rằng mật khẩu chỉ chứa các số 0-9 và các chữ cái nhỏ af!


13
Nếu bạn muốn mật khẩu viết hoa, viết thường và số, hãy thử điều này: gist.github.com/zyphlar/7217f566fc83a9633959
willbradley

@ زياد Nói ai? Nếu trình tạo đang sử dụng byte 7 bit, tôi sẽ đồng ý với bạn, nhưng openssl_random_pseudo_bytes()là trình tạo ngẫu nhiên byte nhị phân đầy đủ mạnh mẽ và không cần xáo trộn thêm nữa. Ngoài ra, tôi sẽ có cơ hội chỉ ra rằng thật nguy hiểm khi giả định việc xếp chồng nhiều phương thức mã hóa sẽ khiến mọi thứ trở nên ngẫu nhiên hơn, trong một số trường hợp thực tế có thể ngược lại vì tích lũy các va chạm băm.
Havenard

56

Mã nhỏ với 2 dòng.

bản demo: http://codepad.org/5rHMHwnH

function rand_string( $length ) {

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

}

echo rand_string(8);

với rand_opes bạn có thể xác định số lượng ký tự sẽ được tạo.


21
Đẹp, mặc dù bạn sẽ không nhận được bất kỳ ký tự lặp đi lặp lại bằng cách sử dụng phương pháp này, điều này có thể không mong muốn.
Hobo

11
Chức năng này là khủng khiếp để tạo mật khẩu dài. Đầu tiên, nếu $ length dài hơn chuỗi ký tự $, thì bạn sẽ không nhận được chuỗi dài bằng độ dài bạn nhập, mà là độ dài của chuỗi ký tự. Ngoài ra, bạn chỉ được đảm bảo 1 trong mỗi nhân vật không có bản sao. Nó cũng không đảm bảo việc sử dụng chữ in hoa hoặc số thường là một yêu cầu (tất nhiên trừ khi độ dài của bạn lớn hơn 26 do lỗi trước đó)
Lập trình viên

Điều gì về @Programster và @Hobo này? substr(str_shuffle(str_repeat($chars,$length)),0,$length);
Charles-Édouard Coste

@ Charles-EdouardCoste dường như hoạt động đủ ổn (đặc biệt nếu bạn ném vào một số ký tự đặc biệt). Mặc dù nó vẫn không đảm bảo ít nhất một trong mỗi loại nhân vật. Điều duy nhất làm phiền tôi là lặp lại toàn bộ ký tự được đặt theo độ dài của mật khẩu mong muốn nhưng điều đó đảm bảo các ký tự trong mật khẩu được tạo không phải là duy nhất và không có tác động hiệu suất đáng chú ý trong một lần sử dụng.
Chương trình

Tôi đồng tình. Có lẽ tốt hơn là không chọn một thuật toán trên số dòng của nó. Nhân tiện, nếu mục tiêu chính chỉ là tạo mật khẩu tạm thời khi tạo người dùng mới trên trang web, thì điều này sẽ đáp ứng nhu cầu, tôi đoán vậy.
Charles-Édouard Coste

40

Nếu bạn đang dùng PHP7, bạn có thể sử dụng random_int()hàm:

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

Câu trả lời cũ dưới đây:

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
không sử dụng mt_randđể tạo mật khẩu.
CodeInChaos

2
@CodesInChaos tốt hơn rand (), đây là những gì ví dụ trên sử dụng. openssl_random_pseudo_bytes () được ưa thích theo hướng dẫn sử dụng PHP.
willbradley

4
@willbradley Chất lượng của hạt giống cũng tệ mt_rand, vì vậy nó vẫn không phù hợp cho bất kỳ mục đích bảo mật nào.
CodeInChaos

2
bạn thấy đây là điều làm tôi khó chịu + ChaosInCodes. Bạn chưa nhìn vào câu hỏi, bạn vừa đưa ra một số tuyên bố chung chung lặp đi lặp lại vô số niềm tin được tổ chức kém. Tóm lại: đúng lời khuyên cho một câu hỏi hoàn toàn khác. Mật khẩu ngẫu nhiên là tốt. Họ có thể chỉ "x" sử dụng. Thành thật mà nói nếu bạn đang thiết kế hệ thống của mình mà không khóa thời gian và phát hiện DOS và "x thử sau đó -> bị khóa" thì bạn đã làm sai. CNTT không thể đoán được mật khẩu mt_rand với các biện pháp như vậy. Ngược lại, sử dụng mt_rand sẽ không làm cho nó trở nên DỄ DÀNG để buộc mật khẩu. Nó sẽ không.
Ông Heelis

1
Tôi sẽ không sử dụng \ in$chars
CONvid19

36

Trong một dòng:

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

11
Điều này ngăn việc sử dụng lại các chữ cái giống nhau khi chúng chỉ xáo trộn xung quanh nhưng không xảy ra nhiều lần.
nickdnk

8
Không cần phải nói, không ai nên tối ưu hóa chức năng tạo mật khẩu của họ dựa trên số lượng dòng. Ngay cả khi RNG được sử dụng này là an toàn (không phải), việc tránh các ký tự lặp lại trong khi tạo mật khẩu 10 ký tự sẽ đưa bạn xuống từ ~ 52 bit entropy xuống ~ 50 bit entropy (nhanh hơn gấp 4 lần để bẻ khóa). Nếu bạn mở rộng ra 20 ký tự, việc không lặp lại sẽ đưa bạn xuống từ ~ 103 bit xuống ~ 94 bit (nhanh hơn ~ 512 lần để bẻ khóa).
Jeremy Banks

1
Phương pháp này làm tôi nhớ đến lỗ hổng trong mã Enigma Lol
ghét

4
substr(str_shuffle(str_repeat($chars,$length)),0,$length); Entropy được khôi phục
Charles-Édouard Coste

27

Đặt cược tốt nhất của bạn là thư viện RandomLib bởi ircmaxell .

Ví dụ sử dụng:

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

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

Nó tạo ra các chuỗi ngẫu nhiên mạnh hơn các hàm ngẫu nhiên thông thường như shuffle()rand()(đó là những gì bạn thường muốn cho thông tin nhạy cảm như mật khẩu, muối và khóa).


4
Đây là câu trả lời chính xác. Đừng sử dụng rand()hay mt_rand().
Scott Arciszewski 6/07/2015

1
Nó có thể là câu trả lời an toàn nhất (không chắc nó so sánh như thế nào random_bytes), nhưng điều đó không làm cho randcâu trả lời không chính xác.
Cerbrus 6/07/2015


8
@Cerbrus: Chắc chắn câu trả lời này không đưa ra câu trả lời bằng cách sử dụng rand()không chính xác. Họ không chính xác tất cả!
Ded

14

Bạn muốn strlen($alphabet), không phải countlà hằng số alphabet(tương đương với'alphabet' ).

Tuy nhiên, randkhông phải là một chức năng ngẫu nhiên phù hợp cho mục đích này. Đầu ra của nó có thể dễ dàng được dự đoán vì nó được gieo hạt giống với thời gian hiện tại. Ngoài ra,rand không an toàn về mặt mật mã; do đó tương đối dễ dàng để xác định trạng thái bên trong của nó từ đầu ra.

Thay vào đó, hãy đọc từ /dev/urandomđể có được dữ liệu ngẫu nhiên về mật mã.


14

Tôi sẽ đăng câu trả lời vì một số câu trả lời hiện có gần nhưng có một trong:

  • một không gian ký tự nhỏ hơn bạn muốn để việc bắt buộc dễ dàng hơn hoặc mật khẩu phải dài hơn cho cùng một entropy
  • một RNG không được coi là an toàn về mật mã
  • một yêu cầu đối với một số thư viện của bên thứ 3 và tôi nghĩ sẽ rất thú vị khi thể hiện những gì có thể cần để tự làm

Câu trả lời này sẽ tránh được count/strlenvấn đề vì tính bảo mật của mật khẩu được tạo, ít nhất là IMHO, vượt xa cách bạn đến đó. Tôi cũng sẽ giả sử PHP> 5.3.0.

Hãy chia vấn đề thành các phần cấu thành:

  1. sử dụng một số nguồn ngẫu nhiên an toàn để có được dữ liệu ngẫu nhiên
  2. sử dụng dữ liệu đó và biểu diễn nó dưới dạng một chuỗi có thể in

Đối với phần đầu tiên, PHP> 5.3.0 cung cấp hàm openssl_random_pseudo_bytes. Lưu ý rằng trong khi hầu hết các hệ thống sử dụng thuật toán mã hóa mạnh, bạn phải kiểm tra để chúng tôi sử dụng trình bao bọc:

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

Đối với phần thứ hai, chúng ta sẽ sử dụng base64_encodevì nó lấy một chuỗi byte và sẽ tạo ra một chuỗi các ký tự có bảng chữ cái rất gần với ký tự được chỉ định trong câu hỏi ban đầu. Nếu chúng tôi không phiền +, /và các =ký tự xuất hiện trong chuỗi cuối cùng và chúng tôi muốn có kết quả $ndài ít nhất là các ký tự, chúng tôi chỉ có thể sử dụng:

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

Các 3/4yếu tố là do thực tế rằng base64 mã hóa kết quả trong một chuỗi có chiều dài ít nhất một phần ba lớn hơn chuỗi byte. Kết quả sẽ chính xác $nlà bội số của 4 và tối đa 3 ký tự nếu không. Vì các ký tự phụ chủ yếu là ký tự đệm =, nếu vì lý do nào đó chúng tôi có một ràng buộc rằng mật khẩu có độ dài chính xác, thì chúng tôi có thể cắt nó theo độ dài chúng tôi muốn. Điều này đặc biệt bởi vì đối với một $nmật khẩu nhất định , tất cả mật khẩu sẽ kết thúc với cùng một số trong số này, do đó, kẻ tấn công có quyền truy cập vào mật khẩu kết quả, sẽ có ít hơn 2 ký tự để đoán.


Đối với tín dụng bổ sung, nếu chúng tôi muốn đáp ứng thông số kỹ thuật chính xác như trong câu hỏi của OP thì chúng tôi sẽ phải làm thêm một chút. Tôi sẽ từ bỏ cách tiếp cận chuyển đổi cơ sở ở đây và đi với một cách nhanh chóng và bẩn thỉu. Cả hai cần tạo ra nhiều tính ngẫu nhiên hơn dù sao sẽ được sử dụng trong kết quả vì bảng chữ cái dài 62 mục.

Đối với các ký tự phụ trong kết quả, chúng ta chỉ cần loại bỏ chúng khỏi chuỗi kết quả. Nếu chúng ta bắt đầu với 8 byte trong chuỗi byte của mình, thì có tới khoảng 25% các ký tự base64 sẽ là các ký tự "không mong muốn" này, do đó, việc loại bỏ các ký tự này sẽ dẫn đến một chuỗi không ngắn hơn OP muốn. Sau đó, chúng ta có thể cắt ngắn nó để đi xuống độ dài chính xác:

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

Nếu bạn tạo mật khẩu dài hơn, ký tự đệm =tạo thành một tỷ lệ nhỏ hơn và nhỏ hơn của kết quả trung gian để bạn có thể thực hiện một cách tiếp cận gọn gàng hơn, nếu việc sử dụng nhóm entropy được sử dụng cho PRNG là một mối quan tâm.


1
Cảm ơn vì sự bổ sung này. Không có câu trả lời hiện có lưu ý rằng openssl_random_pseudo_bytescó thể tạo ra một kết quả yếu. Tôi đã không nhận ra rằng đó là trường hợp.
Jeremy Banks

12

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

ví dụ. e0m6ngefmj4

BIÊN TẬP

Như tôi đã đề cập trong các bình luận, độ dài có nghĩa là các cuộc tấn công vũ phu sẽ hoạt động tốt hơn so với các cuộc tấn công thời gian để nó không thực sự liên quan đến việc lo lắng về "mức độ an toàn của trình tạo ngẫu nhiên". Bảo mật, đặc biệt cho trường hợp sử dụng này, cần bổ sung cho khả năng sử dụng để giải pháp trên thực sự đủ tốt cho vấn đề cần thiết.

Tuy nhiên, chỉ trong trường hợp bạn vấp phải câu trả lời này trong khi tìm kiếm một trình tạo chuỗi ngẫu nhiên an toàn (như tôi giả sử một số người đã dựa trên các phản hồi), đối với một số thứ như tạo mã thông báo, đây là cách một trình tạo mã như vậy sẽ như thế nào:

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 - đây là PHP - chỉ sử dụng \ để biểu thị không gian tên toàn cầu.
Bob Gregor

Ngoại trừ việc uniqid không bảo mật bằng mật mã. Sử dụng rand () thay vì: base_convert (rand (78364164096, 2821109907455), 10, 36);
Benubird

7
@Benubird rand () cũng không bảo mật bằng mật mã, theo hướng dẫn của PHP. Hướng dẫn sử dụng gợi ý openssl_random_pseudo_bytes ().
willbradley

Đối với hầu hết các trường hợp sử dụng, cụ thể là khi kẻ tấn công không có quyền truy cập vào thời gian chính xác, điều này hoàn toàn tốt và tạo ra một mật khẩu "tạm thời" thân thiện với con người ít nhiều. Nếu chúng ta đưa điều này đến cực độ thì độ dài ở đây rắc rối hơn nhiều thì chức năng nào đã được sử dụng để tạo ra số ngẫu nhiên.
srcspider

Tôi đã thêm một ví dụ để tạo các chuỗi bảo mật hoàn toàn, cho những người quan tâm; nhưng rất không khuyến khích sử dụng điều này khi tạo mật khẩu tạm thời cho người dùng. Ngay cả khi sử dụng phiên bản bảo mật, vấn đề về độ dài vẫn được áp dụng.
srcspider

9

Một số khác (chỉ dành cho 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
Đọc 1024 byte để nén thành hàm băm mật mã 128 bit của entropy thì hơi lãng phí. Ngoài ra, fread()bộ đệm tới 8192 byte theo mặc định, vì vậy bạn sẽ luôn đọc nhiều từ /dev/urandomvới mã đã cho. Điều này cũng sẽ không hoạt động trên Windows. Mặc dù vậy, Kudos đã sử dụng CSPRNG.
Scott Arciszewski

9

Thông minh hơn một chút:

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

kiểm tra xem nó ở đây .


7

Sử dụng mã đơn giản này để tạo mật khẩu trung bình 12 độ dài

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

Điều này thực sự (rất?) Sai. Nó thực sự sử dụng mỗi char từ bảng chữ cái chỉ một lần, do đó thu hẹp không gian của tất cả các giá trị có thể (liên quan đến bẻ khóa).
Radoslav Bodo

6

Hãy thử điều này với chữ in hoa, chữ nhỏ, chữ số và ký tự đặc biệt

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
}

Hãy nói rằng chúng ta cần 10 chữ số

echo generatePassword(10);  

Ví dụ đầu ra:

, IZCQ_IV \ 7

@wlqsfhT (d

1! 8 + 1 \ 4 @ uD


các randchức năng không thực sự mã hóa bảo mật vì vậy nó có thể khá nguy cơ để tạo ra một mật khẩu sử dụng nó
jeteon

3

Một cách nhanh chóng. Định dạng đơn giản, sạch sẽ và nhất quán nếu đó là những gì bạn muốn

$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

Điều này dựa trên một câu trả lời khác trên trang này, https://stackoverflow.com/a/21498316/525649

Câu trả lời này chỉ tạo ra các ký tự hex 0-9,a-f. Đối với một cái gì đó không giống như hex, hãy thử điều này:

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 trả về một phạm vi rộng hơn của ký tự chữ và số
  • rtrimloại bỏ =đôi khi ở cuối

Ví dụ:

  • 32eFVfGDg891Be5e7293e54z1D23110M3ZU3FMjb30Z9a740Ej0jz4
  • b280R72b48eOm77a25YCj093DE5d9549Gc73Jg8TdD9Z0Nj4b98760
  • 051b33654C0Eg201cfW0e6NA4b9614ze8D2FN49E12Y0zY557aUCb8
  • y67Q86ffd83G0z00M0Z152f7O2ADcY313gD7a774fc5FF069zdb5b7

Đây không phải là cấu hình để tạo giao diện cho người dùng, nhưng đối với một số mục đích thì không sao. Tăng số lượng ký tự để giải thích cho việc thiếu các ký tự đặc biệt.


3
  1. Tạo một tập tin với mã này trong đó.
  2. Gọi nó như trong các ý kiến.

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

Tôi đã tạo một tập lệnh mật khẩu toàn diện và an toàn hơn. Điều này sẽ tạo ra sự kết hợp của hai chữ hoa, hai chữ thường, hai số và hai ký tự đặc biệt. Tổng cộng 8 ký tự.

$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

Điều này thực sự (rất?) Sai. Nó thực sự sử dụng mỗi char từ bảng chữ cái chỉ một lần, do đó thu hẹp không gian của tất cả các giá trị có thể (liên quan đến bẻ khóa).
Radoslav Bodo

0

Tạo một mật khẩu mạnh có độ dài 8 chứa ít nhất một chữ cái viết thường, một chữ cái viết hoa, một chữ số và một ký tự đặc biệt. Bạn cũng có thể thay đổi độ dài trong mã.

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

Hàm này sẽ tạo mật khẩu dựa trên các quy tắc trong tham số

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

Đây là của tôi tại trình trợ giúp tạo mật khẩu đơn giản ngẫu nhiên.

Nó đảm bảo rằng mật khẩu có số, chữ in hoa và in thường cũng như tối thiểu 3 ký tự đặc biệt.

Độ dài của mật khẩu sẽ nằm trong khoảng từ 11 đến 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);
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.