यहाँ समस्या मूल रूप से एन्ट्रापी की समस्या है। तो चलिए देखना शुरू करते हैं:
प्रवेश प्रति चरित्र
प्रति बाइट एन्ट्रापी के बिट्स की संख्या हैं:
- हेक्स वर्ण
- बिट्स: 4
- मान: 16
- एन्ट्रॉपी इन 72 चार्ट्स: 288 बिट्स
- अल्फा-न्यूमेरिक
- बिट्स: 6
- मान: 62
- एन्ट्रॉपी इन 72 चार्ट्स: 432 बिट्स
- "आम" प्रतीक
- बिट्स: 6.5
- मान: 94
- एन्ट्रॉपी इन 72 चार्ट्स: 468 बिट्स
- पूर्ण बाइट्स
- बिट्स: 8
- मान: 255
- एन्ट्रॉपी इन 72 चार्ट्स: 576 बिट्स
इसलिए, हम कैसे कार्य करते हैं, इस पर निर्भर करता है कि हम किस प्रकार के पात्रों की अपेक्षा करते हैं।
पहली समस्या
आपके कोड के साथ पहली समस्या यह है कि आपका "काली मिर्च" हैश कदम हेक्स वर्णों को आउटपुट कर रहा है (चूंकि चौथा पैरामीटर hash_hmac()
सेट नहीं है)।
इसलिए, अपनी काली मिर्च को हैशिंग में, आप प्रभावी रूप से 2 (576 से 288 संभावित बिट्स) के कारक द्वारा पासवर्ड के लिए उपलब्ध अधिकतम एन्ट्रापी को काट रहे हैं ।
दूसरी समस्या
हालांकि, sha256
केवल 256
पहले स्थान पर एंट्रोपी के टुकड़े प्रदान करता है। तो आप प्रभावी रूप से 576 बिट्स को 256 बिट्स तक प्रभावी रूप से काट रहे हैं। आपका हैश चरण * तुरंत *, बहुत परिभाषा से पासवर्ड में कम से कम 50% संभावित एन्ट्रोपी खो देता है
।
आप इसे आंशिक रूप से उस पर स्विच करके हल कर सकते हैं SHA512
, जहाँ आप केवल उपलब्ध एंट्रॉपी को लगभग 12% कम कर देंगे। लेकिन यह अभी भी एक महत्वहीन अंतर है। वह 12% के एक कारक द्वारा क्रमपरिवर्तन की संख्या को कम करता है 1.8e19
। यह एक बड़ी संख्या है ... और यह वह कारक है जो इसे कम करता है ...
अवर मुद्दा
अंतर्निहित मुद्दा यह है कि 72 वर्णों से अधिक तीन प्रकार के पासवर्ड हैं। इस शैली प्रणाली का उन पर प्रभाव बहुत अलग होगा:
नोट: यहां से मैं मान रहा हूं कि हम एक काली मिर्च प्रणाली की तुलना कर रहे हैं जो SHA512
कच्चे आउटपुट (हेक्स नहीं) के साथ उपयोग करता है ।
उच्च एन्ट्रापी यादृच्छिक पासवर्ड
ये आपके उपयोगकर्ता हैं जो पासवर्ड जेनरेटर का उपयोग करते हैं जो पासवर्ड के लिए बड़ी कुंजी को उत्पन्न करते हैं। वे यादृच्छिक (उत्पन्न, मानव चुने हुए नहीं) हैं, और प्रति चरित्र उच्च एन्ट्रापी हैं। ये प्रकार उच्च-बाइट्स (वर्ण> 127) और कुछ नियंत्रण वर्ण का उपयोग कर रहे हैं।
इस समूह के लिए, आपका हैशिंग फ़ंक्शन उनके उपलब्ध एन्ट्रापी को काफी कम कर देगा bcrypt
।
मुझे फिर वही बात कहना है। उन उपयोगकर्ताओं के लिए जो उच्च एन्ट्रापी, लंबे पासवर्ड का उपयोग कर रहे हैं, आपके समाधान से उनके पासवर्ड की शक्ति काफी कम हो जाती है। (72 वर्ण कूटशब्द के लिए एन्ट्रापी के 62 बिट्स खो गए, और अधिक लंबे पासवर्ड के लिए)
मध्यम एन्ट्रापी यादृच्छिक पासवर्ड
यह समूह सामान्य प्रतीकों वाले पासवर्ड का उपयोग कर रहा है, लेकिन कोई उच्च बाइट या नियंत्रण वर्ण नहीं है। ये आपके टाइप करने योग्य पासवर्ड हैं।
इस समूह के लिए, आप अधिक एन्ट्रॉपी को थोड़ा अनलॉक करने जा रहे हैं (इसे न बनाएं, लेकिन अधिक एन्ट्रापी को bcrypt पासवर्ड में फिट होने दें)। जब मैं थोड़ा कहता हूं, तो मेरा मतलब थोड़ा होता है। ब्रेक-इवन तब भी होता है जब आप SHA512 के 512 बिट्स को अधिकतम करते हैं। इसलिए, शिखर 78 वर्णों पर है।
मुझे फिर वही बात कहना है। पासवर्डों की इस श्रेणी के लिए, आप एंट्रॉपी से बाहर निकलने से पहले केवल एक अतिरिक्त 6 अक्षर स्टोर कर सकते हैं।
कम एन्ट्रापी गैर-यादृच्छिक पासवर्ड
यह वह समूह है जो अल्फा-न्यूमेरिक वर्णों का उपयोग कर रहे हैं, जो शायद यादृच्छिक रूप से उत्पन्न नहीं होते हैं। एक बाइबिल बोली या ऐसा कुछ। इन वाक्यांशों में प्रति वर्ण लगभग 2.3 बिट्स एन्ट्रापी हैं।
इस समूह के लिए, आप बहुत से एन्ट्रॉपी को अनलॉक कर सकते हैं (इसे न बनाएं, लेकिन अधिक जानकारी को bcrypt पासवर्ड इनपुट में फिट करने की अनुमति दें)। जब आप एन्ट्रापी से बाहर निकलते हैं, तो ब्रेकेवन लगभग 223 अक्षर का होता है।
चलिए फिर बताते हैं। पासवर्ड के इस वर्ग के लिए, प्री-हैशिंग निश्चित रूप से सुरक्षा में काफी वृद्धि करता है।
असली दुनिया में वापस
इस तरह की एन्ट्रापी गणना वास्तव में वास्तविक दुनिया में ज्यादा मायने नहीं रखती है। क्या मामलों में एंट्रोपी अनुमान लगा रही है। हमलावरों क्या कर सकते हैं कि सीधे प्रभाव। यही आप अधिकतम करना चाहते हैं।
हालांकि वहाँ थोड़ा अनुसंधान है कि एंट्रोपी अनुमान लगाने में चला गया है, कुछ बिंदु हैं जो मैं इंगित करना चाहता हूं।
एक पंक्ति में बेतरतीब ढंग से 72 सही पात्रों की संभावना बेहद कम है। इस टक्कर के होने की तुलना में, आपको 21 बार पॉवरबॉल लॉटरी जीतने की संभावना है ... यह एक बड़ी संख्या है जिसके बारे में हम बात कर रहे हैं।
लेकिन हम इस पर सांख्यिकीय रूप से नहीं ठोकर खा सकते हैं। वाक्यांशों के मामले में पहले 72 अक्षरों के होने की संभावना यादृच्छिक पासवर्ड के लिए पूरी तरह से बहुत अधिक है। लेकिन यह अभी भी तुच्छ रूप से कम है (आप प्रति वर्ण 2.3 बिट्स के आधार पर 5 बार पावरबॉल लॉटरी जीतने की अधिक संभावना है)।
वास्तव में
व्यावहारिक रूप से, यह वास्तव में मायने नहीं रखता है। पहले 72 वर्णों के सही होने का अनुमान लगाने की संभावना, जहां बाद वाले महत्वपूर्ण अंतर रखते हैं, वे इतने कम होते हैं कि यह चिंता करने लायक नहीं है। क्यों?
ठीक है, मान लें कि आप एक वाक्यांश ले रहे हैं। यदि व्यक्ति को पहले 72 अक्षर सही मिल सकते हैं, तो वे वास्तव में भाग्यशाली हैं (संभावना नहीं है), या यह एक सामान्य वाक्यांश है। यदि यह एक सामान्य वाक्यांश है, तो इसे बनाने के लिए एकमात्र चर कितना लंबा है।
एक उदाहरण लेते हैं। आइए बाईबल से एक उद्धरण लें (सिर्फ इसलिए कि यह लंबे पाठ का एक सामान्य स्रोत है, किसी अन्य कारण से नहीं):
आप अपने पड़ोसी के घर को लालच नहीं देंगे। आप अपने पड़ोसी की पत्नी, या उसकी हवेली या नौकरानी, उसके बैल या गधे, या आपके पड़ोसी की किसी भी चीज़ का लालच नहीं करेंगे।
वह 180 अक्षर का है। 73 वां वर्ण g
दूसरे में है neighbor's
। यदि आपने ऐसा अनुमान लगाया है, तो आप संभवत: रोक नहीं रहे हैं nei
, लेकिन शेष कविता के साथ जारी है (क्योंकि पासवर्ड का उपयोग किए जाने की संभावना है)। इसलिए, आपके "हैश" ने बहुत कुछ नहीं जोड़ा।
BTW: मैं ABSOLUTELY एक बाइबिल बोली का उपयोग करने की वकालत नहीं कर रहा हूँ। वास्तव में, ठीक इसके विपरीत।
निष्कर्ष
आप वास्तव में पहले हैशिंग द्वारा लंबे पासवर्ड का उपयोग करने वाले लोगों की मदद करने वाले नहीं हैं। कुछ समूह आप निश्चित रूप से मदद कर सकते हैं। कुछ आप निश्चित रूप से चोट कर सकते हैं।
लेकिन अंत में, इसमें से कोई भी अत्यधिक महत्वपूर्ण नहीं है। संख्या हम साथ काम कर रहे बस कर रहे हैं रास्ता बहुत अधिक है। एन्ट्रापी में अंतर ज्यादा होने वाला नहीं है।
आप bcrypt को छोड़ना बेहतर समझते हैं। आपके पास हैशिंग (शाब्दिक रूप से पेंच करने की अधिक संभावना है, आपने इसे पहले ही कर लिया है, और आप उस गलती से पहले, या अंतिम नहीं हैं) जिस हमले को आप रोकने की कोशिश कर रहे हैं वह होने जा रहा है।
बाकी साइट को सुरक्षित करने पर ध्यान दें। और पासवर्ड की शक्ति को इंगित करने के लिए पंजीकरण पर पासवर्ड बॉक्स में एक पासवर्ड एन्ट्रापी मीटर जोड़ें (और इंगित करें कि क्या पासवर्ड अधिक है कि उपयोगकर्ता इसे बदलना चाह सकता है) ...
कि मेरी $ 0.02 कम से कम (या संभवतः $ 0.02 से अधिक है) ...
जहां तक "सीक्रेट" काली मिर्च का उपयोग करने की बात है:
शाब्दिक रूप से bcrypt में एक हैश फ़ंक्शन को खिलाने में कोई शोध नहीं है। इसलिए, यह सबसे अच्छा नहीं है अगर bcrypt में "peppered" हैश को खिलाने से कभी अज्ञात कमजोरियां होंगी (हम जानते हैं कि hash1(hash2($value))
टकराव प्रतिरोध और प्राइमेज हमलों के आसपास महत्वपूर्ण कमजोरियों को उजागर कर सकते हैं)।
यह देखते हुए कि आप पहले से ही एक गुप्त कुंजी ("काली मिर्च") के भंडारण पर विचार कर रहे हैं, इसका उपयोग इस तरह से क्यों नहीं किया जाता है जो अच्छी तरह से अध्ययन और समझ में आता है? इसे संग्रहीत करने से पहले हैश को एन्क्रिप्ट क्यों नहीं किया जाता है?
असल में, आपके पास पासवर्ड हैश करने के बाद, पूरे हैश आउटपुट को एक मजबूत एन्क्रिप्शन एल्गोरिथ्म में फीड करें। फिर एन्क्रिप्टेड परिणाम को स्टोर करें।
अब, SQL- इंजेक्शन का हमला कुछ भी उपयोगी नहीं होगा, क्योंकि उनके पास सिफर कुंजी नहीं है। और अगर चाबी लीक हो जाती है, तो हमलावर आपसे बेहतर नहीं हैं यदि आपने एक सादे हैश का उपयोग किया है (जो कि सिद्ध है, काली मिर्च "प्री-हैश" प्रदान नहीं करता है)।
नोट: यदि आप ऐसा करने के लिए चुनते हैं, तो एक पुस्तकालय का उपयोग करें। PHP के लिए, मैं दृढ़ता से Zend फ्रेमवर्क 2 के Zend\Crypt
पैकेज की सिफारिश करता हूं । यह वास्तव में केवल एक ही है जिसे मैं इस वर्तमान बिंदु पर सुझाऊँगा। इसकी जोरदार समीक्षा की गई है, और यह आपके लिए सभी निर्णय लेता है (जो कि बहुत अच्छी बात है) ...
कुछ इस तरह:
use Zend\Crypt\BlockCipher;
public function createHash($password) {
$hash = password_hash($password, PASSWORD_BCRYPT, ["cost"=>$this->cost]);
$blockCipher = BlockCipher::factory('mcrypt', array('algo' => 'aes'));
$blockCipher->setKey($this->key);
return $blockCipher->encrypt($hash);
}
public function verifyHash($password, $hash) {
$blockCipher = BlockCipher::factory('mcrypt', array('algo' => 'aes'));
$blockCipher->setKey($this->key);
$hash = $blockCipher->decrypt($hash);
return password_verify($password, $hash);
}
और यह फायदेमंद है क्योंकि आप सभी एल्गोरिदम का उपयोग उन तरीकों से कर रहे हैं जिन्हें अच्छी तरह से समझा जाता है और अच्छी तरह से अध्ययन किया जाता है (अपेक्षाकृत कम से कम)। याद है:
कोई भी, सबसे क्लूलेस शौकिया से सर्वश्रेष्ठ क्रिप्टोग्राफर तक, एक एल्गोरिथ्म बना सकता है जिसे वह खुद नहीं तोड़ सकता।