Uniqid độc đáo như thế nào?


76

Câu hỏi này không thực sự là một vấn đề tìm kiếm giải pháp, nó chỉ là vấn đề của sự tò mò đơn giản. Hàm uniqid trong PHP có cờ entropy hơn, để làm cho đầu ra "độc đáo hơn". Điều này khiến tôi tự hỏi, khả năng hàm này tạo ra cùng một kết quả nhiều lần khi more_entropy là true, so với khi không. Nói cách khác, uniqid độc đáo như thế nào khi bật more_entropy so với khi nó bị tắt? Có hạn chế nào khi luôn bật more_entropy không?


3
Nếu bạn muốn thứ gì đó luôn độc đáo, bạn cần triển khai GUID . Khá nhiều thứ khác cuối cùng sẽ va chạm vì chỉ có quá nhiều entropy trong hàm. Ví dụ, uniqidvới more_entropyset chỉ cung cấp khoảng 92 bit entropy (23 hexbit). Để hiểu tại sao điều đó không tốt cho tính độc đáo, xem The Birthday Vấn đề ...
ircmaxell

@ircmaxell cảm ơn bạn đã chỉ ra Vấn đề sinh nhật, nó khá thú vị. Nó chắc chắn nên được đề cập trong câu trả lời.
Petr Peller

2
uniqid () không phải là một hàm băm nên Vấn đề Sinh nhật không áp dụng cho nó. Tuy nhiên, nó có những lỗ hổng.
Joel Mellon

@ircmaxell ở đâu ra con số đó? more_entropylà khoảng 30 bit entropy (chín chữ số thập phân), phần micro giây là khoảng 20 (sáu chữ số thập phân), phần còn lại đến từ đâu? Bạn sẽ cần chọn thứ hai từ phạm vi 100.000 năm để có được 42 bit entropy.
Tgr

Câu trả lời:


36

Cập nhật, tháng 3 năm 2014:

Đầu tiên, điều quan trọng cần lưu ý uniqidlà có một chút nhầm lẫn vì nó không đảm bảo một ID duy nhất.

Theo tài liệu PHP :

CẢNH BÁO!

Hàm này không tạo chuỗi ngẫu nhiên hoặc không thể đoán trước. Chức năng này không được sử dụng cho mục đích bảo mật. Sử dụng hàm / trình tạo ngẫu nhiên an toàn bằng mật mã và các hàm băm an toàn bằng mật mã để tạo ID an toàn không thể đoán trước.

Hàm này không tạo ra các mã thông báo an toàn bằng mật mã, trên thực tế mà không được chuyển bất kỳ tham số bổ sung nào, giá trị trả về sẽ khác một chút so với microtime () . Nếu bạn cần tạo mã thông báo bảo mật bằng mật mã, hãy sử dụng openssl_random_pseudo_bytes () .


Đặt nhiều entropy hơn thành true tạo ra giá trị độc đáo hơn, tuy nhiên thời gian thực thi lâu hơn (mặc dù ở một mức độ nhỏ), theo tài liệu:

Nếu được đặt thành TRUE, uniqid () sẽ thêm entropy bổ sung (sử dụng trình tạo đồng dư tuyến tính kết hợp) vào cuối giá trị trả về, điều này làm tăng khả năng kết quả là duy nhất.

Lưu ý dòng increases the likelihood that the result will be uniquevà không phải là sẽ đảm bảo tính duy nhất.

Bạn có thể 'không ngừng' cố gắng cho tính duy nhất, cho đến một thời điểm và nâng cao bằng cách sử dụng bất kỳ số lượng quy trình mã hóa nào, thêm muối và những thứ tương tự- tùy thuộc vào mục đích.

Tôi khuyên bạn nên xem các nhận xét về chủ đề PHP chính, đáng chú ý là:

http://www.php.net/manual/en/ Chức năng.uniqid.php#96898

http://www.php.net/manual/en/ Chức năng.uniqid.php#96549

http://www.php.net/manual/en/ Chức năng.uniqid.php#95001

Những gì tôi khuyên bạn nên tìm ra lý do tại sao bạn cần tính duy nhất, đó là để bảo mật (tức là thêm vào quy trình mã hóa / xáo trộn)? Ngoài ra, như thế nào độc đáo hiện nó cần phải được? Cuối cùng, hãy xem xét tốc độ. Sự phù hợp sẽ thay đổi với những cân nhắc cơ bản.


1
Bài học quan trọng nhất với các nhận xét hàm đó là bản thân uuid là một mã nhận dạng rất nguy hiểm để chuyển làm cookie / ID khách hàng có thể đọc được, nhưng với tư cách là một ID duy nhất cục bộ / được bảo vệ, nó có một số công dụng tốt, đó là tốc độ. 2,5 xu.
DrPerdix

