2008-09-10 47 views
12

Tôi đang tìm kiếm một cách, đặc biệt trong PHP mà tôi sẽ được đảm bảo luôn nhận được khóa duy nhất.Tạo khóa duy nhất

Tôi đã làm như sau:

strtolower(substr(crypt(time()), 0, 7)); 

Nhưng tôi đã phát hiện ra rằng một lần trong một thời gian tôi kết thúc với một chìa khóa trùng lặp (hiếm, nhưng thường đủ).

Tôi cũng đã nghĩ đến việc thực hiện:

strtolower(substr(crypt(uniqid(rand(), true)), 0, 7)); 

Nhưng theo trang web PHP, uniqid() có thể, nếu uniqid() được gọi hai lần trong micro cùng, nó có thể tạo ra các phím tương tự. Tôi nghĩ rằng việc bổ sung rand() mà nó hiếm khi xảy ra, nhưng vẫn có thể.

Sau khi các dòng được đề cập ở trên, tôi cũng xóa các ký tự như L và O để nó ít gây nhầm lẫn cho người dùng. Điều này có thể là một phần của nguyên nhân cho các bản sao, nhưng vẫn cần thiết.

Một tùy chọn tôi có ý nghĩ là tạo trang web sẽ tạo khóa, lưu trữ khóa đó trong cơ sở dữ liệu, đảm bảo nó hoàn toàn độc đáo.

Bất kỳ suy nghĩ nào khác? Có bất kỳ trang web nào ở đó đã làm điều này có một số loại API hoặc chỉ trả lại khóa. Tôi tìm thấy http://userident.com nhưng tôi không chắc liệu các phím sẽ hoàn toàn độc đáo hay không.

Điều này cần chạy dưới nền mà không có bất kỳ thao tác nhập nào của người dùng.

+0

Tại sao mật khẩu cần phải hoàn toàn độc đáo? –

+0

Tôi cho rằng mật mã chỉ là vì bạn cần phải mã hóa giá trị, nó không liên quan gì đến việc tạo ra giá trị duy nhất, phải không? –

+0

