ASP.NET पहचान का डिफ़ॉल्ट पासवर्ड हैशर - यह कैसे काम करता है और क्या यह सुरक्षित है?


162

मैं सोच रहा हूँ कि पासवर्ड हैशर जो कि MVC 5 और ASP.NET आइडेंटिटी फ्रेमवर्क के साथ आता है , में कार्यान्वित किया गया डिफ़ॉल्ट रूप से विकर करने के लिए पर्याप्त सुरक्षित है? और यदि हां, तो अगर आप मुझे समझा सकते हैं कि यह कैसे काम करता है?

IPasswordHasher इंटरफ़ेस इस तरह दिखता है:

public interface IPasswordHasher
{
    string HashPassword(string password);
    PasswordVerificationResult VerifyHashedPassword(string hashedPassword, 
                                                       string providedPassword);
}

जैसा कि आप देख सकते हैं, यह नमक नहीं लेता है, लेकिन यह इस धागे में वर्णित है: " Asp.net आइडेंटिटी पासवर्ड हैशिंग " कि यह पर्दे के पीछे नमक को संक्रमित करता है। तो मैं सोच रहा हूँ कि यह कैसे करता है? और यह नमक कहाँ से आता है?

मेरी चिंता यह है कि नमक स्थिर है, यह काफी असुरक्षित है।


मुझे नहीं लगता कि यह सीधे आपके प्रश्न का उत्तर देता है, लेकिन ब्रॉक एलेन ने आपकी कुछ चिंताओं के बारे में यहां लिखा है => brockallen.com/2013/10/20/… और एक खुला स्रोत उपयोगकर्ता पहचान प्रबंधन और प्रमाणीकरण पुस्तकालय भी लिखा है जिसमें विभिन्न हैं बॉयलर-प्लेट की विशेषताएं जैसे पासवर्ड रीसेट, हैशिंग आदि आदि। github.com/brockallen/BrockAllen.MembershipReboot
Shiva

@ शिव धन्यवाद, मैं पृष्ठ पर पुस्तकालय और वीडियो को देखूंगा। लेकिन मुझे बाहरी लाइब्रेरी से नहीं जूझना होगा। नहीं तो मैं इससे बच सकता हूं।
एंड्रे स्नेड कोक

2
FYI करें: सुरक्षा के लिए समतुल्य समान। तो यद्यपि आपको अक्सर यहाँ एक अच्छा / सही उत्तर मिलेगा। विशेषज्ञ Security.stackexchange.com पर हैं, विशेष रूप से टिप्पणी "यह सुरक्षित है" मैंने एक समान प्रकार का प्रश्न पूछा और उत्तर की गहराई और गुणवत्ता अद्भुत थी।
तत्कालीन दादाजी

@philsoady धन्यवाद, जो समझ में आता है, Im पहले से ही कुछ अन्य "उप-मंचों" पर है, अगर मुझे कोई जवाब नहीं मिला, तो मैं उपयोग कर सकता हूं, मैं आगे बढ़ूंगा securiry.stackexchange.com। और टिप के लिए धन्यवाद!
एंड्रे स्नेड कोक

जवाबों:


227

यहां बताया गया है कि डिफ़ॉल्ट कार्यान्वयन ( ASP.NET फ्रेमवर्क या ASP.NET कोर ) कैसे काम करता है। यह हैश का उत्पादन करने के लिए यादृच्छिक नमक के साथ एक कुंजी व्युत्पत्ति कार्य का उपयोग करता है । नमक को केडीएफ के उत्पादन के हिस्से के रूप में शामिल किया गया है। इस प्रकार, हर बार जब आप एक ही पासवर्ड "हैश" करेंगे तो आपको अलग-अलग हैश मिलेंगे। हैश को सत्यापित करने के लिए आउटपुट को वापस नमक और बाकी हिस्सों में विभाजित किया जाता है, और केडीएफ निर्दिष्ट नमक के साथ पासवर्ड पर फिर से चलाया जाता है। यदि परिणाम प्रारंभिक आउटपुट के शेष से मेल खाता है, तो हैश सत्यापित किया जाता है।

हैशिंग:

public static string HashPassword(string password)
{
    byte[] salt;
    byte[] buffer2;
    if (password == null)
    {
        throw new ArgumentNullException("password");
    }
    using (Rfc2898DeriveBytes bytes = new Rfc2898DeriveBytes(password, 0x10, 0x3e8))
    {
        salt = bytes.Salt;
        buffer2 = bytes.GetBytes(0x20);
    }
    byte[] dst = new byte[0x31];
    Buffer.BlockCopy(salt, 0, dst, 1, 0x10);
    Buffer.BlockCopy(buffer2, 0, dst, 0x11, 0x20);
    return Convert.ToBase64String(dst);
}

