मौजूदा उपयोगकर्ताओं के लिए एक नया पासवर्ड मजबूर किए बिना पासवर्ड हैशिंग अपडेट करना


32

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

इसमें शामिल उपयोगकर्ताओं के लिए एक 'सरलीकृत' डेटाबेस मॉडल मान लें:

  1. आईडी
  2. ईमेल
  3. पारण शब्द

ऐसी आवश्यकता को हल करने के लिए कोई कैसे घूमता है?


मेरे वर्तमान विचार हैं:

  • उपयुक्त कक्षा में एक नई हैशिंग विधि बनाएं
  • अतिरिक्त पासवर्ड फ़ील्ड को रखने के लिए डेटाबेस में उपयोगकर्ता तालिका को अपडेट करें
  • एक बार जब कोई उपयोगकर्ता पुराने पासवर्ड हैश का उपयोग करने में सफलतापूर्वक लॉग इन करता है, तो अपडेटेड हैश के साथ दूसरा पासवर्ड फ़ील्ड भरें

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

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

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


4
आप एक सेट और एक अनसेट माध्यमिक हैश के बीच अंतर क्यों नहीं कर पाएंगे? बस डेटाबेस कॉलम को अशक्त बनाने के लिए और अशक्त के लिए जाँच करें।
काइलिन फोथ

6
नए हैश के लिए एक फ़ील्ड के बजाय अपने नए कॉलम के रूप में हैश-प्रकार के साथ जाएं। जब आप हैश अपडेट करते हैं, तो टाइप फ़ील्ड बदलें। इस तरह, जब यह भविष्य में फिर से होता है, तो आप पहले से ही सौदा करने की स्थिति में होंगे, और आपके पास एक पुराने (संभवतः कम सुरक्षित) हैश पर रखने का कोई मौका नहीं है।
माइकल कोहेन

1
मुझे लगता है कि तुम सही रास्ते पर हो। अब से 6 महीने या एक साल बाद, आप किसी भी शेष उपयोगकर्ता को अपना पासवर्ड बदलने के लिए बाध्य कर सकते हैं। एक साल बाद या जो भी हो, आप पुराने क्षेत्र से छुटकारा पा सकते हैं।
ग्लेनपेटर्सन

3
सिर्फ पुराने हैश क्यों नहीं?
सियुआन रेन

क्योंकि आप चाहते हैं कि पासवर्ड हैशेड हो (पुराना हैश नहीं) ताकि इसे अनहैश किया जाए (यानी यूजर द्वारा दिए गए हैशेड से इसकी तुलना करें) आपको देता है ... पासवर्ड - दूसरा मूल्य नहीं है जो तब 'dehashed' होना चाहिए पुरानी पद्धति के तहत। संभव है, लेकिन क्लीनर नहीं।
माइकल डुरंट

जवाबों:


25

मैं एक नया क्षेत्र, "hash_method" जोड़ने का सुझाव दूंगा, शायद 1 के साथ पुरानी पद्धति को और 2 को नई विधि को सूचित करने के लिए।

यथोचित रूप से, यदि आप इस प्रकार की परवाह करते हैं और आपका आवेदन अपेक्षाकृत लंबे समय तक रहता है (जो कि यह स्पष्ट रूप से पहले से ही है), तो यह संभवत: फिर से होने वाला है क्योंकि क्रिप्टोग्राफी और सूचना सुरक्षा एक ऐसा विकसित नहीं है, बल्कि अप्रत्याशित क्षेत्र है। एक समय था जब एमडी 5 के माध्यम से एक सरल रन मानक था, अगर हैशिंग का बिल्कुल भी उपयोग किया जाता था! तब कोई सोच सकता है कि उन्हें SHA1 का उपयोग करना चाहिए, और अब नमकीन बनाना है, वैश्विक नमक + व्यक्तिगत यादृच्छिक नमक, SHA3, क्रिप्टो-तैयार यादृच्छिक संख्या पीढ़ी के विभिन्न तरीकों ... यह सिर्फ 'स्टॉप' करने के लिए नहीं जा रहा है, इसलिए आप इस प्रकार हो सकते हैं अच्छी तरह से एक एक्स्टेंसिबल, दोहराने योग्य तरीके से इसे ठीक करें।