3
Tôi không biết liệu điều này có rõ ràng hay không, nhưng đừng sử dụng uniqid(hoặc nó là dẫn xuất) cho bất kỳ thứ gì liên quan đến bảo mật. PHP cung cấp một loạt toàn bộ máy phát ngẫu nhiên crypto-an toàn, chẳng hạn như: openssl_random_pseudo_bytes. Hãy sử dụng đúng công cụ cho công việc.
Halcyon

1
Giả sử không có 2 tệp nào được lưu trong cùng một micro giây, dấu thời gian unix micro giây sẽ là duy nhất cho mọi tệp.
CMCDragonkai

Theo thống kê, có khả năng bạn sẽ bị va chạm, nhưng không phải là không thể. Đặt thế hệ uniqid của bạn bên trong a do{} while(collision). Ví dụ: tôi sử dụng phương pháp này khi tạo đường dẫn cho các tệp đã tải lên.
afilina

2
Không chắc tại sao câu trả lời này được chấp nhận. Duy nhất! =
Ngẫu

16

Mọi thứ chỉ là duy nhất nếu bạn kiểm tra xem chúng chưa tồn tại. Không quan trọng bạn sử dụng hàm nào để tạo chuỗi hoặc ID 'ngẫu nhiên' - nếu bạn không kiểm tra kỹ xem nó không phải là bản sao, thì luôn có cơ hội đó ..;)

Mặc dù uniqid dựa trên thời điểm hiện tại, lưu ý cảnh báo ở trên vẫn được áp dụng - nó chỉ phụ thuộc vào nơi bạn sẽ sử dụng các "ID duy nhất" này. Đầu mối cho tất cả điều này là nơi nó nói "độc đáo hơn". Độc nhất là duy nhất là duy nhất. Làm thế nào bạn có thể có một cái gì đó ít nhiều độc đáo, tôi hơi khó hiểu!

Kiểm tra như trên và kết hợp tất cả những thứ này sẽ cho phép bạn kết thúc với một cái gì đó đang đạt đến sự độc đáo, nhưng tất cả đều liên quan đến nơi các phím sẽ được sử dụng và bối cảnh. Hy vọng rằng sẽ giúp!


10
Có một sự khác biệt rất lớn giữa "cơ hội bị va chạm là một phần vạn" và "thay đổi khi bị va chạm ít hơn so với việc mọi người dùng của chương trình bị sét đánh đồng thời". Giá trị 128 bit được tạo ra bởi một RNG tốt với một hạt giống tốt gần như là "thực sự" duy nhất nên điều đó không quan trọng, vì chi phí cực kỳ cao để có được một thứ gì đó độc nhất có thể chứng minh được (và không thể đoán trước).
Michael Borgwardt

6
Chỉ để tiếp tục quan điểm của bạn @Michael: Đối với 128 bit, bạn sẽ cần tất cả mọi người ở Mỹ (300 triệu) tạo ra 1 triệu số mỗi giây chỉ trong khoảng một ngày để có 50% khả năng xảy ra va chạm ... Đối với 512 bit, bạn sẽ cần mọi cơ thể trên trái đất (7 tỷ người) tạo ra 1 nghìn tỷ số mỗi giây trong những 10^47năm tiếp theo chỉ để có 50% khả năng xảy ra va chạm ... Vì vậy, có, với giới hạn trên đủ lớn về số ngẫu nhiên và một RNG đủ tốt, bạn có thể mô phỏng độc đáo với chỉ ngẫu nhiên ...
ircmaxell

1
Tôi hoàn toàn đồng ý, với những ví dụ về thế giới lý tưởng của bạn như trên. Cơ hội là tối thiểu. Tuy nhiên, tính ngẫu nhiên không phải là hoàn hảo trong các triển khai được đề cập đến trong câu hỏi ban đầu và tôi khẳng định, miền mà số duy nhất này đang được sử dụng là quan trọng. Nếu bạn có 1000 máy chủ, mỗi máy chủ làm ID 'duy nhất' dựa trên vi thời gian và giả sử chúng là duy nhất "chỉ vì", thì tại một số điểm, bạn có thể bị cháy. Bỏ qua bất kỳ điều gì kỳ quặc trong mã .. lỗi, hoặc bất cứ điều gì. Sự khác biệt ở đây là giữa thực tế và lý thuyết, và đó là lý do tại sao chúng tôi kiểm tra;)
dmp

5
"Nguyên tắc tạo ra một lượng nhỏ khả năng ứng biến hữu hạn bằng cách chỉ cần nối các mạch logic của Bambleweeny 57 Sub- Meson Brain vào một máy vẽ vectơ nguyên tử được treo trong một nhà sản xuất Chuyển động Brown mạnh mẽ (ví dụ như một tách trà nóng) tất nhiên đã được hiểu rõ . "
dmp