सत्यापित किया जा रहा:

public static bool VerifyHashedPassword(string hashedPassword, string password)
{
    byte[] buffer4;
    if (hashedPassword == null)
    {
        return false;
    }
    if (password == null)
    {
        throw new ArgumentNullException("password");
    }
    byte[] src = Convert.FromBase64String(hashedPassword);
    if ((src.Length != 0x31) || (src[0] != 0))
    {
        return false;
    }
    byte[] dst = new byte[0x10];
    Buffer.BlockCopy(src, 1, dst, 0, 0x10);
    byte[] buffer3 = new byte[0x20];
    Buffer.BlockCopy(src, 0x11, buffer3, 0, 0x20);
    using (Rfc2898DeriveBytes bytes = new Rfc2898DeriveBytes(password, dst, 0x3e8))
    {
        buffer4 = bytes.GetBytes(0x20);
    }
    return ByteArraysEqual(buffer3, buffer4);
}

7
तो अगर मैं इसे सही ढंग से समझता हूं, तो HashPasswordफ़ंक्शन, एक ही स्ट्रिंग में दोनों लौटाता है? और जब आप इसे सत्यापित करते हैं, तो यह फिर से इसे फिर से विभाजित करता है, और आने वाले क्लीयरटेक्स्ट पासवर्ड को विभाजित करता है, विभाजन से नमक के साथ, और मूल हैश के साथ तुलना करता है?
आंद्रे स्नेद कोक

9
@ AndréSnedeHansen, बिल्कुल। और मैं भी आपको सुरक्षा पर या क्रिप्टोग्राफी एसई पर पूछने की सलाह देता हूं। "यह सुरक्षित है" भाग को उन संबंधित संदर्भों में बेहतर तरीके से संबोधित किया जा सकता है।
एंड्रयू साविनिख

1
जैसा कि ऊपर दिए गए उत्तर में वर्णित है @shajeerpuzhakkal।
एंड्रयू सविनाख

3
@AndrewSavinykh मुझे पता है, इसीलिए मैं पूछ रहा हूँ - क्या बात है? कोड को अधिक स्मार्ट बनाने के लिए? ;) मेरे लिए कारण दशमलव संख्याओं का उपयोग करके सामान गिनना एक बहुत अधिक सहज है (हमारे पास 10 उंगलियां हैं - कम से कम हम में से अधिकांश), इसलिए हेक्साडेसिमल का उपयोग करके कुछ संख्या घोषित करना एक अनावश्यक कोड अवरोधन जैसा लगता है।
एंड्रयू साइरुल

1
@ MihaiAlexandru-Ionut var hashedPassword = HashPassword(password); var result = VerifyHashedPassword(hashedPassword, password);- आपको क्या करना है। उसके बाद resultसच होता है।
एंड्रयू साविनिख

43

क्योंकि इन दिनों ASP.NET खुला स्रोत है, आप इसे GitHub: AspNet.Identity 3.0 और AspNet.Identity 2.0 पर पा सकते हैं ।

टिप्पणियों से:

/* =======================
 * HASHED PASSWORD FORMATS
 * =======================
 * 
 * Version 2:
 * PBKDF2 with HMAC-SHA1, 128-bit salt, 256-bit subkey, 1000 iterations.
 * (See also: SDL crypto guidelines v5.1, Part III)
 * Format: { 0x00, salt, subkey }
 *
 * Version 3:
 * PBKDF2 with HMAC-SHA256, 128-bit salt, 256-bit subkey, 10000 iterations.
 * Format: { 0x01, prf (UInt32), iter count (UInt32), salt length (UInt32), salt, subkey }
 * (All UInt32s are stored big-endian.)
 */

हां, और ध्यान देने योग्य है कि एल्गोरिथ्म ज़िपरी में कुछ जोड़ दिखाई दे रहे हैं।
एंड्रे स्नैड कोक

1
GitHub का स्रोत Asp.Net.Identity 3.0 है जो अभी भी प्रीलेरेज में है। 2.0 हैश फंक्शन का स्रोत कोडप्लेक्स
डेविड

1
नवीनतम कार्यान्वयन github.com/dotnet/aspnetcore/blob/master/src/Identity/… अब के तहत पाया जा सकता है । उन्होंने अन्य रिपॉजिटरी को संग्रहीत किया;)
फ्रांजहुबर 23

32

मैं स्वीकार किए गए उत्तर को समझता हूं, और इसे वोट दिया है, लेकिन मैंने सोचा कि मैं अपने आम आदमी के उत्तर को यहां दूंगा ...

