2009-03-07 31 views
7

Tôi đang sử dụng api có tên là 21 char tối đa để biểu thị phiên nội bộ có thời gian tồn tại khoảng "hai ngày". Tôi muốn cái tên đó không có ý nghĩa gì khi sử dụng một số thứ gì đó? md5 tạo ra 40 ký tự, có cái gì khác tôi có thể sử dụng?Các phím Python và ngẫu nhiên của 21 char max

Hiện tại tôi sử dụng 'userid [: 10]' + thời gian tạo: ddhhmmss + ngẫu nhiên 3 ký tự.

Cảm ơn,

+0

Bạn phải suy nghĩ SHA1. MD5 là 32 chữ số thập lục phân. – kmkaplan

Trả lời

23

Nếu tôi đọc chính xác câu hỏi của bạn, bạn muốn tạo một số mã thông báo nhận dạng tùy ý phải có tối đa 21 ký tự. Nó có cần phải có khả năng chống đoán cao không? Ví dụ bạn đưa ra không phải là "mạnh mẽ về mặt sắc thái" ở chỗ nó có thể được đoán bằng cách tìm kiếm ít hơn 1/2 của toàn bộ không gian phím có thể.

Bạn không nói nếu các ký tự có thể là tất cả 256 ký tự ASCII, hoặc nếu nó cần được giới hạn, ví dụ, ASCII có thể in (33-127, bao gồm) hoặc phạm vi nhỏ hơn.

Có mô-đun Python được thiết kế cho UUID s (Số nhận dạng duy nhất của Đại học). Bạn có thể muốn uuid4 tạo ra một UUID ngẫu nhiên và sử dụng hỗ trợ hệ điều hành nếu có (trên Linux, Mac, FreeBSD và các khả năng khác).

>>> import uuid 
>>> u = uuid.uuid4() 
>>> u 
UUID('d94303e7-1be4-49ef-92f2-472bc4b4286d') 
>>> u.bytes 
'\xd9C\x03\xe7\x1b\xe4I\xef\x92\xf2G+\xc4\xb4(m' 
>>> len(u.bytes) 
16 
>>> 

16 byte ngẫu nhiên là rất unguessable, và không có nhu cầu sử dụng đầy đủ 21 byte API của bạn cho phép, nếu tất cả các bạn muốn là phải có một định danh đục unguessable.

Nếu bạn không thể sử dụng các byte thô như vậy, đó có thể là một ý tưởng tồi vì khó sử dụng trong nhật ký và các thông báo gỡ lỗi khác và khó so sánh hơn bằng mắt, sau đó chuyển đổi byte thành một thứ dễ đọc hơn, như sử dụng mã hóa base-64, với kết quả được cắt nhỏ xuống 21 (hoặc bất kỳ) byte nào:

>>> u.bytes.encode("base64") 
'2UMD5xvkSe+S8kcrxLQobQ==\n' 
>>> len(u.bytes.encode("base64")) 
25 
>>> u.bytes.encode("base64")[:21] 
'2UMD5xvkSe+S8kcrxLQob' 
>>> 

Điều này mang lại cho bạn chuỗi chuỗi ngẫu nhiên có độ dài cực kỳ cao 21.

Bạn có thể không thích '+' hoặc '/' có thể nằm trong chuỗi base-64, vì không thoát đúng cách có thể ảnh hưởng đến URL. Vì bạn đã nghĩ để sử dụng "ngẫu nhiên 3 ký tự", tôi không nghĩ rằng đây là một lo lắng của bạn. Nếu có, bạn có thể thay thế các ký tự đó bằng một thứ khác ('-' và '.' Có thể hoạt động) hoặc xóa chúng nếu có.

Như những người khác đã chỉ ra, bạn có thể sử dụng .encode ("hex") và nhận được hex tương đương, nhưng đó chỉ là 4 bit ngẫu nhiên/ký tự * 21 ký tự tối đa cho bạn 84 bit ngẫu nhiên thay vì gấp đôi. Mỗi bit tăng gấp đôi keyspace của bạn, làm cho không gian tìm kiếm lý thuyết nhiều, nhỏ hơn nhiều. Với hệ số 2E24 nhỏ hơn.

