2009-03-12 15 views
36

मैं एक पुन: प्रयोज्य फ़ंक्शन बनाना चाहता हूं जो चयनित लंबाई के प्रिंट करने योग्य ACSII वर्णों (2 से 1000+ तक) के साथ एक यादृच्छिक कुंजी उत्पन्न करेगा। मैं सोच रहा हूं कि प्रिंट करने योग्य ASCII वर्ण 33-126 होंगे। उन्हें कुंजी पूरी तरह अनूठी होने की आवश्यकता नहीं है, अगर सटीक उसी मिलीसेकंड पर उत्पन्न होता है तो अनूठा (इसलिए uniqid() काम नहीं करेगा)।PHP के भीतर एक यादृच्छिक कुंजी उत्पन्न करने का सबसे अच्छा तरीका क्या है?

मैं chr() और mt_rand() का संयोजन सोच रहा हूं।

क्या यह जाने का तरीका है, या कुछ और सर्वोत्तम तरीका है?

संपादित करें:uniqid() भी काम नहीं करेगा क्योंकि इसमें लंबाई पैरामीटर नहीं है, यह वही है जो PHP आपको देता है।

मेरा उपाय:

function GenerateKey($length = 16) { 
    $key = ''; 

    for($i = 0; $i < $length; $i ++) { 
     $key .= chr(mt_rand(33, 126)); 
    } 

    return $key; 
} 

वहाँ इस के साथ कोई समस्या है: यह है कि मैं क्या के साथ आया है?

अन्य संपादित करें: अन्य प्रश्नों में से अधिकांश पासवर्ड पीढ़ी के साथ सौदा करते हैं। मुझे कई प्रकार के पात्र चाहिए और मुझे 1 बनाम l परवाह नहीं है। मैं चाहता हूं कि अधिकतम कुंजियों की अधिकतम संख्या संभव हो।

नोट: जेनरेट की गई कुंजी को क्रिप्टोग्राफ़िक रूप से सुरक्षित नहीं होना चाहिए।

+0

रैंडम संख्या जनरेटर आम तौर पर _guarantee_ नहीं विशिष्टता करते हैं, भले ही "सटीक एक ही मिलीसेकंड पर उत्पन्न होता है।" विशिष्टता की गारंटी के लिए, आपको टकराव का पता लगाने में सक्षम होना चाहिए। – danorton

+0

सुरक्षा के बारे में बड़ी चेतावनी जोड़ा गया, अन्यथा मुझे प्रत्येक उत्तर को कम करना होगा। चेतावनी दीजिये कि उत्तर में कुछ कार्य बाइनरी लौटते हैं, अन्य हेक्स, अन्य बेस 64 इत्यादि लौटते हैं। –

उत्तर

54

अद्यतन (12/2015): पीएचपी 7.0, आप mt_rand के बजाय random_int() का उपयोग करना चाहिए के लिए के रूप में यह "क्रिप्टोग्राफी द्वारा सुरक्षित मूल्यों"

व्यक्तिगत रूप से प्रदान करता है, मैं sha1(microtime(true).mt_rand(10000,90000)) का उपयोग करना चाहते हैं, लेकिन आप अधिक के लिए देख रहे हैं एक अनुकूलन दृष्टिकोण है, इसलिए इस समारोह (जो this answer के आपके अनुरोध के एक संशोधन है) की कोशिश: फिर भी

function rand_char($length) { 
    $random = ''; 
    for ($i = 0; $i < $length; $i++) { 
    $random .= chr(mt_rand(33, 126)); 
    } 
    return $random; 
} 

, यह शायद uniqid की तुलना में काफी धीमी हो जाएगा(), md5(), या SHA1()।

संपादित करें: ऐसा लगता है कि आपको पहले यह मिला, क्षमा करें। : डी

संपादित करें 2: मैं PHP 5 और eAccelerator के साथ अपने डेबियन मशीन पर एक अच्छी छोटी परीक्षण करना का फैसला किया (लंबी कोड बहाना):

function rand_char($length) { 
    $random = ''; 
    for ($i = 0; $i < $length; $i++) { 
    $random .= chr(mt_rand(33, 126)); 
    } 
    return $random; 
} 

