2009-08-18 27 views
17

PHP có hàm uniqid() tạo ra UUID loại.Tại sao MD5'ing một UUID không phải là một ý tưởng tốt?

Trong ví dụ sử dụng, nó cho thấy như sau:

$token = md5(uniqid());

Nhưng trong các ý kiến, someone says this:

Tạo một MD5 từ một ID duy nhất là ngây thơ và làm giảm nhiều giá trị của ID duy nhất, cũng như cung cấp độ nghiêm trọng đáng kể (có thể tấn công) trên miền MD5. Đó là một điều sâu sắc bị hỏng để làm. Cách tiếp cận chính xác là sử dụng ID duy nhất trên riêng của nó; nó đã được thiết kế cho không va chạm.

Tại sao điều này đúng, nếu có? Nếu một băm MD5 là (gần như) duy nhất cho một ID duy nhất, sau đó những gì là sai từ md5'ing một uniqid?

Trả lời

33

UUID rộng 128 bit và có tính duy nhất vốn có theo cách được tạo. Một băm MD5 là 128 bit rộng và không đảm bảo uniquess, chỉ có một probablity thấp va chạm. Băm MD5 không nhỏ hơn UUID nên nó không hỗ trợ lưu trữ.

Nếu bạn biết hàm băm từ UUID dễ bị tấn công hơn vì miền UUID hợp lệ thực sự có thể dự đoán được nếu bạn biết bất cứ điều gì về máy tạo gen cho chúng.

Nếu bạn cần cung cấp mã bảo mật thì bạn cần phải sử dụng cryptographically secure random number generator. (1) UUID không được thiết kế để bảo mật mã hóa, chỉ được đảm bảo duy nhất. Một chuỗi tăng đơn điệu bao quanh bởi các mã định danh máy duy nhất (thường là một MAC) và thời gian vẫn là một UUID hoàn toàn hợp lệ nhưng có thể dự đoán cao nếu bạn có thể đảo ngược một UUID đơn lẻ từ chuỗi mã thông báo.

  1. Đặc tính xác định của PRNG an toàn mã hóa là kết quả của một lần lặp lại đã cho không chứa đủ thông tin để suy ra giá trị của lần lặp tiếp theo - nghĩa là có một số trạng thái ẩn trong trình tạo không được tiết lộ trong số và không thể suy ra bằng cách kiểm tra chuỗi các số từ PRNG.

    Nếu bạn tham gia vào lý thuyết số, bạn có thể tìm cách đoán trạng thái nội tại của một số PRNG từ một chuỗi giá trị được tạo. Mersenne Twister là một ví dụ về máy phát điện như vậy. Nó có trạng thái ẩn mà nó sử dụng để có được thời gian dài nhưng nó không an toàn về mặt mã hóa - bạn có thể lấy một dãy số khá nhỏ và sử dụng nó để suy ra trạng thái bên trong. Một khi bạn đã làm điều này, bạn có thể sử dụng nó để tấn công một cơ chế mã hóa phụ thuộc vào việc giữ cho chuỗi đó là một bí mật.
4

MD5ing UUID là vô nghĩa vì UUID đã là duy nhất và độ dài cố định (ngắn), thuộc tính là một số lý do khiến mọi người thường sử dụng MD5 để bắt đầu. Vì vậy, tôi cho rằng nó phụ thuộc vào những gì bạn có kế hoạch làm với UUID, nhưng nói chung một UUID có các thuộc tính giống như một số dữ liệu đã được MD5'd, vậy tại sao làm cả hai?

+1

Trong thực tế, điều này tệ hơn, bởi vì UUID là duy nhất, trong khi băm MD5 của UUID thì không. –

2

UUID đã là duy nhất, do đó, không có bất kỳ điểm nào trong MD5.

Về câu hỏi bảo mật, nói chung bạn có thể bị tấn công nếu kẻ tấn công có thể dự đoán ID duy nhất tiếp theo bạn sẽ tạo ra.Nếu bạn biết rằng bạn tạo ID duy nhất của mình từ UUID, tập hợp các ID duy nhất tiềm năng tiếp theo nhỏ hơn nhiều, tạo cơ hội tốt hơn cho cuộc tấn công bạo lực.