1
@ircmaxell: Điểm bắt buộc là những con số đó đòi hỏi sự ngẫu nhiên thực sự và do đó là RNG thực. Bạn thậm chí không thể mô phỏng nó với một PRNG có trạng thái bên trong> 128 bit, trừ khi bạn cũng có cách gieo nó với giá trị duy nhất / ngẫu nhiên> 128 bit. Nhưng đó chính là vấn đề bạn phải giải quyết! Và bất cứ điều gì ít hơn thế, hầu như đảm bảo va chạm. Cũng 300 triệu người đó, nếu họ đang sử dụng kho dữ liệu tồi tệ của trình biên dịch của họ rand(), sẽ có> 90% khả năng xảy ra va chạm trong lần lặp đầu tiên . Thêm vào đó, nếu bạn cần sự độc đáo, thậm chí 0,001% cơ hội va chạm là quá nhiều.
cHao

10

Từ các cuộc thảo luận về hàm trên trang web hướng dẫn sử dụng PHP:

Như những người khác lưu ý dưới đây, không có tiền tố và không có "thêm entropy", hàm này chỉ trả về dấu thời gian UNIX với bộ đếm micro giây được bổ sung dưới dạng số hex; nó ít nhiều chỉ là microtime (), ở dạng hexit.

[...]

Cũng cần lưu ý rằng vì microtime () chỉ hoạt động trên các hệ thống có gettimeofday ()> present, mà Windows nguyên bản KHÔNG PHẢI, uniqid () có thể chỉ mang lại dấu thời gian UNIX độ phân giải một giây trong môi trường Windows.

Nói cách khác nếu không có "more_entropy", hàm này hoàn toàn khủng khiếp và không bao giờ được sử dụng, dấu chấm. Mã hóa cho tài liệu, cờ sẽ sử dụng "trình tạo đồng dư tuyến tính kết hợp" để "thêm entropy". Đó là một RNG khá yếu. Vì vậy, tôi sẽ bỏ qua hoàn toàn chức năng này và sử dụng một cái gì đó dựa trên mt_rand với một hạt giống tốt cho những thứ không liên quan đến bảo mật và SHA-256 cho những thứ có.


7

Không có cờ more_unique, nó trả về dấu thời gian unix với bộ đếm micro giây, do đó nếu hai lệnh gọi được thực hiện ở cùng một micro giây thì chúng sẽ trả về cùng một id 'duy nhất'.

Từ đó, nó là một câu hỏi về khả năng đó là như thế nào. Câu trả lời là, không phải rất, nhưng không phải ở mức độ có thể chiết khấu. Nếu bạn cần một id duy nhất và bạn tạo chúng thường xuyên (hoặc làm việc với dữ liệu được tạo ở nơi khác), đừng coi nó là hoàn toàn duy nhất.


21
tin hay không thì tùy, nó thực sự gọi usleep (1) để đảm bảo điều đó không bao giờ xảy ra!
Eli

2
@Eli không chắc có phải trolling hay không, nhưng rõ ràng đó không phải là trường hợp vì tôi đang nhận được các bản sao đang chạy điều này: for ($ i = 0; $ i <10; $ i ++) echo uniqid (). "\ n";
djule5

3
@ djule5 Không, không phải trolling: github.com/php/php-src/blob/… Có lẽ bạn đang chạy một phiên bản PHP rất cũ hoặc trên nền tảng cho usleep không tồn tại?
Eli,

@Eli thú vị haha ​​cảm ơn vì nguồn! Tôi đang chạy PHP 5.5.11 nhưng tôi đang sử dụng Windows trên máy dev này ... nên điều đó có thể giải thích cho điều đó! Vì vậy, nó chắc chắn không phải là duy nhất trên Windows sau đó ...
djule 5

1
@ user5542121, họ quyết định không gọi usleep và thăm dò thời gian thay vì usleep "có thể khiến hạt nhân lên lịch cho một quá trình khác, gây ra tình trạng tạm dừng khoảng 10ms" ~ github.com/php/php-src/blob/PHP-7.2.12/ ext / standard /…
x3ns

5

Bit có liên quan từ mã nguồn

if (more_entropy) {
    uniqid = strpprintf(0, "%s%08x%05x%.8F", prefix, sec, usec, php_combined_lcg() * 10);
} else {
    uniqid = strpprintf(0, "%s%08x%05x", prefix, sec, usec);
}

Vì vậy, more_entropythêm chín chữ số thập phân hơi ngẫu nhiên ( php_combined_lcg()trả về giá trị bằng (0,1)) - đó là 29,9 bit entropy, đỉnh (trong thực tế có lẽ ít hơn vì LCG không phải là trình tạo số giả ngẫu nhiên an toàn về mặt mật mã).

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.