2010-07-20 29 views
13

Tôi muốn tạo một băm trên toàn trang web được sử dụng làm muối trong việc tạo mã thông báo truy xuất mật khẩu. Tôi đã bouncing xung quanh stackoverflow cố gắng để có được một cảm giác của cách tốt nhất để làm điều này.Cách tốt nhất để tạo một "muối trang web" ngẫu nhiên được sử dụng trong việc tạo mã thông báo truy xuất mật khẩu là gì?

Dưới đây là quá trình thiết lập lại:

Khi người dùng yêu cầu một thiết lập lại mật khẩu email mã tạo ra một mã thông báo thu hồi:

$token = hash_hmac('sha256', $reset_hash* , $site_hash) 

* $ reset_hash là một hash được tạo ra sử dụng phpass HashPassword() chức năng, lưu trong bảng người dùng.

Sau đó tôi gửi mã thông báo trong URL tới địa chỉ email của người dùng. Họ nhấp vào trước khi mã thông báo hết giờ trong một giờ. Tôi phù hợp với nội dung gửi của họ với mã thông báo được tạo phía máy chủ thử thách. Nếu nó phù hợp, sau đó họ buộc phải chọn một mật khẩu mới, và sau đó đăng nhập.

Tôi muốn biết cách tốt nhất để tạo $ site_key. Tôi đang nghĩ đến việc sử dụng một băm HMAC được hạt giống bằng số ngẫu nhiên:

$site_key = hash_hmac('sha256', MCRYPT_DEV_RANDOM, MCRYPT_DEV_RANDOM); 

Điều này tạo ra một cái gì đó như thế này:

98bb403abbe62f5552f03494126a732c3be69b41401673b08cbfefa46d9e8999 

Đây sẽ là một phù hợp ngẫu nhiên được sử dụng cho mục đích này? Tôi có quá nhiều điều này, hoặc tiếp cận nó một cách sai lầm?

I was inspired to use HMAC by this answer

EDIT: Tôi cố gắng để tránh một 'câu hỏi bí mật' bước thúc giục của một số đồng nghiệp của tôi, vì vậy tôi muốn liên kết đặt lại để cung cấp một bước duy nhất để đặt lại mật khẩu. Do đó, mối quan tâm của tôi là quá trình này đủ an toàn để bảo vệ hệ thống chứa thông tin nhạy cảm.

RESOLVED, hiện tại: Tôi sẽ đi với một nonce như được mô tả bởi The Rook làm mã thông báo đặt lại. Cảm ơn tất cả mọi người cho các ý kiến ​​và phản hồi.

+0

Tôi phải nói đây là cách quá phức tạp. Tôi sử dụng mã thông báo gồm cả chữ và số ngẫu nhiên 6 ký tự đơn giản, với thời gian chờ như bạn đã nói và phát hiện cơ bản về sức mạnh vũ phu. – Fosco

+0

http: // stackoverflow.com/questions/1416060/if-i-make-the-muối-ngẫu nhiên-cho-mỗi-người-làm-như-do-i-xác thực-họ # đọc này, nó phải bao gồm hầu hết các khái niệm bạn cần phải hiểu. –

+0

@Fosco: bằng cách phát hiện brute-force cơ bản, bạn có nghĩa là giới hạn số lần mã thông báo có thể được xác thực trong thời gian đặt lại được cho phép không? –

Trả lời

22

Để bắt đầu, bạn không nói về muối. Bạn đang nói về một số Cryptographic Nonce và khi bạn nhập một mật khẩu, bạn nên sử dụng Mật mã Nonce. Trong trường hợp đặt lại mật khẩu, nó phải là một số ngẫu nhiên được lưu trữ trong cơ sở dữ liệu. Nó không phải là thuận lợi để có một "muối trang web".

Đầu tiên và trước hết tôi không thích uniqid() vì đây là thời gian tính toán nặng và time is a very weak seed. rand() vs mt_rand(), spoiler: rand() là tổng số crap.

Trong ứng dụng web, một nguồn tốt cho bí mật bảo mật là không chặn quyền truy cập vào một nhóm entropy chẳng hạn như /dev/urandom. Kể từ PHP 5.3, các ứng dụng PHP có thể sử dụng openssl_random_pseudo_bytes() và thư viện Openssl sẽ chọn nguồn entropy tốt nhất dựa trên hệ điều hành của bạn, dưới Linux, điều này có nghĩa là ứng dụng sẽ sử dụng /dev/urandom. Điều này code snip from Scott is pretty good:

function crypto_rand_secure($min, $max) { 
     $range = $max - $min; 
     if ($range < 0) return $min; // not so random... 
     $log = log($range, 2); 
     $bytes = (int) ($log/8) + 1; // length in bytes 
     $bits = (int) $log + 1; // length in bits 
     $filter = (int) (1 << $bits) - 1; // set all lower bits to 1 
     do { 
      $rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes))); 
      $rnd = $rnd & $filter; // discard irrelevant bits 
     } while ($rnd >= $range); 
     return $min + $rnd; 
} 

function getToken($length=32){ 
    $token = ""; 
    $codeAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 
    $codeAlphabet.= "abcdefghijklmnopqrstuvwxyz"; 
    $codeAlphabet.= ""; 
    for($i=0;$i<$length;$i++){ 
     $token .= $codeAlphabet[crypto_rand_secure(0,strlen($codeAlphabet))]; 
    } 
    return $token; 
} 
+0

@ TheRook: Cảm ơn vì điều này. Bạn có khuyên sử dụng $ password_token làm mã thông báo đầy đủ không. Nó sẽ được tốt hơn để sử dụng nonce để muối $ reset_hash để tạo một mã thông báo không được lưu trữ trong cơ sở dữ liệu, nhưng có thể xác minh khi người dùng nhấp vào URL đặt lại trong email? Điều này, một lần nữa, sẽ làm quá sức? Tôi đang cố gắng tránh một bước "câu hỏi bí mật" được thúc đẩy bởi một số đồng nghiệp của tôi, vì vậy tôi muốn liên kết đặt lại để cung cấp một bước duy nhất để đặt lại mật khẩu. –

+0

Tôi ghét nội dung "Câu hỏi bí mật", thường là một trong những điều khiến tôi "không còn quan tâm" trong trang web của bạn nữa. Nhưng tôi luôn hoang tưởng ai đó sẽ chiếm đoạt tài khoản email của tôi và sau đó đặt lại tất cả mật khẩu của tôi .... bạn không thể giành chiến thắng. Ngoài ra, bạn đã thử hỗ trợ OpenID? Tuyệt vời của nó! –

+0

Sử dụng tốt hơn bộ ký tự Base-64 đã sửa đổi cho URL (xem http://tools.ietf.org/html/rfc4648#section-5). – Gumbo

Các vấn đề liên quan