function rand_sha1($length) { 
    $max = ceil($length/40); 
    $random = ''; 
    for ($i = 0; $i < $max; $i ++) { 
    $random .= sha1(microtime(true).mt_rand(10000,90000)); 
    } 
    return substr($random, 0, $length); 
} 

function rand_md5($length) { 
    $max = ceil($length/32); 
    $random = ''; 
    for ($i = 0; $i < $max; $i ++) { 
    $random .= md5(microtime(true).mt_rand(10000,90000)); 
    } 
    return substr($random, 0, $length); 
} 

$a = microtime(true); 
for ($x = 0; $x < 1000; $x++) 
    $temp = rand_char(1000); 

echo "Rand:\t".(microtime(true) - $a)."\n"; 

$a = microtime(true); 
for ($x = 0; $x < 1000; $x++) 
    $temp = rand_sha1(1000); 

echo "SHA-1:\t".(microtime(true) - $a)."\n"; 

$a = microtime(true); 
for ($x = 0; $x < 1000; $x++) 
    $temp = rand_md5(1000); 

echo "MD5:\t".(microtime(true) - $a)."\n"; 

परिणाम:

Rand: 2.09621596336 
SHA-1: 0.611464977264 
MD5: 0.618473052979 

तो मेरा सुझाव, यदि आप गति चाहते हैं (लेकिन पूर्ण वर्णमाला नहीं), एमडी 5, एसएचए -1, या यूनिकिड (जिसे मैंने परीक्षण नहीं किया है ..) तक चिपकाना है।

+1

बीट या बस कुछ सेकंड तक। –

+3

बीट या कुछ महीनों तक;) – lpfavreau

+0

+1 मूल कोड के लिए स्वच्छ उत्तर और संशोधन के लिए +1, यह mt_rand() – lpfavreau

0

क्या that question आपके लिए ब्याज होगा?

मुझे यकीन नहीं है कि uniqid() आपके लिए क्यों काम नहीं करता है और किस मामले में आपको एक ही मिलीसेकंड में एक अद्वितीय संख्या की आवश्यकता होती है लेकिन अन्यथा आवश्यक नहीं है; आप इतनी तेजी से क्या उत्पन्न कर रहे हैं कि एक ही मिलीसेकंड में आप टकराव कर सकते हैं? मैं सोच रहा हूं कि uniqid() कितना समय लगता है इसकी संख्या उत्पन्न करने के लिए। यदि आप चाहते हैं, तो कुछ यादृच्छिक अक्षरों के साथ uniqid() फ़ंक्शन के उपसर्ग पैरामीटर का उपयोग करें और आपको सुरक्षित होना चाहिए।

यदि यह फ़ाइल उत्पन्न करने के लिए है, तो आप tmpfile() या tempname() पर देख सकते हैं।

किसी भी मामले में, जो आप प्राप्त करने का प्रयास कर रहे हैं उसके आधार पर, आप केवल लूप कर सकते हैं और सत्यापित कर सकते हैं कि अद्वितीय आईडी पहले से ही ली गई है (एक सरणी में, file_exists, आदि के साथ) और यदि मामला है तो बस एक और उत्पन्न करें ।


इसके अलावा

, के रूप में मुझे यकीन है कि मैं आपके सवाल का ठीक से समझ नहीं कर रहा हूँ, मैं तुम्हें उन अन्य प्रश्न है कि बहुत समान ध्वनि, जबकि मैं तुम्हारा के अंतर पाने के लिए बात करेंगे:

पहले एक आप में एक विशिष्ट आईडी कि मानव पठनीय है क्या करने के लिए देख रहे हैं ब्याज की हो जाएगा। दूसरा अगर आप यादृच्छिक संख्या और md5/sha1 के साथ खेलना चाहते हैं तो उपयोगी हो सकता है। हालांकि, फिर, मुझे लगता है कि uniqid() पहले से ही हो सकता है कि आप क्या देख रहे हैं।

7

आप अभी भी se uniqid(), बस अपने मूल्य को विस्तारित करने के लिए कुछ अतिरिक्त प्रोसेसिंग करें जो आपको चाहिए।

उदाहरण के लिए, 32 वर्णों को विस्तृत करने के लिए, आप तो इतना

