2013-02-05 16 views
15

मैं PHP में हैश पासवर्ड के लिए crypt() का उपयोग कर रहा हूं, और पासवर्ड जांच करते समय परिणामी हैश की समानता का परीक्षण करने का सबसे सुरक्षित तरीका काम करने की कोशिश कर रहा हूं ।strcmp बनाम == बनाम === PHP में हैश समानता

तीन विकल्प है कि मैं देख सकता हूँ रहे हैं: - डबल बराबर

function checkPassword($hash, $password) 
{ 
    return crypt($password, $hash) == $hash; 
} 

विकल्प 2 -

विकल्प 1 ट्रिपल बराबर

function checkPassword($hash, $password) 
{ 
    return crypt($password, $hash) === $hash; 
} 

विकल्प 3 - strcmp()

function checkPassword($hash, $password) 
{ 
    return strcmp(crypt($password, $hash), $hash) === 0; 
} 

मेरा अंतर्ज्ञान मुझे बताता है कि विकल्प 1 टाइपिंग जांच की कमी के कारण एक बुरा विचार है, और विकल्प 2 या 3 बेहतर होने की संभावना है। हालांकि, अगर कोई विशिष्ट मामला है तो === या strcmp विफल होने पर मैं काम नहीं कर सकता। इस उद्देश्य के लिए सबसे सुरक्षित कौन सा है?

+1

इसे पढ़ें: http://raz0r.name/vulnerabilities/simple-machines-forum/ – user956584

+0

@Userpassword दिलचस्प बग! मुझे आश्चर्य है कि कैसे PHP संख्याओं के रूप में डालने पर '$ 2a $ 10 $ ... $ 'जैसे तारों को संभालता है ... – Polynomial

+0

