2009-03-07 10 views
7

की यादृच्छिक कुंजी मैं एक एपीआई का उपयोग कर रहा हूं जो एक आंतरिक सत्र का प्रतिनिधित्व करने के लिए 21 चार अधिकतम का नाम लेता है जिसमें जीवन भर "दो दिन" रहता है। मैं किसी प्रकार की हैशिंग का उपयोग करके नाम का अर्थपूर्ण नहीं होना चाहूंगा? एमडी 5 40 वर्ण उत्पन्न करता है, क्या मैं कुछ और उपयोग कर सकता हूं?पाइथन और 21 चर अधिकतम

अब के लिए मैं 'userid [: 10]' + निर्माण समय का उपयोग करता हूं: ddhhmmss + random 3 वर्ण।

धन्यवाद,

+0

आप SHA1 सोच किया जाना चाहिए। एमडी 5 32 हेक्साडेसिमल अंक है। – kmkaplan

उत्तर

23

यदि मैं आपका प्रश्न सही ढंग से पढ़ता हूं, तो आप कुछ मनमानी पहचानकर्ता टोकन उत्पन्न करना चाहते हैं जो 21 वर्ण अधिकतम होना चाहिए। अनुमान लगाने के लिए इसे अत्यधिक प्रतिरोधी होने की आवश्यकता है? आपके द्वारा दिया गया उदाहरण "क्रिटोग्राफिक रूप से मजबूत" नहीं है, जिसमें पूरे संभव कुंजीपटल के 1/2 से कम खोज करके अनुमान लगाया जा सकता है।

आप यह नहीं कहते कि पात्र सभी 256 ASCII वर्ण हो सकते हैं, या यदि इसे सीमित करने की आवश्यकता है, तो कहें, प्रिंट करने योग्य ASCII (33-127, समावेशी), या कुछ छोटी रेंज।

UUID एस (यूनिवर्सल अद्वितीय पहचानकर्ता) के लिए डिज़ाइन किया गया एक पायथन मॉड्यूल है। आप संभवतः uuid4 चाहते हैं जो एक यादृच्छिक यूयूआईडी उत्पन्न करता है, और उपलब्ध होने पर ओएस समर्थन का उपयोग करता है (लिनक्स, मैक, फ्रीबीएसडी, और अन्य लोगों पर)।

>>> 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 यादृच्छिक बाइट्स बहुत unguessable है, और, पूर्ण 21 बाइट्स अपने एपीआई की अनुमति देता है का उपयोग करने के अगर सभी आप चाहते हैं एक unguessable अपारदर्शी पहचानकर्ता है कोई आवश्यकता नहीं है।

यदि आप कच्चे बाइट्स का उपयोग नहीं कर सकते हैं, जो शायद एक बुरा विचार है क्योंकि लॉग और अन्य डीबग संदेशों में उपयोग करना कठिन होता है और आंखों की तुलना करना कठिन होता है, तो बाइट्स को कुछ और पठनीय में परिवर्तित करें, , आधार -64 एन्कोडिंग का उपयोग के साथ परिणाम 21 (या जो भी) के लिए नीचे कटा तरह बाइट्स:

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

यह आपको लंबाई 21 की एक अत्यंत उच्च गुणवत्ता यादृच्छिक स्ट्रिंग देता है।

आप पसंद नहीं हो सकता है '+' या '/' जो एक आधार -64 स्ट्रिंग में हो सकता है, उचित एस्केपिंग बिना के बाद से है कि यूआरएल के साथ हस्तक्षेप कर सकते हैं। चूंकि आप पहले से ही "यादृच्छिक 3 वर्ण" का उपयोग करना चाहते हैं, मुझे नहीं लगता कि यह आपकी चिंता है। यदि ऐसा है, तो आप उन पात्रों को किसी अन्य चीज़ से बदल सकते हैं ('-' और '।' काम कर सकते हैं), या उपस्थित होने पर उन्हें हटा दें।

जैसा कि अन्य ने इंगित किया है, आप .encode ("हेक्स") का उपयोग कर सकते हैं और हेक्स समकक्ष प्राप्त कर सकते हैं, लेकिन यह केवल 4 बिट्स यादृच्छिकता/चरित्र * 21 वर्ण अधिकतम आपको दो बार की बजाय यादृच्छिकता के 84 बिट देता है। प्रत्येक बिट आपके कुंजीपटल को दोगुना करता है, सैद्धांतिक खोज स्थान को बहुत छोटा बनाता है। 2E24 छोटे के कारक से।

आपका keyspace अभी भी 2E24 आकार में है, यहां तक ​​कि हेक्स एन्कोडिंग के साथ है, तो मुझे लगता है कि यह एक सैद्धांतिक चिंता है। मैं आपके सिस्टम के खिलाफ क्रूर बल हमले करने वाले लोगों के बारे में चिंता नहीं करता।

