2010-09-11 53 views
5

Tôi cần trình tạo số ngẫu nhiên lớn (như, nói, 128-bit) lớn trong PHP. Tôi đã suy nghĩ trong việc lưu trữ số này trong một chuỗi dưới dạng thập lục phân. Lưu ý rằng điều này có nghĩa là cho một hệ thống đăng nhập đề cập đến sự cần thiết cho một số "ngẫu nhiên", vì vậy tôi đoán tôi thực sự cần nó là "ngẫu nhiên đủ" (vì tôi biết giả ngẫu nhiên là không bao giờ thực sự ngẫu nhiên).Tạo số ngẫu nhiên lớn

Thuật toán tôi đã suy nghĩ đã tạo ra số một chữ số hex tại một thời điểm, sau đó ghép tất cả. Như thế này:

$random = ''; 
for ($i = 0; $i < 32; ++$i) { 
    $digit = rand(0, 15); 
    $random .= ($digit < 10 ? $digit : ($digit - 10 + 'a')); 
} 
return $random; 

Tôi có thể tin tưởng chức năng này để trả lại số giả ngẫu nhiên hay tôi đang làm rối tung điều gì đó mà tôi thực sự không nên làm?

Trả lời

4

Hãy thử:

for ($str = '', $i = 0; $i < $len; $i++) { 
    $str .= dechex(mt_rand(0, 15)); 
} 
1

Tôi thường thấy điều này xử lý trong hệ thống đăng nhập bằng cách chỉ làm một cái gì đó như:

$salt = "big string of random stuff"; // you can generate this once like above 
$token = md5($salt . time()); // this will be your "unique" number 

băm MD5 có thể có va chạm, nhưng điều này là khá hiệu quả và rất đơn giản .

+0

Tại sao không chỉ thay thế $ muối bởi rand()? Nó sẽ không giống nhau ngẫu nhiên? Heck, có lẽ còn ngẫu nhiên hơn. – luiscubal

+0

đó là sự thật, nhưng bằng cách sử dụng rand() sẽ phủ nhận khả năng của bạn để so sánh băm dự kiến, nếu bạn muốn làm điều đó. VÍ DỤ.trong các tình huống mật khẩu, bạn thường sẽ băm mật khẩu của người dùng bằng một muối - vì bạn có lẽ là người duy nhất biết muối, sau đó bạn có thể so sánh số băm bạn đã ghi trong DB cho người dùng đó với "dự kiến băm "và bạn có thể xác minh rằng đó là chính xác. – julio

3

Tôi đã hỏi câu hỏi này vài năm trước và, kể từ đó, kiến ​​thức của tôi về chủ đề này đã được cải thiện.

Trước hết, tôi đã đề cập đến tôi muốn số ngẫu nhiên cho hệ thống đăng nhập. Hệ thống đăng nhập là cơ chế bảo mật. Điều này có nghĩa là bất kỳ trình tạo số ngẫu nhiên nào mà hệ thống đăng nhập dựa vào phải là an toàn mã hóa.

PHP randmt_rand không bảo mật về mặt mã hóa.

Trong những trường hợp này, tốt nhất là an toàn hơn xin lỗi. Có các trình tạo số ngẫu nhiên được thiết kế đặc biệt để bảo mật, đặc biệt là openssl_random_pseudo_bytes (rất tiếc là không phải lúc nào cũng có sẵn - bạn phải kích hoạt phần mở rộng OpenSSL để nó hoạt động). Trên * Các hệ thống NIX (chẳng hạn như Linux), các byte cũng đọc từ /dev/urandomcan be used.

Thật không may (vì mục đích của câu hỏi này), cả hai phương pháp này đều trả về dữ liệu nhị phân thay vì thập lục phân. May mắn thay, PHP đã có một chức năng để sửa lỗi này cho chúng tôi, bin2hex, hoạt động cho các chuỗi có độ dài bất kỳ.

Vì vậy, dưới đây là cách mã sẽ trông như thế:

function generate_secure_random_hex_string($length) { 
    // $length should be an even, non-negative number. 

    // Because each byte is represented as two hex digits, we'll need the binary 
    // string to be half as long as the hex string. 
    $binary_length = $length/2; 

    // First, we'll generate the random binary string. 
    $random_result = openssl_random_pseudo_bytes($binary_length, $cstrong); 

    if (!$cstrong) { 
     // The result is not cryptographically secure. Abort. 
     // die() is just a placeholder. 
     // There might be better ways to handle this error. 
     die(); 
    } 

    //Convert the result to hexadecimal 
    return bin2hex($random_result); 
} 

// Example: 
echo generate_secure_random_hex_string(32); 
0

Tính đến PHP 5.3:

function getRandomHex($num_bytes=4) { 
    return bin2hex(openssl_random_pseudo_bytes($num_bytes)); 
} 

Ví dụ bạn 128 bit:

$rand128 = getRandomHex(16);