2012-12-30 35 views
9

Tôi đang phát triển một trang web trong php 5.4 và tôi đã tự hỏi đó là tốt hơn để sử dụng để gen một muối ngẫu nhiên cho bảo mật mật khẩu?tôi có nên sử dụng urandom hoặc openssl_random_pseudo_bytes không?

$salt = sha1(openssl_random_pseudo_bytes(23)); 

hoặc

$seed = ''; 
$a = @fopen('/dev/urandom','rb'); 
$seed .= @fread($a,23); 
$salt = sha1(seed); 

hay nên tôi chỉ đi với:

$salt = openssl_random_pseudo_bytes(40); 

hoặc

$salt = ''; 
$a = @fopen('/dev/urandom','rb'); 
$salt .= @fread($a,23); 
+4

Sử dụng 'sha1()' sẽ làm giảm đáng kể hiệu quả của muối ngẫu nhiên vì nó sẽ chuyển đổi nó thành chuỗi có 40 ký tự và chỉ chứa ký tự 0-9 và a-f. Sẽ có ít kết hợp hơn (có nghĩa là ít ngẫu nhiên hơn) nếu bạn chỉ sử dụng 40 byte từ 'openssl_random_pseudo_bytes()' –

+0

tôi đang đi với cả hai đề xuất của bạn – John

Trả lời

10

Đối với mục đích bảo mật mà bạn là nên sử dụng openssl_random_pseudo_bytes. OpenSSL chăm sóc thu thập đủ entropy để phục vụ bạn ngẫu nhiên tốt. /dev/urandom được tạo ra để không bao giờ là khối và có thể bị lừa đưa bạn không phải các byte ngẫu nhiên.

Với byte ngẫu nhiên, bạn không cần phải chạy chúng thông qua SHA1.

Nói tóm lại tất cả, làm:

$salt = openssl_random_pseudo_bytes(40, $cstrong); 
if (! $cstrong) { 
    exit('This should not happen'); 
} 
+1

Thực ra, 'openssl_rand_pseudo_bytes' không _guarantee_ true randomness, bất kỳ hơn '/ dev/urandom'; đó là ý nghĩa của 'pseudo' trong tên. Tuy nhiên, trong thực tế, cả hai sản phẩm đều không thể phân biệt được đầu ra ngẫu nhiên bởi bất kỳ phương tiện đã biết nào. –

+0

@IlmariKaronen Tất nhiên bạn không nhận được sự ngẫu nhiên thực sự. Tôi chỉ viết “tốt”; những gì OpenSSL gọi là "mạnh mẽ về mặt mã hóa". Đó là lý do tại sao tôi đưa vào thử nghiệm để kiểm tra xem kết quả có mạnh mẽ về mặt mã hóa hay không. – kmkaplan

+1

[Không sử dụng OpenSSL] (https://github.com/ramsey/uuid/issues/80). –

9

Trong thực tế, hầu như chắc chắn không có sự khác biệt.

Cả hai openssl_random_pseudo_bytes/dev/urandom cung cấp nguồn mật mã giả bảo mật mã hóa. Không được đảm bảo là thực sự là ngẫu nhiên, nhưng trong thực tế, cả hai đều được cho là không thể phân biệt được với sự ngẫu nhiên thực sự của bất kỳ kỹ thuật đã biết hoặc có thể dự đoán trước nào.

Kmkaplan là kỹ thuật chính xác trong lưu ý rằng /dev/urandom có thể trở lại đầu ra về mặt lý thuyết có thể dự đoán điều kiện nhất định, như đã nêu trong man unrandom:

"Một đọc từ /dev/urandom thiết bị sẽ không chặn chờ đợi để biết thêm Do đó, nếu không có đủ entropy trong nhóm entropy, các giá trị trả về sẽ dễ bị tấn công về mặt lý thuyết đối với một cuộc tấn công mã hóa trên các thuật toán được sử dụng bởi trình điều khiển. nhưng về mặt lý thuyết có thể là một cuộc tấn công như vậy có thể tồn tại Nếu đây là một mối quan tâm trong ứng dụng của bạn n, sử dụng /dev/ngẫu nhiên thay thế. "

Tuy nhiên, điều này cũng thực sự thực sự của openssl_random_pseudo_bytes (mà calls OpenSSL chức năng RAND_pseudo_bytes nội bộ), như đã nêu trong OpenSSL documentation:

"RAND_pseudo_bytes() đặt num giả ngẫu nhiên byte vào buf Các chuỗi byte giả ngẫu nhiên được tạo ra bởi RAND_pseudo_bytes() sẽ là duy nhất nếu chúng có đủ độ dài, nhưng không nhất thiết phải không thể đoán trước, chúng có thể được sử dụng cho các mục đích không mã hóa và cho các mục đích nhất định trong tiếng kêu giao thức ptographic, nhưng thường không dành cho việc tạo khóa vv"

Cả những cảnh báo này thực sự nên scare bạn từ việc sử dụng những phương pháp — những điểm yếu mà họ mô tả là chỉ lý thuyết, ngoại trừ có thể là trong những trường hợp giả tạo nào đó (chẳng hạn như trên một không đĩa thiết bị nhúng với không RNG phần cứng ngay lập tức sau khi boot- và không nên quan tâm thực tế trong các tình huống mà PHP thường được triển khai.

Kết quả là, không phải các phương pháp tạo số ngẫu nhiên này sẽ là the weakest link trong hệ thống mật mã của bạn. Nếu bạn cảm thấy hoang tưởng, bạn thậm chí có thể sử dụng cả hai.


Ps. Một lợi thế của openssl_random_pseudo_bytes là nó cũng hoạt động trên Windows. Mặt khác, /dev/urandom khả dụng trên Unix ngay cả khi phần mở rộng OpenSSL PHP chưa được cài đặt. Vì vậy, đối với tính di động tối đa, bạn thực sự nên thực hiện hỗ trợ cho cả hai.

Ngoài ra, hãy luôn kiểm tra xem bạn có thực sự nhận được nhiều byte như bạn dự kiến ​​hay không; ví dụ: mã dựa trên /dev/urandom trong câu hỏi của bạn ở trên có thể âm thầm trả về một chuỗi trống trên các hệ thống như Windows nơi /dev/urandom không tồn tại.

+0

'RAND_pseudo_bytes' và' openssl_random_pseudo_bytes' trả về mã cho bạn biết "nếu các byte được tạo có mã hóa mạnh không". – kmkaplan