यदि आप केवल हैश की तुलना करना चाहते हैं, तो बस' === 'का उपयोग करें। यदि आप वास्तव में सुरक्षा और संभावित समय के हमलों (यहां तक ​​कि नेटवर्क जिटर के बावजूद) की परवाह करते हैं, तो आपको [इस] (https://github.com/delight-im/Faceless/issues/4) या [यह] (https://github.com/delight-im/Faceless/pull/5) चर्चा या 'हैश_equals()' फ़ंक्शन (PHP 5.6+) का उपयोग करें। – caw

उत्तर

19

जब सुरक्षा की बात आती है तो मैं === ऑपरेटर का उपयोग करना पसंद करता हूं। === सुनिश्चित करता है कि दो ऑपरेंड बिल्कुल समान हैं, कुछ सफलताओं तक पहुंचने के लिए तुलना में "सहायता" करने के लिए कुछ कास्टिंग को समायोजित करने की कोशिश किए बिना - क्योंकि यह एक ढीली टाइप की गई भाषा, जैसे कि PHP की तरह विकसित करने में मदद कर सकता है।

बेशक, ऑपरेंड में से एक को भरोसा किया जाना है। डेटाबेस से एक हैश भरोसेमंद है, जबकि उपयोगकर्ता इनपुट नहीं है।

कोई हमेशा थोड़ी देर के लिए यहां जा सकता है, निष्कर्ष पर आ रहा है कि किसी विशिष्ट मामले में == का उपयोग करने का कोई जोखिम नहीं है। शायद। लेकिन उदाहरण के लिए

"0afd9f7b678fdefca" == 0 is true 
    "aafd9f7b678fdefca" == 0 is also true 

पीएचपी एक संख्या में "हैश" कन्वर्ट करने के लिए कोशिश करता है जो 0. देता है जबकि यह संभव नहीं दिखता crypt रिटर्न 0 है (शायद atoi का प्रयोग करके), मैं ऐसे मामलों में जहां अधिकतम करने के लिए पसंद करते हैं === का उपयोग करके पासवर्ड == का उपयोग करके नहीं सोचने वाले दुर्लभ मामले की अनुमति देने से मेल नहीं खाते हैं (और एक समर्थन कॉल का जवाब देते हैं)।

strcmp के लिए, फ़ंक्शन <0 या >0 अलग-अलग होता है, और 0 बराबर होता है। लेकिन

strcmp("3", 0003) returns 0 
    strcmp("0003", 0003) returns -3 

जो बाद में आश्चर्यजनक नहीं हैं।एक शाब्दिक 0003 वास्तव में एक पूर्णांक है, 3 और strcmp एक स्ट्रिंग की अपेक्षा करता है, 3 को "3" में परिवर्तित कर दिया जाएगा। लेकिन इससे पता चलता है कि इस मामले में कुछ रूपांतरण हो सकता है, क्योंकि strcmp एक फ़ंक्शन है, जबकि === भाषा का हिस्सा है।

तो उस मामले में मेरी प्राथमिकता === पर जाती है (जो कि == से भी तेज है)।

+0

बदल सकती हैं I यह सबसे समझदार उत्तर है I 'देखा है। मैं मानता हूं कि "कास्ट सहायक" के साथ मुद्दों से बचने के लिए दोनों प्रकार और मूल्य महत्वपूर्ण हैं। – Polynomial

+0

ध्यान दें कि [हैश_equals() का उपयोग किया जाना चाहिए] (http://stackoverflow.com/a/27066499/978756) जब 'password_hash' जैसे मजबूत फ़ंक्शन के साथ उत्पादित हैश मानों का परीक्षण करते हैं। – Polynomial

-3

मुझे लगता है कि == का उपयोग आपके मामले में पर्याप्त होगा।

== प्रकार की परवाह किए बिना समानता के लिए जांच करता है, जबकि === समानता के साथ-साथ प्रकार के लिए जांच करता है।

1 == "1" = सच

1 === "1" = झूठी

जब से हम प्रकार के साथ नहीं भी चिंतित हैं, मैं इसे सरल रखने के लिए और == साथ जाना चाहते हैं।

+1

मुझे '==' और '===' के बीच अंतरों के बारे में पता है, लेकिन मैं ' मैं एक विशिष्ट सुरक्षा-संवेदनशील केस है जो मुझे याद आ रही है, तो काम करने की कोशिश कर रहा हूं। उदाहरण के लिए, 'strcmp' का उपयोग करने के लिए कोई कारण नहीं है * नहीं? – Polynomial

+0

चूंकि आप बाइनरी सुरक्षित तुलना से चिंतित नहीं हैं, इसलिए मैं strcmp का उपयोग नहीं करता। आप इस बात से चिंतित नहीं हैं कि तार कितने अलग हैं - आप इस बात से चिंतित हैं कि वे अर्थात् समान हैं या नहीं। –

+0

क्या होगा अगर किसी कारण से 'bcrypt' विफल हो जाता है? हो सकता है कि गैर-स्ट्रिंग रिटर्न मान को '$ हैश' के लिए स्ट्रिंग मान के बराबर माना जा सके, जहां वह चर मान्य हैश है? – Polynomial

0

यह गलत है, कृपया फ़ंक्शन की परिभाषा देखें। पीएचपी के अनुसार:

Returns < 0 if str1 is less than str2;

> 0 if str1 is greater than str2,

and 0 if they are equal

यह 0 से कम लौटाता है यदि str1 str2 से कम है। "कम से कम" वाक्यांश को नोट करें, यह केवल -1 नहीं लौटाता है, लेकिन कोई नकारात्मक मान। ऐसा तब होता है जब str1 str2 से अधिक होता है, लेकिन यह एक सकारात्मक, शून्य-शून्य मान देता है। यह एक सकारात्मक मूल्य देता है जो 1, या उसके बाद किसी भी संख्या हो सकता है।

strcmp() एक संख्या देता है जो कि पिछले चरित्र के साथ शुरू होने वाले दो तारों के बीच अंतर है।

यहाँ एक उदाहरण है:

$output = strcmp("red", "blue");

चर $ उत्पादन 16

6

के मान के साथ आप hash_equals() फ़ंक्शन है कि PHP में बनाया गया है का उपयोग करना चाहिए। अपना काम करने की कोई ज़रूरत नहीं होगी। हैश_equals() एक बूलियन मान वापस करेगा।

मेरी राय में आमतौर पर तारों की तुलना करने के लिए == या === का उपयोग करने का अच्छा विचार नहीं है, केवल स्ट्रिंग को छोड़ दें।

+1

यह अब 'password_hash' द्वारा उत्पन्न मानों के लिए सही उत्तर है, लेकिन पूछने के समय मुख्यधारा के PHP में' हैश_equals' मौजूद नहीं था, और यह फ्लैट हैश पर लागू नहीं होता है (जिसे किसी भी तरह से उपयोग नहीं किया जाना चाहिए, कभी-कभी विरासत के लिए आवश्यक होते हैं) – Polynomial

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