$first = md5(uniqid()); 
$id = $first . md5($first); 

की तरह,

$id = md5(uniqid()); 

64 वर्णों तक यह विस्तार करने के लिए, बस md5 की md5 संलग्न कर सकता है, आवश्यकतानुसार प्रशिक्षित करें, अगर आपको 32 के कुछ से अधिक की आवश्यकता है।

यह संभव है कि आप टकराव में भाग सकें, लेकिन यह काफी संभावना नहीं है। यदि आप इसके बारे में पागल हैं, तो बस एक ही विचार का उपयोग करें, लेकिन uniqid() को एक सममित सिफर के माध्यम से एईएस की बजाय इसे हस करने के बजाय चिपकाएं।

27

यदि आप क्रिप्टोग्राफिक-शक्ति यादृच्छिकता चाहते हैं तो यहां कोई भी जवाब पर्याप्त नहीं है (क्या कोई निर्धारित हमलावर यह अनुमान लगाने का प्रयास कर रहा है कि आपकी यादृच्छिक कुंजी क्या हैं?)। समय को धक्का देना सुरक्षित नहीं है, एक हमलावर अपने सर्वर को कुंजी उत्पन्न करने के समय अनुमान लगाकर अपनी खोज को तेज़ी से बढ़ा सकता है, और किसी भी वर्ष में सभी मिलीसेकंडों को खोजना आसान है, यहां तक ​​कि एक कमोडिटी लैपटॉप पर (यह 35 है बिट खोज स्थान)। साथ ही, uniqid() या किसी अन्य कमजोर यादृच्छिक स्रोत के परिणाम को "इसे विस्तारित" करने के लिए केवल खतरनाक स्रोतों को चलाने के सुझाव खतरनाक हैं- इससे पता चलता है कि यह करने के बाद यह हमलावर की खोज को कठिन बना देता है।

तुम सच में क्रिप्टो-स्तर की सुरक्षा की जरूरत है, तो आप पढ़ना चाहिए/से देव/यादृच्छिक, निम्नलिखित कोड आपके लिए किसी भी POSIX अनुरूप प्रणाली (लेकिन Windows कुछ भी) में काम करना चाहिए:

#Generate a random key from /dev/random 
function get_key($bit_length = 128){ 
    $fp = @fopen('/dev/random','rb'); 
    if ($fp !== FALSE) { 
     $key = substr(base64_encode(@fread($fp,($bit_length + 7)/8)), 0, (($bit_length + 5)/6) - 2); 
     @fclose($fp); 
     return $key; 
    } 
    return null; 
} 

आप तो थोड़ी अधिक गति की आवश्यकता है, आप इसके बजाय 'dev/urandom' से पढ़ सकते हैं।

+4

बस ध्यान रखना चाहता था - मेरे पास एक ऐसी स्क्रिप्ट थी जो लोड करने के लिए अतिरिक्त 50 या उससे अधिक समय ले रही थी, और यह/dev/urandom के बजाय/dev/random का उपयोग करने का कारण बन गया। मेरे स्थानीय परीक्षण पर्यावरण पर, यह कभी नहीं हुआ। – whichdan

+4

'/ dev/urandom' डिफ़ॉल्ट होना चाहिए, '/ dev/random /' का उपयोग करके यादृच्छिक एन्ट्रॉपी पूल बहुत जल्द समाप्त हो जाएगा (सिस्टम पर सिस्टम पर '/ dev/random' से जुड़े समर्पित यादृच्छिक संख्या जनरेटर के बिना)। दरअसल, चूंकि हमलावर के लिए डीओएस हमले करने का एक अच्छा तरीका होगा, मुझे नहीं लगता कि समारोह को बिल्कुल उजागर किया जाना चाहिए, यह केवल अपने स्वयं के पीआरएनजी के साथ अनुप्रयोगों/पुस्तकालयों के लिए उपयोगी है। –

3

openssl_random_pseudo_bytes का उपयोग क्यों नहीं http://www.php.net/manual/en/function.openssl-random-pseudo-bytes.php

+0

यह उत्तर अधिक प्रभावी होगा यदि आपने एक उदाहरण दिखाया कि यह कैसे मदद करेगा। – ethrbunny

+0