एक हैश बनाना

  1. नमक Rfc2898DeriveBytes फ़ंक्शन का उपयोग करके बेतरतीब ढंग से उत्पन्न होता है जो एक हैश और एक नमक उत्पन्न करता है। Rfc2898DeriveBytes को इनपुट पासवर्ड, उत्पन्न करने के लिए नमक का आकार और प्रदर्शन करने के लिए हैशिंग पुनरावृत्तियों की संख्या है। https://msdn.microsoft.com/en-us/library/h83s4e12(v=vs.110).aspx
  2. नमक और हैश को फिर एक साथ मैश किया जाता है (पहले हैश के बाद नमक) और एक स्ट्रिंग के रूप में एन्कोडेड किया जाता है (इसलिए हैश में नमक को इनकोड किया जाता है)। यह एन्कोडेड हैश (जिसमें नमक और हैश होता है) तब उपयोगकर्ता के खिलाफ डेटाबेस में (आमतौर पर) संग्रहीत होता है।

हैश के खिलाफ पासवर्ड की जाँच करना

एक पासवर्ड की जांच करने के लिए जो एक उपयोगकर्ता इनपुट करता है।

  1. नमक को संग्रहीत हैशेड पासवर्ड से निकाला जाता है।
  2. नमक का उपयोग Rfc2898DeriveBytes के अधिभार का उपयोग करने वाले उपयोगकर्ताओं के इनपुट पासवर्ड को हैश करने के लिए किया जाता है जो एक उत्पन्न करने के बजाय एक नमक लेता है। https://msdn.microsoft.com/en-us/library/yx129kfs(v=vs.110).aspx
  3. संग्रहीत हैश और परीक्षण हैश की तुलना तब की जाती है।

द हैश

