क्रिप्टोग्राफिक रूप से सुरक्षित टोकन उत्पन्न करना


84

हमारे द्वारा वर्तमान में उपयोग किए जा रहे हमारे एपीआई तक पहुँच के लिए एक 32 वर्ण का टोकन उत्पन्न करने के लिए:

$token = md5(uniqid(mt_rand(), true));

मैंने पढ़ा है कि यह विधि क्रिप्टोग्राफिक रूप से सुरक्षित नहीं है क्योंकि यह सिस्टम घड़ी पर आधारित है, और यह openssl_random_pseudo_bytesएक बेहतर समाधान होगा क्योंकि यह भविष्यवाणी करना कठिन होगा।

यदि ऐसा है, तो समतुल्य कोड कैसा दिखेगा?

मैं कुछ इस तरह से मानता हूं, लेकिन मुझे नहीं पता कि क्या यह सही है ...

$token = md5(openssl_random_pseudo_bytes(32));

यह भी कि लंबाई क्या समझती है कि मुझे फंक्शन पास करना चाहिए?


4
हालांकि यह md5 क्यों? बस बाइटस्ट्रीम को हेक्स में परिवर्तित करें: आप 32 बाइट्स से ओपनश्ल_रजैंडर_पसूडो_बाइट्स () से प्राप्त कर रहे हैं, उन बाइट्स में से प्रत्येक को बीन 2 हेक्स के साथ हेक्सेवल्यू के रूप में प्रस्तुत करें () जैसा कि PHP डॉक्स उदाहरणों में दिखाया गया है
मार्क बेकर

मुझे केवल 32 अक्षर चाहिए? मुझे यह कैसे करना है?
अग्नि

10
md5()एक 32 वर्ण स्ट्रिंग उत्पन्न करता है, लेकिन इसमें केवल 128 बिट्स का डेटा है। openssl_random_pseudo_bytes()सही द्विआधारी डेटा देता है, इसलिए इसमें 32 * 8 = 256 बिट्स यादृच्छिकता है। अपने 32-बाइट रैंडम स्ट्रिंग को md5 के माध्यम से भरकर, आप प्रभावी रूप से इसकी विशिष्टता को भारी मात्रा में काट रहे हैं।
मार्क बी

1
तो $token = bin2hex(openssl_random_pseudo_bytes(16));पर्याप्त है या क्या मुझे 1 के रूप में लंबाई और हेक्स में एक स्ट्रिंग में जोड़कर 16 पुनरावृत्तियों के लूप की आवश्यकता है?
अग्नि

हेक्स में परिवर्तित 16 बाइट्स के साथ अंतिम समाधान सही है। लेकिन आपको वास्तव में यहाँ # 1 # 2 # 3 पर ओपनएसएसएल पर भरोसा नहीं करना चाहिए । जैसे ही आप PHP 7.0+ पर हैं, इसका उपयोग करने के लिए वास्तव में कोई बहाना नहीं है। ओपनएसएसएल और हेक्स एन्कोडिंग के बजाय, कोशिश करें Random::alphanumericString($length), जो उन 16 पात्रों में लगभग 2 बिलियन गुना "एन्ट्रापी" फिट बैठता है।
कांव-कांव

जवाबों:


189

यहाँ सही समाधान है:

$token = bin2hex(openssl_random_pseudo_bytes(16));

# or in php7
$token = bin2hex(random_bytes(16));

1
मैंने एक और उत्तर जोड़ा है कि आप CryptoLib के साथ Opensl_random_pseudo_bytes का उपयोग करके एक अद्वितीय टोकन कैसे उत्पन्न कर सकते हैं। यह आपको केवल 0-9, AF के विपरीत सभी पात्रों के साथ टोकन उत्पन्न करने की अनुमति देता है।
mjsa

4
Random_bytes () और random_int () github.com/paragonie/random_compat
MTK

4
आप यह भी चाह bin2hex(random_bytes($length/2))सकते हैं क्योंकि आपके पास प्रत्येक बाइट के लिए 2 हेक्स वर्ण हो सकते हैं, इसलिए वर्णों की संख्या हमेशा $lengthइसके बिना दोगुनी होगी
एक मित्र का

3
@ सैफ्रीड सहमत। यदि आप एक फ़ंक्शन बनाना चाहते हैं जो $lengthवर्णों की संख्या की एक स्ट्रिंग पैदा करता है (बाइट के आकार की परवाह करने के बजाय) तो आप पास करना चाहेंगे random_bytes($length/2)
BadHorsie