मैं उपरोक्त का उपयोग सफलतापूर्वक $ sessionkey = bin2hex (openssl_random_pseudo_bytes (1024)) के रूप में कर रहा हूं; यह एक क्रिप्टोग्राफिक रूप से सुरक्षित यादृच्छिक कुंजी उत्पन्न करता है ... यह एक जवाब है .. 'एक यादृच्छिक कुंजी उत्पन्न करने का सबसे अच्छा तरीका' ... यह एक बहुत अच्छा तरीका है .. ए) यह एक साधारण त्वरित कार्य का उपयोग करता है ... यह है क्रिप्पो सुरक्षित, यह स्पष्ट रूप से यादृच्छिक है .. और आप किसी भी लंबाई की चाबियाँ उत्पन्न कर सकते हैं ... –

0

$ कुंजी = md5 (microtime() रैंड()।);

माइक्रोटाइम स्वयं सुरक्षित नहीं है क्योंकि यह अनुमान लगाने का केवल 1/1000 मौका छोड़ देता है।

खुद ही रैंड भी बहुत सुरक्षित नहीं है, लेकिन उन्हें एक साथ जोड़कर उन्हें एक ठोस ठोस यादृच्छिकता मिलती है।

+0

"खुद ही रैंड भी बहुत सुरक्षित नहीं है, लेकिन उन्हें एक साथ जोड़कर उन्हें एक ठोस ठोस यादृच्छिकता मिलती है।" नहीं। आपके पास 'रैंड() 'से एन्ट्रॉपी के 32 बिट्स की ऊपरी सीमा के साथ अनुमानित मूल्य है। अगर हम मानते हैं कि 'माइक्रोटाइम()' में एन्ट्रॉपी के 10 बिट होते हैं, तो आप लगभग 42 बिट्स के साथ समाप्त होते हैं। प्रत्येक 2 मिलियन नमूने के बाद जन्मदिन टकराव, लेकिन 'रैंड() 'अनुमानित है। बेहतर समाधान: कुंजी उत्पन्न करने के लिए एक सीएसपीआरएनजी का प्रयोग करें। –

1

मेरा पिछला उत्तर सिस्टम चर से प्राप्त नमक के साथ संयुक्त यूनिकिड() का हैश ले गया, लेकिन यह यादृच्छिक कुंजी उत्पन्न नहीं करता है, केवल एक ही अद्वितीय होने की संभावना है। इसी प्रकार, रैंड() या mt_rand() से आउटपुट क्रिप्टोग्राफिक उद्देश्यों के लिए पर्याप्त यादृच्छिक नहीं है।() यह मुद्रण योग्य अक्षरों में बनाने के लिए है

$randkey = base64_encode(openssl_random_pseudo_bytes(32)); 

base64_encode:

एक यादृच्छिक कुंजी उत्पन्न करने के लिए, आप एक अच्छी यादृच्छिक डेटा स्रोत के लिए जाने की जरूरत है, और समारोह openssl_random_pseudo_bytes() ऐसा करने के लिए बनाया गया है।

अन्य उत्तरों की सिफारिश नहीं है openssl_random_pseudo_bytes() शायद यह है कि इसे PHP 5.3 में पेश किया गया था, और यह प्रश्न लगभग 6 वर्ष पुराना है।

-1

इसके अलावा, आप एक यादृच्छिक कुंजी उत्पन्न करने और अपने DB में महत्वपूर्ण जाँच करता है, तो कुंजी बाहर निकलता है कर सकते हैं, तो आप इस विधि द्वारा एक अन्य प्रमुख उत्पन्न कर सकते हैं

 function activation($lengt=20){ 
    $modalpage =new Modal;//you can call your modal page and check the key 

    $characters = "1234567890abcdefghijklmnopqrstuvwxyz"; 
    for($i=0;$i<$lengt;$i++) 

    {  

    $key .= $characters{rand(0,35)}; 
    $check= array(
    ":key" => $key, 
    ); 

    $result = $modalpage->findkey($check); 

    if($result==true){ //if the key is exits return the function and generate another key ! 

     return activation($lengt); 

    }else //if the key is not exits return the key 
    return $key; 
    } 


      } 

$mykey=activation(15); 
संबंधित मुद्दे