कवर के तहत SHA1 हैश फ़ंक्शन ( https://en.wikipedia.org/wiki/SHA-1 ) का उपयोग करके हैश उत्पन्न किया जाता है । यह फ़ंक्शन 1000 बार कहा जाता है (डिफ़ॉल्ट पहचान कार्यान्वयन में)

यह सुरक्षित क्यों है?

  • यादृच्छिक लवण का मतलब है कि एक हमलावर पासवर्ड को आज़माने और तोड़ने के लिए हैश की पूर्व-निर्मित तालिका का उपयोग नहीं कर सकता है। उन्हें हर नमक के लिए एक हैश तालिका तैयार करनी होगी। (यहाँ यह मानते हुए कि हैकर ने आपके नमक से समझौता किया है)
  • यदि 2 पासवर्ड समान हैं, तो उनके पास अलग-अलग हैश होंगे। (मतलब हमलावर 'आम' पासवर्ड नहीं खोज सकते हैं)
  • शाब्दिक रूप से SHA1 को 1000 बार कॉल करने का मतलब है कि हमलावर को भी ऐसा करने की आवश्यकता है। यह विचार कि जब तक उनके पास एक सुपर कंप्यूटर पर समय नहीं होता, तब तक उनके पास हैश से पासवर्ड को हटाने के लिए पर्याप्त संसाधन नहीं होंगे। यह किसी दिए गए नमक के लिए हैश टेबल बनाने के लिए बड़े पैमाने पर धीमा होगा।

आपके व्याख्या के लिये धन्यवाद। "क्रिएशन हैश 2" में आप उल्लेख करते हैं कि नमक और हैश को एक साथ मैश किया जाता है, क्या आप जानते हैं कि यह एस्पेन्चुअर्स टेबल में पासवर्डहैश में संग्रहीत है या नहीं। क्या मेरे लिए नमक कहीं भी संग्रहीत है?
यूनिकॉर्न 2

1
@ यूनिकॉर्न 2 यदि आप एंड्रयू सविनाख के उत्तर पर एक नज़र डालते हैं ... हैशिंग के बारे में अनुभाग में ऐसा लगता है कि नमक बाइट सरणी के पहले 16 बाइट्स में संग्रहीत है जो बेस 64 एनकोडेड है और डेटाबेस को लिखा गया है। आप इस बेस 64 एनकोडेड स्ट्रिंग को पासवर्डश टेबल में देख पाएंगे। बेस 64 स्ट्रिंग के बारे में आप बस इतना ही कह सकते हैं कि इसमें से पहला तीसरा हिस्सा नमक है। सार्थक नमक
पासवर्डहैश

@Nattrass, हैश और सॉल्ट के बारे में मेरी समझ अशिष्ट है, लेकिन अगर हैश पासवर्ड से नमक आसानी से निकाला जाता है, तो पहली बार में नमकीन खाने की क्या बात है। मुझे लगा कि नमक हैशिंग एल्गोरिथ्म के लिए एक अतिरिक्त इनपुट होना चाहिए जो आसानी से अनुमान नहीं लगाया जा सकता है।
NSouth

1
@NSouth अद्वितीय नमक किसी दिए गए पासवर्ड के लिए हैश को अद्वितीय बनाता है। तो दो समान पासवर्ड के अलग-अलग हैश होंगे। अपने हैश और नमक के उपयोग के बाद भी हमलावर को आपका पासवर्ड याद नहीं रहता है। हैश प्रतिवर्ती नहीं है। उन्हें अभी भी हर संभव पासवर्ड के माध्यम से वहां बल की आवश्यकता होगी। अनूठे नमक का मतलब है कि हैकर विशिष्ट हैश पर एक आवृत्ति विश्लेषण करके एक आम पासवर्ड का अनुमान नहीं लगा सकता है यदि वे आपकी संपूर्ण उपयोगकर्ता तालिका को पकड़ने में कामयाब रहे हैं।
नटरास

8

मेरे जैसे उन लोगों के लिए जो इस के लिए नए हैं, यहाँ कास्ट के साथ कोड है और बाइट [] की तुलना करने का एक वास्तविक तरीका है। मुझे स्टैकओवरफ़्लो से यह सभी कोड मिला है, लेकिन परिभाषित कॉन्स्टेंस इसलिए मूल्यों को बदला जा सकता है और यह भी

// 24 = 192 bits
    private const int SaltByteSize = 24;
    private const int HashByteSize = 24;
    private const int HasingIterationsCount = 10101;


    public static string HashPassword(string password)
    {
        // http://stackoverflow.com/questions/19957176/asp-net-identity-password-hashing

        byte[] salt;
        byte[] buffer2;
        if (password == null)
        {
            throw new ArgumentNullException("password");
        }
        using (Rfc2898DeriveBytes bytes = new Rfc2898DeriveBytes(password, SaltByteSize, HasingIterationsCount))
        {
            salt = bytes.Salt;
            buffer2 = bytes.GetBytes(HashByteSize);
        }
        byte[] dst = new byte[(SaltByteSize + HashByteSize) + 1];
        Buffer.BlockCopy(salt, 0, dst, 1, SaltByteSize);
        Buffer.BlockCopy(buffer2, 0, dst, SaltByteSize + 1, HashByteSize);
        return Convert.ToBase64String(dst);
    }

    public static bool VerifyHashedPassword(string hashedPassword, string password)
    {
        byte[] _passwordHashBytes;

        int _arrayLen = (SaltByteSize + HashByteSize) + 1;

        if (hashedPassword == null)
        {
            return false;
        }

        if (password == null)
        {
            throw new ArgumentNullException("password");
        }

        byte[] src = Convert.FromBase64String(hashedPassword);

        if ((src.Length != _arrayLen) || (src[0] != 0))
        {
            return false;
        }

        byte[] _currentSaltBytes = new byte[SaltByteSize];
        Buffer.BlockCopy(src, 1, _currentSaltBytes, 0, SaltByteSize);

        byte[] _currentHashBytes = new byte[HashByteSize];
        Buffer.BlockCopy(src, SaltByteSize + 1, _currentHashBytes, 0, HashByteSize);

        using (Rfc2898DeriveBytes bytes = new Rfc2898DeriveBytes(password, _currentSaltBytes, HasingIterationsCount))
        {
            _passwordHashBytes = bytes.GetBytes(SaltByteSize);
        }

        return AreHashesEqual(_currentHashBytes, _passwordHashBytes);

    }

    private static bool AreHashesEqual(byte[] firstHash, byte[] secondHash)
    {
        int _minHashLength = firstHash.Length <= secondHash.Length ? firstHash.Length : secondHash.Length;
        var xor = firstHash.Length ^ secondHash.Length;
        for (int i = 0; i < _minHashLength; i++)
            xor |= firstHash[i] ^ secondHash[i];
        return 0 == xor;
    }

आपके कस्टम ApplicationUserManager में, आपने पासवर्डहैसर प्रॉपर्टी को उस वर्ग के नाम पर सेट किया है जिसमें उपरोक्त कोड है।


इसके लिए .. _passwordHashBytes = bytes.GetBytes(SaltByteSize); मुझे लगता है कि आपका यह मतलब है _passwordHashBytes = bytes.GetBytes(HashByteSize);.. आपके परिदृश्य में कोई फर्क नहीं पड़ता क्योंकि दोनों एक ही आकार के हैं, लेकिन सामान्य रूप से ..
अक्षता
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.