c# एएसपी.नेट पहचान डिफ़ॉल्ट पासवर्ड हैशर, यह कैसे काम करता है और यह सुरक्षित है?




asp.net security (4)

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

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

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

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

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


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

hashing:

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);
}

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

// 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://.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 में, आप पासवर्ड हैशर प्रॉपर्टी को उस श्रेणी का नाम सेट करते हैं जिसमें उपरोक्त कोड होता है।


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

एक हैश बनाना

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

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

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

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

हैश

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

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

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

चूंकि इन दिनों एएसपी.नेट ओपन सोर्स है, तो आप इसे एस्पनेट के लिए गिटहब पर देख सकते हैं। इडेंटिटी 3.0 या एस्पनेट के लिए कोडप्लेक्स पर। इडेंटिटी 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.)
 */




asp.net-identity