संपादित:

पी.एस .: uuid.uuid4 समारोह यदि उपलब्ध libuuid उपयोग करता है। यह os.urandom (यदि उपलब्ध हो) से अन्यथा एंट्रॉपी प्राप्त करता है अन्यथा वर्तमान समय और स्थानीय ईथरनेट मैक पते से। यदि libuuid उपलब्ध नहीं है तो uuid.uuid4 फ़ंक्शन बाइट्स को os.urandom (अगर उपलब्ध हो) से सीधे प्राप्त करता है अन्यथा यह यादृच्छिक मॉड्यूल का उपयोग करता है। यादृच्छिक मॉड्यूल os.urandom (यदि उपलब्ध हो) के आधार पर डिफ़ॉल्ट बीज का उपयोग करता है अन्यथा वर्तमान समय के आधार पर एक मान। प्रत्येक फ़ंक्शन कॉल के लिए जांच होती है, इसलिए यदि आपके पास os.urandom नहीं है तो ओवरहेड अपेक्षा से थोड़ा बड़ा है।

लें घर संदेश? क्या आप जानते हैं आप os.urandom है तो आप

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

कर सकता है, लेकिन अगर आप इसकी उपलब्धता के बारे में चिंता नहीं करना चाहते तो UUID मॉड्यूल का उपयोग करें।

+0

मैं जोड़ना भूल गया कि यूआरएल सुरक्षित होना चाहिए, मुझे इसे तीन यादृच्छिक वर्णों में निर्दिष्ट करना चाहिए था। मैं आपकी विधि का उपयोग करूंगा और + और/वर्णों को प्रतिस्थापित करूंगा। – coulix

+0

मुझे एक uri_b64encode सुरक्षित विधि मिली जो नौकरी अच्छी तरह से करेगी – coulix

+0

ध्यान दें कि यूयूआईडी 4 आपको 16 यादृच्छिक बाइट्स नहीं देता है। 6 निश्चित (गैर यादृच्छिक) बिट्स हैं। बेशक यह काफी पर्याप्त है। – kmkaplan

2

क्यों पहले md5 या SHA1 हैश से 21 वर्ण नहीं ले?

+0

यह सच है कि काफी यादृच्छिक होना चाहिए पर्याप्त – coulix

+0

कुछ hashlib.md5 की तरह (एसटीआर (random.random())) hexdigest()।: डिफ़ॉल्ट रूप से [21] –

+0

random.random() से किसी और, os.urandom से अपने बीज हो जाता है time.time। ओएस मानते हैं os.urandom का समर्थन करता है, साथ ही os.urandom (11) .encode ("हेक्स") [: 21] कर सकता है। –

4

एमडी 5 के हेक्साडेसिमल प्रतिनिधित्व में बहुत खराब यादृच्छिकता है: आपको केवल प्रति चरित्र एन्ट्रॉपी के 4 बिट मिलते हैं।

उपयोग यादृच्छिक वर्ण, जैसे कुछ:

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

चुनाव में सभी स्वीकार्य पात्रों डाल दिया।

एसएचए 1 जैसे वास्तविक हैश फ़ंक्शन का उपयोग करते समय आपको अच्छे परिणाम मिलेंगे यदि सही ढंग से उपयोग किया गया है, तो अतिरिक्त जटिलता और सीपीयू खपत आपकी आवश्यकताओं के लिए उचित नहीं है। आप केवल एक यादृच्छिक स्ट्रिंग चाहते हैं।

+0

string.ascii_letters, क्योंकि string.letters लोकेल निर्भर है। –

0

अक्षर, या बाइट्स? यदि यह मनमाने ढंग से तार लेता है, तो आप केवल बाइट्स का उपयोग कर सकते हैं और पठनीय पात्रों तक विस्तार करने की चिंता नहीं कर सकते (जिसके लिए बेस 64 हेक्स से भी बेहतर होगा)।

एमडी 5 16 वर्ण उत्पन्न करता है यदि आप इसके हेक्साडेसिमल विस्तार का उपयोग नहीं करते हैं। SHA1 उसी स्थिति के तहत 20 उत्पन्न करता है।

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

उसके बाद कुछ अतिरिक्त बाइट की आवश्यकता है।

2

बेस 64 मॉड्यूल यूआरएल-सुरक्षित एन्कोडिंग कर सकते हैं। तो, अगर जरूरत है,

u.bytes.encode("base64") 

के बजाय आप

import base64 

token = base64.urlsafe_b64encode(u.bytes) 

कर सकता है और, आसानी से, वापस कन्वर्ट करने के लिए

u = uuid.UUID(bytes=base64.urlsafe_b64decode(token)) 
संबंधित मुद्दे