Xem thêm: [Chức năng PHP để tạo ra UUID v4] (http://stackoverflow.com/a/15875555/1338292). –

Trả lời

19

Chỉ có 3 cách để tạo ra giá trị duy nhất, chứ không phải họ có mật khẩu, ID người dùng, v.v .:

  1. Sử dụng một GUID máy phát điện hiệu quả - đây là những lâu và không thể được thu nhỏ. Nếu bạn chỉ sử dụng một phần bạn FAIL.
  2. Ít nhất một phần của số này được tạo ra tuần tự ngoài một chuỗi. Bạn có thể thêm lông tơ hoặc mã hóa để làm cho nó trông ít tuần tự hơn. Lợi thế là họ bắt đầu ngắn - bất lợi là họ yêu cầu một nguồn duy nhất. Công việc xung quanh cho giới hạn nguồn đơn là có nguồn được đánh số, vì vậy bạn bao gồm [source #] + [seq #] và sau đó mỗi nguồn có thể tạo chuỗi riêng của nó.
  3. Tạo chúng qua một số phương tiện khác và sau đó kiểm tra chúng dựa trên lịch sử duy nhất của các giá trị được tạo trước đó.

Bất kỳ phương pháp nào khác không được đảm bảo. Hãy nhớ, về cơ bản bạn đang tạo ra một số nhị phân (nó là một máy tính), nhưng sau đó bạn có thể mã hóa nó trong hệ thập lục phân, thập phân, Base64, hoặc một danh sách từ. Chọn một mã hóa phù hợp với việc sử dụng của bạn. Thông thường cho người dùng nhập dữ liệu bạn muốn một số biến thể của Base32 (mà bạn ám chỉ).

Lưu ý về GUIDS: Chúng đạt được độ bền độc đáo từ độ dài và phương pháp được sử dụng để tạo ra chúng. Bất kỳ điều gì dưới 128 bit đều không an toàn. Ngoài việc tạo số ngẫu nhiên, có những đặc điểm đi vào GUID để làm cho nó độc đáo hơn. Hãy nhớ rằng chúng chỉ thực tế độc đáo, không hoàn toàn độc đáo. Có thể, mặc dù thực tế không thể có một bản sao.

Lưu ý cập nhật khoảng GUIDS: Kể từ khi viết những dòng này tôi biết được rằng nhiều máy phát điện GUID sử dụng một bộ tạo số ngẫu nhiên mã hóa an toàn (khó hoặc không thể dự đoán số tiếp theo được tạo ra, và không có khả năng lặp lại). Thực tế có 5 khác nhau UUID algorithms. Thuật toán 4 là những gì Microsoft hiện đang sử dụng cho API thế hệ GUID Windows. Một GUID là việc Microsoft triển khai tiêu chuẩn UUID.

Cập nhật: Nếu bạn muốn 7-16 ký tự thì bạn cần phải sử dụng một trong hai phương pháp 2 hoặc 3.

Tóm lại: Thành thật mà nói không có những điều như hoàn toàn độc đáo. Ngay cả khi bạn đã đi với một máy phát điện tuần tự bạn cuối cùng sẽ chạy ra khỏi lưu trữ bằng cách sử dụng tất cả các nguyên tử trong vũ trụ, do đó lặp lại trên chính mình và lặp đi lặp lại. Hy vọng duy nhất của bạn sẽ là cái chết nhiệt của vũ trụ trước khi đạt đến điểm đó.

Ngay cả trình tạo số ngẫu nhiên tốt nhất cũng có khả năng lặp lại bằng tổng kích thước của số ngẫu nhiên bạn đang tạo. Lấy một phần tư ví dụ. Nó là một trình tạo bit ngẫu nhiên hoàn toàn, và tỷ lệ lặp lại của nó là 1 trong 2.

Vì vậy, tất cả đều đi xuống ngưỡng duy nhất của bạn. Bạn có thể có 100% tính duy nhất trong 8 chữ số cho 1.099.511.627.776 số bằng cách sử dụng một chuỗi và sau đó mã hóa base32. Bất kỳ phương pháp nào khác không liên quan đến việc kiểm tra danh sách các số trong quá khứ chỉ có tỷ lệ cược bằng n/1.099,511,627,776 (trong đó n = số các số trước được tạo) không phải là duy nhất.

+0

Xin chào, bạn có đọc thêm về số 2 không, tôi muốn sử dụng loại tạo mã này bằng cách sử dụng các "nguồn" khác nhau, Cảm ơn. – Jon

+0

@ Jon: Tôi không có bất kỳ đọc về điều này, nhưng về cơ bản bạn nối một định danh nguồn với một chuỗi từ nguồn đó. Vì vậy, bạn biết nó là duy nhất. Ví dụ, nếu bạn có hai nguồn, sau đó bạn sẽ có một chuỗi A1, A2, A3, A4 ... A999 và một chuỗi B1, B2, B3, B4 khác. .. B999. Vì một ID từ nguồn A sẽ không bao giờ bắt đầu bằng B, khi đó bạn biết sẽ không bao giờ có xung đột. –

+0

k cảm ơn bạn, mã định danh nguồn có thể là id cho bảng db để khi mã được nhập vào thông tin có thể được thu thập từ một bản ghi trong bảng không? – Jon

0

Nếu không viết mã, logic của tôi sẽ là:

Tạo chuỗi ngẫu nhiên từ bất kỳ ký tự được chấp nhận nào bạn thích.
Sau đó, thêm một nửa dấu ngày (một phần giây và tất cả) vào mặt trước và nửa còn lại để kết thúc (hoặc ở đâu đó ở giữa nếu bạn thích).

Ở lại JOLLY!
H

+1

Điều này là gần, nhưng tùy thuộc vào thói quen ngẫu nhiên của bạn chỉ có độ chính xác chỉ hơn micro giây. Như ông đã đề cập, uniqid thất bại trong cùng một khả năng. –

0

Nếu bạn sử dụng phương pháp gốc, nhưng thêm tên người dùng hoặc địa chỉ email trước mật khẩu, nó sẽ luôn là duy nhất nếu mỗi người dùng chỉ có thể có 1 mật khẩu.

0

Bạn có thể quan tâm đến bài viết này đề cập đến cùng một vấn đề: GUIDs are globally unique, but substrings of GUIDs aren't.

Mục tiêu của thuật toán này là sử dụng sự kết hợp của thời gian và địa điểm ("không gian-thời gian phối" cho các chuyên viên máy tính tương đối trên mạng) là chìa khóa độc đáo. Tuy nhiên, chấm công không phải là hoàn hảo, do đó, có một khả năng rằng, ví dụ, hai GUID được tạo ra trong kế nhanh chóng từ cùng một máy, do đó, gần nhau trong thời gian đó các dấu thời gian sẽ giống nhau. Đó là nơi mà uniquifier do thỏa thuận hợp

0

Tôi thường làm điều đó như thế này:.

$this->password = ''; 

for($i=0; $i<10; $i++) 
{ 
    if($i%2 == 0) 
     $this->password .= chr(rand(65,90)); 
    if($i%3 == 0) 
     $this->password .= chr(rand(97,122)); 
    if($i%4 == 0) 
     $this->password .= chr(rand(48,57)); 
} 

Tôi cho rằng có một số lỗ lý thuyết nhưng tôi chưa bao giờ có một vấn đề với sự trùng lặp. Tôi thường sử dụng nó cho mật khẩu tạm thời (như sau khi đặt lại mật khẩu) và nó hoạt động đủ tốt cho điều đó.

-1

Tôi thường làm một chuỗi con ngẫu nhiên (ngẫu nhiên có bao nhiêu ký tự giữa 8, 32 hoặc ít hơn để thuận tiện cho người dùng) hoặc MD5 của một số giá trị tôi đã nhận hoặc thời gian hoặc kết hợp. Đối với ngẫu nhiên hơn tôi làm MD5 của đến giá trị (nói tên cuối cùng) nối rằng với thời gian, MD5 nó một lần nữa, sau đó đi các chuỗi con ngẫu nhiên. Có, bạn có thể nhận mật khẩu bằng nhau, nhưng không hẳn là có mật khẩu.

+0

Nếu bạn lấy một chuỗi con của một băm mật mã bảo mật thì bạn sẽ đánh bại tính duy nhất của băm. Không có phần nào của băm an toàn hơn hoặc ngẫu nhiên hơn bất kỳ phần băm nào khác. Nó giống như có khả năng nhận được mật khẩu bằng nhau như sử dụng một cuộc gọi thông thường đến một bộ tạo số ngẫu nhiên. –

0

Bạn có thể quan tâm đến việc thực hiện an toàn vượt trội của Steve Gibson về trình tạo mật khẩu (không có nguồn, nhưng ông có mô tả chi tiết cách hoạt động) tại https://www.grc.com/passwords.htm.

Trang web tạo mật khẩu 64 ký tự lớn, vì chúng hoàn toàn ngẫu nhiên, bạn có thể dễ dàng lấy 8 ký tự đầu tiên (hoặc nhiều ký tự) với mật khẩu kém an toàn hơn nhưng "ngẫu nhiên càng tốt".

EDIT: từ câu trả lời sau đó của bạn tôi thấy bạn cần một cái gì đó giống như một GUID hơn một mật khẩu, do điều này có lẽ không phải là những gì bạn muốn ...

1

Bất kỳ thuật toán sẽ cho kết quả trong các mục sao.

Vì vậy, tôi có thể khuyên bạn nên sử dụng thuật toán hiện tại của mình * và chỉ cần kiểm tra các bản sao?

* Bổ sung nhẹ: Nếu uniqid() có thể không độc đáo dựa trên thời gian, cũng bao gồm bộ đếm chung mà bạn tăng sau mỗi lần gọi. Bằng cách đó một cái gì đó là khác nhau ngay cả trong cùng một micro giây.

+0

GUID (hoặc UUIDS) và trình tự là hai cách duy nhất để tránh trùng lặp, nhưng bạn là chính xác cho mọi thuật toán khác được đề cập ở đây. –

+0

Nếu độ dài định danh tùy ý được cho phép, tôi đồng ý. Nếu anh ta muốn giữ 8 ký tự như trong ví dụ của mình, nó chỉ là không đủ. –

+0

8 ký tự đủ cho chính xác 1.099,511,627,776 mật khẩu duy nhất nếu bạn sử dụng Base32, đáng tin cậy cho dữ liệu được nhập theo cách thủ công (32^8) Điều này không có phụ cấp để xác minh, cũng như loại trừ các mẫu như 00000000. –

0

Như Frank Kreuger đã nhận xét, hãy sử dụng bộ tạo GUID.

Giống như this one

0

Tôi vẫn không thấy lý do tại sao các mật khẩu có phải là duy nhất? Nhược điểm nếu 2 người dùng của bạn có cùng mật khẩu?

Giả sử chúng ta đang nói về mật khẩu được liên kết với người dùng chứ không phải chỉ số nhận dạng duy nhất. Nếu đó là những gì bạn đang tìm kiếm, tại sao không sử dụng GUID?

+0

bởi vì nó có thể không phải lúc nào cũng là một mật khẩu, mà thay vào đó là tên người dùng/id đăng nhập thực sự của họ hoặc nói một id giao dịch. nhưng một lần nữa, tôi không thể cho rằng tôi đang xử lý mà tôi có quyền truy cập. Điều khác là tôi chỉ muốn 7 đến 15 ký tự. GUIDs thường dài hơn nhiều và do đó sẽ kết thúc không phải là duy nhất khá dễ dàng. –

0

Tôi tin rằng mọi phần của vấn đề của bạn là bạn đang cố gắng để chúng ta một chức năng đặc biệt cho hai mục đích sử dụng riêng biệt ... mật khẩu và TRANSACTION_ID

những thực sự là hai vấn đề khu vực khác nhau và nó thực sự không phải là tốt nhất để cố gắng giải quyết chúng cùng nhau.

0

Gần đây tôi muốn có một khóa duy nhất ngẫu nhiên nhanh chóng và đơn giản vì vậy tôi đã làm như sau:

$ukey = dechex(time()) . crypt(time() . md5(microtime() + mt_rand(0, 100000))); 

Vì vậy, về cơ bản, tôi nhận được thời gian unix trong vài giây và thêm một chuỗi md5 ngẫu nhiên được tạo ra từ thời gian + số ngẫu nhiên . Nó không phải là tốt nhất, nhưng đối với yêu cầu tần số thấp nó là khá tốt. Nó nhanh và hoạt động.

Tôi đã làm một bài kiểm tra nơi tôi sẽ tạo ra hàng ngàn khóa và sau đó tìm lặp lại, và có khoảng 800 phím mỗi giây không có sự lặp lại, vì vậy không tệ. Tôi đoán nó hoàn toàn phụ thuộc vào mt_rand()

Tôi sử dụng nó cho trình theo dõi khảo sát nơi chúng tôi nhận được tỷ lệ gửi khoảng 1000 bản khảo sát mỗi phút ... vì vậy hiện tại (qua các ngón tay) không có bản sao. Tất nhiên, tỷ lệ không phải là hằng số (chúng tôi nhận được các bài gửi vào những thời điểm nhất định trong ngày) vì vậy đây không phải là bằng chứng không phải là giải pháp tốt nhất ... mẹo sử dụng giá trị gia tăng như một phần của khóa (trong trường hợp của tôi, Tôi đã sử dụng time(), nhưng có thể tốt hơn).

+1

Tôi không hiểu tại sao bạn cần md5 giá trị. MD5 là một cách băm tạo ra một chữ ký. Hãy cẩn thận rằng các giá trị đầu vào khác nhau có thể dẫn đến việc tạo chữ ký giống nhau, các hàm MD5 được kích hoạt để cố gắng trả về các kết quả khác nhau khi các giá trị đầu vào hơi khác nhau hoàn toàn khác nhau. Vì vậy, bằng cách thêm MD5 tôi nghĩ rằng bạn tăng xác suất để có được các giá trị trùng lặp. –

0

Ingoring phần crypting mà không có nhiều việc phải làm với việc tạo ra một giá trị duy nhất tôi thường sử dụng này một:

function GetUniqueValue() 
{ 
    static $counter = 0; //initalized only 1st time function is called 
    return strtr(microtime(), array('.' => '', ' ' => '')) . $counter++; 
} 

Khi được gọi trong cùng một quá trình $ truy cập được tăng lên nên giá trị luôn luôn là duy nhất trong cùng một quá trình .

Khi được gọi trong các quy trình khác nhau, bạn phải thực sự không may khi nhận được 2 microtime() với cùng giá trị, nghĩ rằng các cuộc gọi microtime() thường có các giá trị khác nhau khi được gọi trong cùng một tập lệnh.

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