2010-09-29 10 views
17

मैं अपने डेटाबेस में पासवर्ड स्टोर और सत्यापित करने के तरीके के रूप में PHP के crypt() का उपयोग कर रहा हूं। मैं अन्य चीजों के लिए हैशिंग का उपयोग करता हूं, लेकिन crypt() पासवर्ड के लिए। दस्तावेज इतना अच्छा नहीं है और ऐसा लगता है कि बहुत बहस हो रही है। मैं पासवर्ड को क्रिप्ट करने और डेटाबेस में स्टोर करने के लिए ब्लाफिश और दो लवण का उपयोग कर रहा हूं। इससे पहले कि मैं नमक और एन्क्रिप्टेड पासवर्ड स्टोर करूंगा, (एक नमकीन हैश की तरह) लेकिन इसका अनावश्यक महसूस हुआ क्योंकि नमक एन्क्रिप्टेड पासवर्ड स्ट्रिंग का हिस्सा है।क्या मैं PHP के क्रिप्ट() फ़ंक्शन का सही उपयोग कर रहा हूं?

मैं थोड़ा उलझन में हूं कि इंद्रधनुष तालिका के हमले crypt() पर कैसे काम करेंगे, वैसे भी यह एक सुरक्षा दृष्टिकोण से सही दिखता है। मैं छोटे पासवर्ड की एन्ट्रॉपी बढ़ाने के लिए पासवर्ड में जोड़ने के लिए दूसरा नमक का उपयोग करता हूं, शायद अधिक मात्रा में लेकिन क्यों नहीं?

function crypt_password($password) { 
if ($password) { 
    //find the longest valid salt allowed by server 
    $max_salt = CRYPT_SALT_LENGTH; 

    //blowfish hashing with a salt as follows: "$2a$", a two digit cost parameter, "$", and 22 base 64 
    $blowfish = '$2a$10$'; 

    //get the longest salt, could set to 22 crypt ignores extra data 
    $salt = get_salt ($max_salt); 

    //get a second salt to strengthen password 
    $salt2 = get_salt (30); //set to whatever 


    //append salt2 data to the password, and crypt using salt, results in a 60 char output 
    $crypt_pass = crypt ($password . $salt2, $blowfish . $salt); 

    //insert crypt pass along with salt2 into database. 
    $sql = "insert into database...."; 

    return true; 
    } 
} 


function get_salt($length) { 
$options = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./'; 

$salt = ''; 

for($i = 0; $i <= $length; $i ++) { 
    $options = str_shuffle ($options); 
    $salt .= $options [rand (0, 63)]; 
} 
return $salt; 
} 

function verify_password($input_password) 
{ 
if($input_password) 
{ 
    //get stored crypt pass,and salt2 from the database 
    $stored_password = 'somethingfromdatabase'; 
    $stored_salt2 = 'somethingelsefromdatabase'; 

    //compare the crypt of input+stored_salt2 to the stored crypt password 
    if (crypt($input_password . $stored_salt2, $stored_password) == $stored_password) { 
     //authenticated 
     return true; 
    } 
    else return false; 
} 
else return false; 
} 
+0

'रैंड' के बजाय 'mt_rand' का उपयोग करना आपकी स्क्रिप्ट – Sliq

उत्तर

15

आपको वास्तव में PHPASS पर एक नज़र रखना चाहिए: http://www.openwall.com/phpass/ यह क्रिप्ट() का उपयोग करके एक पासवर्ड हैशिंग फ्रेमवर्क है जिसका उपयोग वर्डप्रेस और पीएचबीबी जैसी परियोजनाओं में किया जाता है।

वहाँ भी पासवर्ड हैशिंग के बारे में इस वेबसाइट पर एक उत्कृष्ट लेख, नमक मिलाना और तहखाने() का उपयोग कर खींच है: http://www.openwall.com/articles/PHP-Users-Passwords

अद्यतन: इस समय वहाँ PHPass लाइब्रेरी के लिए एक वैकल्पिक है। PHP के अगले संस्करण में हैंशिंग और पासवर्ड सत्यापित करने के लिए विशेष कार्य हैं (bcrypt का उपयोग करके): http://www.php.net/manual/en/ref.password.php। एक संगतता लाइब्रेरी है जो PHP 5.3.7+: https://github.com/ircmaxell/password_compat

+1

मैं देख सकता हूं कि बॉक्सवर्क के बाहर के लिए यह ढांचा कैसे सहायक हो सकता है, लेकिन मुझे अपने कोड और कोड फ़ेस कोड के बीच बहुत अलग दिखाई नहीं देता है। – Brian