Điều này đặc biệt đúng nếu kẻ tấn công có thể nhận được toàn bộ các ID duy nhất từ ​​bạn và theo cách đó, hãy đoán sơ đồ tạo UUID của bạn.

+0

"không có điểm": Trên thực tế, nó tệ hơn không có điểm, bởi vì UUID là duy nhất, trong khi băm MD5 của UUID thì không. –

2

Version 3 trong số UUID đã MD5, vì vậy không còn điểm nào để thực hiện lại. Tuy nhiên, tôi không chắc chắn những gì UUID phiên bản PHP sử dụng.

12

Lưu ý rằng uniqid() không trả lại một UUID, nhưng một chuỗi "độc đáo" dựa trên thời gian hiện tại:

$ php -r 'echo uniqid("prefix_", true);' 
prefix_4a8aaada61b0f0.86531181 

Nếu bạn làm điều đó nhiều lần, bạn sẽ nhận ra các chuỗi rất giống nhau và tất cả mọi người người quen thuộc với uniqid() sẽ nhận ra thuật toán nguồn. Bằng cách đó nó là khá dễ dàng để dự đoán các ID tiếp theo sẽ được tạo ra.

Ưu điểm của md5() - ing đầu ra, cùng với một chuỗi muối ứng dụng cụ thể hoặc số ngẫu nhiên, là một cách khó đoán chuỗi:

$ php -r 'echo md5(uniqid("prefix_", true));' 
3dbb5221b203888fc0f41f5ef960f51b 

Không giống như đồng bằng uniqid(), điều này tạo ra rất khác nhau đầu ra mỗi micro giây. Hơn nữa nó không reveil của bạn "tiền tố muối" chuỗi, cũng không phải là bạn đang sử dụng uniqid() dưới mui xe. Nếu không biết muối, nó rất khó (xem xét nó không thể) để đoán ID tiếp theo.

Tóm lại, tôi sẽ không đồng ý với ý kiến ​​của người nhận xét và sẽ luôn thích đầu ra md5() trên đồng bằng uniqid().

+3

Nếu bạn cần ID của mình không thể chấp nhận được, hãy lấy một đầu vào dễ đoán và làm xáo trộn nó là _không phải là cách để đi. –

+0

Đầu vào có thể đoán được như thế nào nếu bạn không để lộ chuỗi muối (Tiền tố được sử dụng cho uniqid())? Bạn có thể giải thích những lời chỉ trích của bạn? –

+1

Có những cách hoàn hảo tốt để tạo ID thực sự không thể chấp nhận. Bởi chỉ đơn thuần là obfuscating một chuỗi dự đoán dễ dàng, bạn đang dựa vào không ai tìm ra phương pháp và chuỗi muối của bạn. Nếu có, họ có thể dễ dàng dự đoán ID bạn sẽ tạo trong tương lai. –

0

Ngoài ra, MD5 thực sự đã lỗi thời và không được sử dụng trong bất kỳ thứ gì đáng được bảo vệ - PHI, PII hoặc PCI - từ năm 2010 trở đi. Các Fed của Hoa Kỳ đã thực hiện điều này và bất kỳ thực thể nào không tuân thủ sẽ phải trả rất nhiều tiền phạt $ $$$.

+0

Có. Phần mềm sử dụng MD5 cho an ninh sẽ chính thức không được xem xét trong năm 2010, nhưng thực tế, không ai muốn nó ngay bây giờ bởi vì họ sẽ được yêu cầu để thoát khỏi nó sau này (cho một giá trị rất sớm sau này). Vì vậy, nếu bạn đang bán phần mềm hoặc phần mềm như một dịch vụ, bạn sẽ loại trừ một số khách hàng chỉ bằng việc sử dụng MD5. Sử dụng SHAx, tốt nhất là với giá trị lớn của x. – quillbreaker

+1

Theo như tôi biết, MD5 chưa bao giờ được bao gồm trong tiêu chuẩn NIST. Những gì đang được loại bỏ bởi NIST là SHA-1 và về cơ bản tất cả mọi thứ có bảo mật 80-bit hoặc ít hơn. Ngoài ra các công ty không thực hiện các tiêu chuẩn NIST không bị phạt tiền.Họ chỉ không thể nhận được chứng nhận của NIST và do đó mất khách hàng yêu cầu chứng nhận như vậy. – Accipitridae

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