तो, चलो अब तुम कुछ की तरह है (सरलता के लिए छद्म जावास्क्रिप्ट में, मुझे आशा है):

var user = getUserByID(id);
var tryPassword = hashPassword(getInputPassword());


if (user.getPasswordHash() == tryPassword)
{
    // Authenticated!
}

function hashPassword(clearPassword)
{
    // TODO: Learn what "hash" means
    return clearPassword + "H@$I-I";
}

अब एहसास हुआ कि एक बेहतर तरीका है, आपको बस एक छोटी सी रिफैक्टिंग देने की जरूरत है:

var user = getUserByID(id);
var tryPassword = hashPassword(getInputPassword(), user.getHashingMethod());

if (user.getPasswordHash() == tryPassword)
{
    // Authenticated!
}

function hashPassword(clearPassword, hashMethod)
{
    // Note: Hash doesn't mean what we thought it did. Oops...

    var hash;
    if (hashMethod == 1)
    {
        hash = clearPassword + "H@$I-I";
    }
    else if (hashMethod == 2)
    {
        // Totally gonna get it right this time.
        hash = SuperMethodTheNSASaidWasAwesome(clearPassword);
    }
    return hash;
}

इस जवाब के निर्माण में किसी भी गुप्त एजेंट या प्रोग्रामर को नुकसान नहीं पहुंचाया गया।


+1 यह काफी समझदार सार लगता है, धन्यवाद। हालाँकि मैं इसे लागू करने पर हैश और हैशमेथोड फ़ील्ड को एक अलग टेबल पर ले जा सकता हूं।
विलेम

1
इस तकनीक के साथ समस्या यह है कि खातों के लिए लॉग इन नहीं है, आप हैश अद्यतन नहीं कर सकते। मेरे अनुभव में अधिकांश उपयोगकर्ता वर्षों तक लॉग इन नहीं करेंगे (यदि आप निष्क्रिय उपयोगकर्ताओं को हटाते हैं)। आपका अमूर्त वास्तव में या तो काम नहीं करता है, क्योंकि यह लवण के लिए खाता नहीं है। मानक अमूर्त में दो कार्य होते हैं, एक सत्यापन के लिए और एक निर्माण के लिए।
कोडइन्चोस 12

पासवर्ड हैशिंग पिछले 15 वर्षों में मुश्किल से विकसित हुआ है। Bcrypt 1999 में प्रकाशित किया गया है और अभी भी अनुशंसित हैश की है। तब से केवल एक महत्वपूर्ण सुधार हुआ है: क्रमिक रूप से मेमोरी हार्ड हैश, स्क्रीप्ट द्वारा अग्रणी।
कोडइन्चोस

इससे पुरानी हैश कमजोर हो जाती है (जैसे अगर कोई डीबी चुराता है)। नई अधिक सुरक्षित विधि के साथ प्रत्येक पुराने हैश को newHash(oldHash, salt)newHash(password, salt)
मारना

42

यदि आप सभी उपयोगकर्ताओं के लिए नई हैशिंग योजना को जल्दी से जल्दी शुरू करने के बारे में पर्याप्त देखभाल करते हैं (जैसे कि क्योंकि पुराना वास्तव में असुरक्षित है), तो वास्तव में हर पासवर्ड के तात्कालिक "प्रवास" का एक तरीका है ।

विचार मूल रूप से हैश करने के लिए है । उपयोगकर्ताओं के लिए प्रतीक्षा करने के बजाय p, अगले लॉगिन पर अपना मौजूदा पासवर्ड ( ) प्रदान करते हैं , आप तुरंत पुराने हैशिंग ( H2) द्वारा निर्मित मौजूदा हैश पर नए हैशिंग एल्गोरिथ्म ( ) का उपयोग करते हैं H1:

hash = H2(hash)  # where hash was previously equal to H1(p) 

उस रूपांतरण को करने के बाद, आप अभी भी पासवर्ड सत्यापन करने में पूरी तरह सक्षम हैं; जब भी उपयोगकर्ता पासवर्ड से लॉग इन करने का प्रयास करता है H2(H1(p')), तो आपको पहले की बजाय गणना करने की आवश्यकता होती है ।H1(p')p'

सिद्धांत रूप में, इस तकनीक कई माइग्रेशन (करने के लिए लागू किया जा सकता H3, H4, आदि)। व्यवहार में, आप प्रदर्शन और पठनीयता दोनों कारणों से पुराने हैश फ़ंक्शन से छुटकारा पाना चाहेंगे। सौभाग्य से, यह काफी आसान है: अगले सफल लॉगिन पर, बस उपयोगकर्ता के पासवर्ड के नए हैश की गणना करें और इसके साथ मौजूदा हैश-ए-हैश को बदलें:

hash = H2(p)

आपको यह याद रखने के लिए अतिरिक्त कॉलम की भी आवश्यकता होगी कि आप किस हैश का भंडारण कर रहे हैं: पासवर्ड या पुराने हैश में से एक। डेटाबेस रिसाव की दुर्भाग्यपूर्ण घटना में, इस स्तंभ को पटाखा का काम आसान नहीं बनाना चाहिए; इसके मूल्य की परवाह किए बिना, हमलावर को अभी भी H2पुराने की बजाय सुरक्षित एल्गोरिदम को उलटना होगा H1


3
एक विशाल +1: H2 (H1 (p)) आमतौर पर H2 (p) का उपयोग करते हुए सीधे सुरक्षित होता है, भले ही H1 भयानक हो, क्योंकि (1) नमक और स्ट्रेचिंग में H2 का ध्यान रखा जाता है, और (2) समस्याएँ MD5 जैसे "टूटे हुए" हैश के साथ पासवर्ड हैशिंग को प्रभावित नहीं करता है। संबंधित: crypto.stackexchange.com/questions/2945/...
orip

दिलचस्प है, मुझे लगा है कि पुराने हैश के बाद किसी तरह की सुरक्षा 'मुद्दा' बनेगी। लगता है कि मुझसे गलती हुई।
विलेम

4
यदि H1 वास्तव में भयानक है तो यह सुरक्षित नहीं होगा। इस संदर्भ में भयानक होने के नाते ज्यादातर इनपुट से बहुत अधिक एनट्रॉपी खोने के बारे में है। यहां तक ​​कि एमडी 4 और एमडी 5 भी इस संबंध में लगभग सही हैं, इसलिए यह दृष्टिकोण केवल कुछ होमब्रेव हैश या वास्तव में कम आउटपुट (80 बिट से नीचे) वाले हैश के लिए असुरक्षित है।
कोडइन्चोसोस

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

8

आपका समाधान (डेटाबेस में अतिरिक्त स्तंभ) पूरी तरह से स्वीकार्य है। इसके साथ एकमात्र मुद्दा वह है जिसका आपने पहले ही उल्लेख किया था: पुराने हैशिंग का उपयोग अभी भी उन उपयोगकर्ताओं के लिए किया जाता है जो परिवर्तन के बाद से प्रमाणित नहीं हुए हैं।

इस स्थिति से बचने के लिए, आप अपने सबसे सक्रिय उपयोगकर्ताओं को नए हैशिंग एल्गोरिथ्म में जाने के लिए इंतजार कर सकते हैं, फिर:

  1. उन उपयोगकर्ताओं के खाते निकालें, जिन्होंने बहुत अधिक समय तक प्रमाणित नहीं किया है। एक उपयोगकर्ता के खाते को हटाने में कुछ भी गलत नहीं है जो तीन साल के लिए वेबसाइट पर कभी नहीं आया।

  2. शेष उपयोगकर्ताओं के बीच एक ईमेल भेजें, जिन्होंने कुछ समय के लिए प्रमाणित नहीं किया है, यह बताते हुए कि वे कुछ नए में दिलचस्पी ले सकते हैं। यह उन खातों की संख्या को कम करने में मदद करेगा जो पुराने हैशिंग का उपयोग करते हैं।

    सावधान रहें: यदि आपके पास कोई स्पैम विकल्प नहीं है, जिसे उपयोगकर्ता आपकी वेबसाइट पर देख सकते हैं, तो उन उपयोगकर्ताओं को ईमेल न भेजें जिन्होंने इसकी जाँच की थी।

  3. अंत में, चरण 2 के कुछ सप्ताह बाद, उन उपयोगकर्ताओं के लिए पासवर्ड को नष्ट कर दें जो अभी भी पुरानी तकनीक का उपयोग कर रहे हैं। जब वे प्रमाणित करने का प्रयास करते हैं, तो वे देखेंगे कि उनका पासवर्ड अमान्य है; यदि वे अभी भी आपकी सेवा में रुचि रखते हैं, तो वे इसे रीसेट कर सकते हैं।


1

आपके पास शायद एक जोड़े हैश प्रकार से अधिक कभी नहीं होगा, इसलिए आप अपने डेटाबेस को विस्तारित किए बिना इसे हल कर सकते हैं।

यदि विधियों में अलग-अलग हैश लंबाई होती है, और प्रत्येक विधि की हैश लंबाई स्थिर होती है (कहते हैं, md5 से hmac-sha1 में संक्रमण), आप हैश लंबाई से विधि बता सकते हैं। यदि उनके पास समान लंबाई है, तो आप पहले नई विधि का उपयोग करके हैश की गणना कर सकते हैं, फिर पुरानी विधि यदि पहला परीक्षण विफल हो गया है। यदि आपके पास एक फ़ील्ड है (दिखाया नहीं गया है) बता रहा है कि उपयोगकर्ता को अंतिम बार अपडेट किया गया / बनाया गया था, तो आप इसे संकेतक के रूप में उपयोग कर सकते हैं कि किस विधि का उपयोग करना है।


1

मैंने ऐसा कुछ किया है और यह बताने का एक तरीका है कि क्या यह नया हैश है और इसे और भी सुरक्षित बना सकता है। यदि आप अपने हैश को अपडेट करने के लिए समय ले रहे हैं तो मैं आपके लिए और अधिक सुरक्षित है।

अपने DB तालिका में "नमक" और अच्छी तरह से एक नया कॉलम जोड़ें, इसका उपयोग प्रति उपयोगकर्ता यादृच्छिक उत्पन्न नमक के रूप में करें। (बहुत अधिक इंद्रधनुष तालिका हमलों को रोकता है)

इस तरह, अगर मेरा पासवर्ड "पास123" है और यादृच्छिक नमक 3333 है तो मेरा नया पासवर्ड "पास 1233333" का हैश होगा।

यदि उपयोगकर्ता के पास नमक है तो आप जानते हैं कि यह नया हैश है। यदि उपयोगकर्ता का नमक शून्य है, तो आप जानते हैं कि यह पुराना हैश है।


0

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

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


1
एक समझौता है कि मैं अतीत में किया है समय की अवधि के लिए पुराने पासवर्ड रखने के लिए, उन्हें rehashing के रूप में लोगों के लिए लॉग इन है, लेकिन उसके बाद समय बीत गया है आप तो किसी पर एक पासवर्ड रीसेट जो दौरान में लॉग इन नहीं किया मजबूर उस समय। इसलिए आपके पास एक ऐसी अवधि है जहां आपके पास अभी भी कम सुरक्षित पासवर्ड हैं, लेकिन यह समय सीमित है और आप नियमित रूप से लॉग इन करने वाले उपयोगकर्ताओं के लिए व्यवधान को कम करते हैं।
सीन बर्टन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.