+1

और: PHPass एक गड़बड़ है। एक विशाल गड़बड़ यह बहुत गन्दा है कि मैं इस पर भरोसा नहीं करता। – Sliq

+0

@Panique क्या आप समझाएंगे? –

3

इंद्रधनुष तालिका का विचार यह है कि एक हमलावर घर पर सभी संभावित पासवर्ड और उनके हैंश के साथ एक टेबल बना सकता है।

उदा।

PASSWORD HASH 
iloveSO gjroewjgo 
password knbnogjwm 
secret gjroehghe 
jbieber rewgroewj 

आदि

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

नमक का उपयोग करके, पासवर्ड के साथ इसे संग्रहीत करते समय भी, आप इसे अधिक कठिन बनाते हैं। एक शब्दकोष में हर शब्द को हश करने के बजाय, हमलावर को अब प्रत्येक शब्द प्रत्येक नमक के साथ हैश करना होगा। लंबे समय तक नमक के साथ, यह इन सभी हैशों की गणना करने के लिए इसे असुरक्षित बनाने के लिए पर्याप्त संयोजन प्रदान करता है।

तो नमक एक अतिरिक्त पासवर्ड नहीं है, जिसे केवल एप्लिकेशन के लिए जाना जाता है, यह हैश फ़ंक्शन को बदलने के लिए है ताकि यह गैर-मानक हो।

+0

का थोड़ा सुधार होगा, वह नमक का उपयोग कर रहा है, लेकिन यह अज्ञात लंबाई है। एक बड़े पैमाने पर नमक मूल्य के साथ इंद्रधनुष तालिका अक्षम हो जाएगी। उदाहरण के लिए 256^256, या 256 बाइट्स का बेस 256 नमक इतना बड़ा है कि हमारे पास केवल एक ही वर्ण के पासवर्ड को क्रैक करने के लिए आवश्यक बाइट्स की संख्या के लिए एक शब्द नहीं है। – rook

2

के लिए इन कार्यों को लागू करती है यह क्रिप्ट() का दुरुपयोग है क्योंकि आप एक बहिष्कृत आदिम का उपयोग कर रहे हैं। ब्लोफिश बहुत पुराना है, दोहराव प्रतिस्थापन है और यहां तक ​​कि पुराना है क्योंकि तीन फिश लगभग अंतिम रूप दिया गया है। आपको sha2 परिवार, sha256 या sha512 के सदस्य का उपयोग करना चाहिए, दोनों अच्छे विकल्प हैं। crypt() sha256 या sha512 के साथ प्रयोग किया जा सकता है, आपको क्रमशः CRYPT_SHA256 CRYPT_SHA512 पैरामीटर का उपयोग करना चाहिए।

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

+0

ब्लोफिश केवल अल्फान्यूमेरिक वर्ण ले सकता है, इसलिए शायद मुझे CRYPT_SHA512 का उपयोग करना चाहिए। – Brian

+0

@ ब्रायन पेरिन तो क्रिप्ट() के साथ कुछ अजीब है क्योंकि ब्लॉक सिफर का उपयोग फ़ाइलों और ट्रैफिक को हर समय एन्क्रिप्ट करने के लिए किया जाता है। – rook

+2

'क्रिप्ट()' द्वारा उपयोग किया जाने वाला ब्लॉफिश बिल्कुल पुराने के ब्लोफिश ब्लॉक साइफर जैसा नहीं है - यह एक संस्करण एल्गोरिदम है जो विशेष रूप से पासवर्ड हैशिंग/कुंजी व्युत्पन्न के लिए बनाया गया है। – caf

11

crypt() का उपयोग ठीक है। crypt($input, $stored) == $stored जिस तरह से इसे इस्तेमाल करने के लिए डिज़ाइन किया गया है।

आपका get_salt() फ़ंक्शन बहुत अच्छा नहीं है, क्योंकि यह अक्सर-खराब rand() फ़ंक्शन का उपयोग कर रहा है। आपको इसके बजाय openssl_random_pseudo_bytes() जैसे मजबूत यादृच्छिक फ़ंक्शन का उपयोग करने पर विचार करना चाहिए।

0

नमक के साथ SHA-512 (यदि उपलब्ध हो) का उपयोग करें जिसमें समय() और openssl_random_pseudo_bytes() शामिल है। क्रिप्ट समेकित/कुशल है क्योंकि यह हैश स्ट्रिंग के साथ डाले गए नमक को लौटाता है।

संबंधित मुद्दे