10

यदि आप Opensl_random_pseudo_bytes का उपयोग करना चाहते हैं तो CrytoLib के कार्यान्वयन का उपयोग करना सबसे अच्छा है, यह आपको सभी अल्फ़ान्यूमेरिक वर्ण उत्पन्न करने की अनुमति देगा, खुलता है bin2hex के चारों ओर खुलता हैsl_random_pseudo_bytes आपको केवल AF (कैप्स) और संख्याएँ प्राप्त करेगा।

पाथ / / को बदलें जहाँ आप cryptolib.php फ़ाइल डालते हैं (आप इसे GitHub पर देख सकते हैं: https://github.com/IcyApril/CryptoLib )

<?php
  require_once('path/to/cryptolib.php');
  $token = IcyApril\CryptoLib::randomString(16);
?>

पूरा क्रिप्टोकरंसी प्रलेखन यहाँ उपलब्ध है: https://cryptolib.ju.je/ । यह कई अन्य यादृच्छिक तरीकों, कैस्केडिंग एन्क्रिप्शन और हैश पीढ़ी और सत्यापन को शामिल करता है; लेकिन यह वहां है अगर आपको इसकी आवश्यकता है।


बाइट्स की समान संख्या के लिए: openssl_random_pseudo_bytes(16)प्रत्येक बाइट का कोई भी मान (0-255) हो सकता है, जबकि randomString(16)प्रत्येक बाइट में केवल az Az 0-9 हो सकता है जो प्रति बाइट में 62 संयोजन है। यूएन रैंडम स्ट्रींग स्ट्रिंग की लंबाई प्रति बेहतर है , क्योंकि बिन 2 इंच अकुशल एन्कोडिंग (50%) है; base64_encode(openssl_random_pseudo_bytes(16))एक छोटी स्ट्रिंग के लिए उपयोग करने के लिए बेहतर है और सुरक्षा की बाइट्स की एक सटीक ज्ञात संख्या (इस मामले में 16 लेकिन आवश्यक रूप से बदल दें)
रॉडने

1
@Rodney भालू मन आधार में 64 भी स्ट्रिंग वाली उत्पादन करेगा +, /और =वर्ण, इसलिए यदि आप एक उपयोगकर्ता के अनुकूल टोकन (जैसे एक API कुंजी) उत्पन्न करने के लिए यह आदर्श नहीं है कोशिश कर रहे हैं।
BadHorsie

9

यदि आपके पास एक क्रिप्टोग्राफिक रूप से सुरक्षित यादृच्छिक संख्या जनरेटर है, तो आपको इसे आउटपुट करने की आवश्यकता नहीं है। वास्तव में आप नहीं करना चाहते हैं। महज प्रयोग करें

$token  = openssl_random_pseudo_bytes($BYTES,true)

हालांकि $ BYTES डेटा के कई बाइट्स आप चाहते हैं। एमडी 5 में 128 बिट हैश है, इसलिए 16 बाइट करेंगे।

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


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

-1

विश्वसनीय पासवर्ड आप केवल एससीआई अक्षर ए-जेडए-जेड और संख्या 0-9 से बना सकते हैं । ऐसा करने के लिए सबसे अच्छा तरीका केवल क्रिप्टोग्राफिक रूप से सुरक्षित तरीकों का उपयोग कर रहा है, जैसे कि random_int () या random_bytes () PHP7 से। बेस 64_encode () के रूप में बाकी कार्य आप स्ट्रिंग की विश्वसनीयता बनाने और इसे ASCII वर्णों में बदलने के लिए समर्थन कार्यों के रूप में उपयोग कर सकते हैं ।

mt_rand () सुरक्षित नहीं है और बहुत पुराना है। किसी भी स्ट्रिंग से आपको random_int () का उपयोग करना होगा। बाइनरी स्ट्रिंग से आपको बाइनरी स्ट्रिंग को विश्वसनीय या Bin2hex बनाने के लिए base64_encode () का उपयोग करना चाहिए , लेकिन तब आप केवल 16 पदों (मूल्यों) पर बाइट काट लेंगे। मेरे इस कार्य का कार्यान्वयन देखें। यह सभी भाषाओं का उपयोग करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.