Không gian phím của bạn vẫn có kích thước 2E24, ngay cả với mã hóa hex, vì vậy tôi nghĩ rằng đó là một mối quan tâm lý thuyết. Tôi sẽ không lo lắng về những người thực hiện các cuộc tấn công bạo lực đối với hệ thống của bạn.

Sửa:

P.S .: Các chức năng sử dụng uuid.uuid4 libuuid nếu có. Điều đó có entropy của nó từ os.urandom (nếu có) nếu không từ thời điểm hiện tại và địa chỉ MAC ethernet cục bộ. Nếu libuuid không có sẵn thì hàm uuid.uuid4 lấy các byte trực tiếp từ os.urandom (nếu có) nếu không nó sẽ sử dụng mô-đun ngẫu nhiên. Các mô-đun ngẫu nhiên sử dụng một hạt giống mặc định dựa trên os.urandom (nếu có) nếu không một giá trị dựa trên thời gian hiện tại. Probing diễn ra cho mọi cuộc gọi chức năng, vì vậy nếu bạn không có os.urandom thì chi phí sẽ lớn hơn một chút so với bạn mong đợi.

Gửi tin nhắn về nhà? Nếu bạn biết bạn có os.urandom thì bạn có thể làm

os.urandom(16).encode("base64")[:21] 

nhưng nếu bạn không muốn lo lắng về tính khả dụng thì hãy sử dụng mô-đun uuid.

+0

Tôi quên thêm rằng nên được url an toàn, tôi nên có quy định nó trong ba ký tự ngẫu nhiên. Tôi sẽ sử dụng phương pháp của bạn và thay thế dấu + và /. – coulix

+0

Tôi tìm thấy một phương pháp an toàn uri_b64encode mà sẽ làm công việc độc đáo nhờ – coulix

+0

Lưu ý rằng UUID4 không chính xác cung cấp cho bạn 16 byte ngẫu nhiên. Có 6 bit cố định (không ngẫu nhiên). Tất nhiên điều này là đủ lớn. – kmkaplan

2

Tại sao không lấy 21 ký tự đầu tiên từ md5 hoặc hàm băm SHA1?

+0

Đúng là phải đủ ngẫu nhiên – coulix

+0

Giống như hashlib.md5 (str (random.random()). Hexdigest() [: 21] –

+0

random.random() theo mặc định lấy hạt giống từ os.urandom, khác với time.time. Giả sử hệ điều hành hỗ trợ os.urandom, cũng như os.urandom (11) .encode ("hex") [: 21]. –

4

Biểu diễn thập lục phân của MD5 có tính ngẫu nhiên rất kém: bạn chỉ nhận được 4 bit entropy cho mỗi ký tự.

Sử dụng ký tự ngẫu nhiên, một cái gì đó như:

import random 
import string 
"".join([random.choice(string.ascii_letters + string.digits + ".-") 
     for i in xrange(21)]) 

Trong sự lựa chọn đặt tất cả các nhân vật có thể chấp nhận.

Trong khi sử dụng hàm băm thực như SHA1 cũng sẽ cho bạn kết quả tốt đẹp nếu sử dụng đúng, mức độ phức tạp và tiêu thụ CPU có vẻ không hợp lý cho nhu cầu của bạn. Bạn chỉ muốn một chuỗi ngẫu nhiên.

+0

string.ascii_letters, vì string.letters là ngôn ngữ phụ thuộc. –

0

Ký tự hoặc byte? Nếu nó có chuỗi tùy ý, bạn chỉ có thể sử dụng các byte và không phải lo lắng về việc mở rộng đến các ký tự có thể đọc được (mà base64 sẽ tốt hơn hex anyway).

MD5 tạo 16 ký tự nếu bạn không sử dụng mở rộng hệ thập lục phân của nó. SHA1 tạo ra 20 trong cùng một điều kiện.

>>> import hashlib 
>>> len(hashlib.md5('foobar').digest()) 
16 
>>> len(hashlib.sha1('foobar').digest()) 
20 

Cần thêm vài byte sau đó.

2

Mô-đun base64 có thể thực hiện mã hóa an toàn cho URL. Vì vậy, nếu cần thiết, thay vì

u.bytes.encode("base64") 

bạn có thể làm

import base64 

token = base64.urlsafe_b64encode(u.bytes) 

và, thuận tiện, để chuyển đổi trở lại

u = uuid.UUID(bytes=base64.urlsafe_b64decode(token)) 
Các vấn đề liên quan