हैश और नमक पासवर्ड C # में


178

मैं सिर्फ हैशिंग उपयोगकर्ता पासवार्ड पर डेविडहेडेन के लेखों में से एक के माध्यम से जा रहा था ।

वास्तव में मुझे वह प्राप्त नहीं हो सकता जो वह हासिल करने की कोशिश कर रहा है।

यहाँ उसका कोड है:

private static string CreateSalt(int size)
{
    //Generate a cryptographic random number.
    RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
    byte[] buff = new byte[size];
    rng.GetBytes(buff);

    // Return a Base64 string representation of the random number.
    return Convert.ToBase64String(buff);
}

private static string CreatePasswordHash(string pwd, string salt)
{
    string saltAndPwd = String.Concat(pwd, salt);
    string hashedPwd =
        FormsAuthentication.HashPasswordForStoringInConfigFile(
        saltAndPwd, "sha1");
    return hashedPwd;
}

क्या हैशिंग पासवर्ड के लिए कोई अन्य C # विधि है और इसमें नमक जोड़ा जा रहा है?


यहाँ एक पुस्तकालय है जो नमक एन्क्रिप्टिंग के
ओमू

6
नमक उत्पन्न करने के लिए पहली विधि में आकार के लिए आपको क्या करना चाहिए?
शेन लेब्लांक

6
लिंक टूट गया है।
ओसमैनरिफ़गन्स

@ShaneLeBlanc आपको कम से कम बिट्स के रूप में फ़ंक्शन आउटपुट होना चाहिए। SHA1क्रिप्टो-ग्रेड नहीं है, इसलिए आपको कम से कम उपयोग करना चाहिए SHA256, जो 256 बिट्स या 32 बाइट्स का आउटपुट देता है। लेकिन, 256 बिट्स आसानी से बेस 64 के लिए परिवर्तनीय नहीं हैं, क्योंकि प्रत्येक बेस 64 चर 6 बिट्स को एन्कोड करता है, और 256 को 6. पूरी तरह से विभाज्य नहीं है। इसलिए आपको 6 (बेस 64 के लिए) और 8 (एक बाइट के लिए बिट्स) के एक सामान्य हर की जरूरत है। 256 से अधिक बिट्स, जो 264 काटने या 33 बाइट्स है। TLDR: 33 का प्रयोग करें।
VSO

जवाबों:


248

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

मेरी किताब, बिगिनिंग एएसपी.नेट सिक्योरिटी , (ओह अंत में, किताब को पिंप करने का एक बहाना) मैं निम्नलिखित कार्य करता हूं

static byte[] GenerateSaltedHash(byte[] plainText, byte[] salt)
{
  HashAlgorithm algorithm = new SHA256Managed();

  byte[] plainTextWithSaltBytes = 
    new byte[plainText.Length + salt.Length];

  for (int i = 0; i < plainText.Length; i++)
  {
    plainTextWithSaltBytes[i] = plainText[i];
  }
  for (int i = 0; i < salt.Length; i++)
  {
    plainTextWithSaltBytes[plainText.Length + i] = salt[i];
  }

  return algorithm.ComputeHash(plainTextWithSaltBytes);            
}

नमक पीढ़ी सवाल में उदाहरण के रूप में है। आप पाठ का उपयोग करके बाइट सरणियों में परिवर्तित कर सकते हैं Encoding.UTF8.GetBytes(string)। यदि आपको एक हैश को उसके स्ट्रिंग प्रतिनिधित्व में परिवर्तित करना होगा जिसका आप उपयोग कर सकते हैं Convert.ToBase64Stringऔर Convert.FromBase64Stringइसे वापस बदल सकते हैं।

आपको ध्यान देना चाहिए कि आप बाइट सरणियों पर समानता ऑपरेटर का उपयोग नहीं कर सकते हैं, यह संदर्भों की जांच करता है और इसलिए आपको प्रत्येक बाइट की जाँच करने वाले दोनों सरणियों के माध्यम से लूप करना चाहिए।

public static bool CompareByteArrays(byte[] array1, byte[] array2)
{
  if (array1.Length != array2.Length)
  {
    return false;
  }

  for (int i = 0; i < array1.Length; i++)
  {
    if (array1[i] != array2[i])
    {
      return false;
    }
  }

  return true;
}

हमेशा प्रति पासवर्ड एक नए नमक का उपयोग करें। साल्ट्स को गुप्त नहीं रखना पड़ता है और इसे हैश के साथ ही स्टोर किया जा सकता है।


3
इस सलाह के लिए धन्यवाद - वास्तव में मुझे शुरू करने में मदद मिली। मैं इस लिंक < dijksterhuis.org/creating-salted-hash-values-in-c > पर भी आया था, जो मुझे अच्छी व्यावहारिक सलाह मिली थी और इस पोस्ट में जो कहा गया था उससे बहुत कुछ पता चलता है
एलेक्स पी।

18
तुलनात्मक के लिए निफ्टी LINQ स्टेटमेंट रिफ्लेक्टर return array1.Length == array2.Length && !array1.Where((t, i) => t != array2[i]).Any();
शिकारी

6
@Brettski तकनीकी रूप से, हाँ, लेकिन प्रत्येक उपयोगकर्ता के लिए एक अद्वितीय नमक होने से रेनबो टेबल्स (आमतौर पर हैशेड पासवर्ड को क्रैक करने के सबसे कुशल तरीके के रूप में स्वीकार किए जाते हैं) व्यावहारिक रूप से बेकार हो जाते हैं। यह एक त्वरित oveview है जो पासवर्डों को सुरक्षित रूप से संग्रहीत करने के लिए गहराई से नहीं बल्कि गहराई से अवलोकन करता है, और यह सब कैसे / कैसे काम करता है।
रेंजर

3
@ हंटर: आपको इसे लगातार समय बनाने के लिए एक .ToList () जोड़ना चाहिए। उदाहरण: वापसी array1.ength == array2.Length &&! array1.Where ((t, i) => t! = array2 [i])। ToList ()। Any () जैसे ही यह एक बाइट पाता है कि बराबर नहीं है, LINQ वापस आ जाएगा।
एलेक्स रूहिलार्ड

17
-1 तेज़ हैश-फ़ंक्शन का उपयोग करने के लिए। PBKDF2, bcrypt या scrypt जैसे धीमे निर्माण का उपयोग करें।
कोडइन्कॉउंस

48

ब्लर्डार्ट ने क्या कहा, लेकिन थोड़ा कम कोड के साथ। Linq का उपयोग करें या CopyToसरणियों को संक्षिप्त करने के लिए।

public static byte[] Hash(string value, byte[] salt)
{
    return Hash(Encoding.UTF8.GetBytes(value), salt);
}

public static byte[] Hash(byte[] value, byte[] salt)
{
    byte[] saltedValue = value.Concat(salt).ToArray();
    // Alternatively use CopyTo.
    //var saltedValue = new byte[value.Length + salt.Length];
    //value.CopyTo(saltedValue, 0);
    //salt.CopyTo(saltedValue, value.Length);

    return new SHA256Managed().ComputeHash(saltedValue);
}

Linq में आपके बाइट सरणियों की तुलना करने का एक आसान तरीका है।

public bool ConfirmPassword(string password)
{
    byte[] passwordHash = Hash(password, _passwordSalt);

    return _passwordHash.SequenceEqual(passwordHash);
}

हालांकि इनमें से किसी को भी लागू करने से पहले, इस पोस्ट को देखें । पासवर्ड हैशिंग के लिए आप धीमी हैश एल्गोरिथ्म चाह सकते हैं, तेज नहीं।

इसके अंत में वह Rfc2898DeriveBytesवर्ग है जो धीमा है (और इसे धीमा बनाया जा सकता है), और मूल प्रश्न के दूसरे भाग का उत्तर दे सकता है कि इसमें पासवर्ड और नमक ले सकते हैं और हैश लौटा सकते हैं। अधिक जानकारी के लिए यह प्रश्न देखें । नोट, स्टैक एक्सचेंजRfc2898DeriveBytes पासवर्ड हैशिंग (स्रोत कोड यहाँ ) के लिए उपयोग कर रहा है ।


6
@MushinNoShin SHA256 एक तेज़ हैश है। पासवर्ड हैशिंग को धीमी गति से चलने वाले हैश की आवश्यकता होती है, जैसे PBKDF2, bcrypt या scrypt। देखें कैसे सुरक्षित रूप से हैश पासवर्ड है? विवरण के लिए Security.se पर।
कोडइंचोज

32

मैं पढ़ रहा हूँ कि SHA256 जैसे हैशिंग फ़ंक्शंस वास्तव में पासवर्ड संग्रहीत करने के लिए उपयोग नहीं किए गए थे: https://patrickmn.com/security/storing-passwords-securely/#notpasswordhashes

इसके बजाय PBKDF2, bcrypt या scrypt जैसे अनुकूली प्रमुख व्युत्पन्न कार्य थे। यहाँ एक PBKDF2 आधारित एक है कि माइक्रोसॉफ्ट के लिए लिखा है PasswordHasher उनके Microsoft.AspNet.Identity पुस्तकालय में:

/* =======================
 * HASHED PASSWORD FORMATS
 * =======================
 * 
 * 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.)
 */

public string HashPassword(string password)
{
    var prf = KeyDerivationPrf.HMACSHA256;
    var rng = RandomNumberGenerator.Create();
    const int iterCount = 10000;
    const int saltSize = 128 / 8;
    const int numBytesRequested = 256 / 8;

    // Produce a version 3 (see comment above) text hash.
    var salt = new byte[saltSize];
    rng.GetBytes(salt);
    var subkey = KeyDerivation.Pbkdf2(password, salt, prf, iterCount, numBytesRequested);

    var outputBytes = new byte[13 + salt.Length + subkey.Length];
    outputBytes[0] = 0x01; // format marker
    WriteNetworkByteOrder(outputBytes, 1, (uint)prf);
    WriteNetworkByteOrder(outputBytes, 5, iterCount);
    WriteNetworkByteOrder(outputBytes, 9, saltSize);
    Buffer.BlockCopy(salt, 0, outputBytes, 13, salt.Length);
    Buffer.BlockCopy(subkey, 0, outputBytes, 13 + saltSize, subkey.Length);
    return Convert.ToBase64String(outputBytes);
}

public bool VerifyHashedPassword(string hashedPassword, string providedPassword)
{
    var decodedHashedPassword = Convert.FromBase64String(hashedPassword);

    // Wrong version
    if (decodedHashedPassword[0] != 0x01)
        return false;

    // Read header information
    var prf = (KeyDerivationPrf)ReadNetworkByteOrder(decodedHashedPassword, 1);
    var iterCount = (int)ReadNetworkByteOrder(decodedHashedPassword, 5);
    var saltLength = (int)ReadNetworkByteOrder(decodedHashedPassword, 9);

    // Read the salt: must be >= 128 bits
    if (saltLength < 128 / 8)
    {
        return false;
    }
    var salt = new byte[saltLength];
    Buffer.BlockCopy(decodedHashedPassword, 13, salt, 0, salt.Length);

    // Read the subkey (the rest of the payload): must be >= 128 bits
    var subkeyLength = decodedHashedPassword.Length - 13 - salt.Length;
    if (subkeyLength < 128 / 8)
    {
        return false;
    }
    var expectedSubkey = new byte[subkeyLength];
    Buffer.BlockCopy(decodedHashedPassword, 13 + salt.Length, expectedSubkey, 0, expectedSubkey.Length);

    // Hash the incoming password and verify it
    var actualSubkey = KeyDerivation.Pbkdf2(providedPassword, salt, prf, iterCount, subkeyLength);
    return actualSubkey.SequenceEqual(expectedSubkey);
}

private static void WriteNetworkByteOrder(byte[] buffer, int offset, uint value)
{
    buffer[offset + 0] = (byte)(value >> 24);
    buffer[offset + 1] = (byte)(value >> 16);
    buffer[offset + 2] = (byte)(value >> 8);
    buffer[offset + 3] = (byte)(value >> 0);
}

private static uint ReadNetworkByteOrder(byte[] buffer, int offset)
{
    return ((uint)(buffer[offset + 0]) << 24)
        | ((uint)(buffer[offset + 1]) << 16)
        | ((uint)(buffer[offset + 2]) << 8)
        | ((uint)(buffer[offset + 3]));
}

ध्यान दें कि इसके लिए Microsoft.AspNetCore.Cryptography.KeyDeritation nuget पैकेज की आवश्यकता है जिसमें .NET मानक 2.0 (.NET 4.6.1 या उच्चतर) की आवश्यकता होती है। .NET के पुराने संस्करणों के लिए Microsoft के System.Web.Helpers लाइब्रेरी से क्रिप्टो क्लास देखें ।

नवंबर 2015 को
अपडेट करें एक अलग Microsoft लाइब्रेरी से कार्यान्वयन का उपयोग करने के लिए अद्यतित उत्तर जो PBKDF2-HMAC-SHA1 के बजाय PBKDF2-HMAC-SHA256 हैशिंग का उपयोग करता है (नोट PBKDF2-HMAC-SHA1 अभी भी सुरक्षित है यदि iterCount पर्याप्त है)। आप स्रोत की जांच कर सकते हैं कि सरलीकृत कोड को कॉपी किया गया था क्योंकि यह वास्तव में पिछले उत्तर से लागू किए गए हैश को मान्य और अपग्रेड करने के लिए उपयोगी है, यदि आपको भविष्य में पुनरावृति बढ़ाने की आवश्यकता है।


1
ध्यान दें कि शायद PBKDF2IterCount को अधिक संख्या में बढ़ाने के लिए, अधिक के लिए सुरक्षा .stackexchange.com/q/3959 देखें ।
माइकल

2
1) PBKDF2SubkeyLength20 बाइट्स को कम करें । यही कारण है कि प्राकृतिक आकार f SHA1 है और इसे परे बढ़ाकर हमलावर को धीमा किए बिना रक्षक को धीमा कर देता है। 2) मैं पुनरावृत्ति गिनती बढ़ाने की सलाह देता हूं। मैं आपके प्रदर्शन बजट के आधार पर 10k से 100k तक की सलाह देता हूं। 3) एक निरंतर समय तुलना या तो चोट नहीं होगी, लेकिन बहुत व्यावहारिक प्रभाव नहीं है।
कोडइन्चोस

KeyDeritationPrf, KeyDeritation और BlockCopy अपरिभाषित हैं, उनकी कक्षाएं क्या हैं?
म्रबेंगी

@mrbengi आपने Microsoft.AspNet.Cryptography.KeyDeritation नौगेट पैकेज का उल्लेख किया है? यदि यह उपयुक्त नहीं है यहाँ एक संस्करण है कि nuget पैकेज की आवश्यकता नहीं है है। Buffer.BlockCopy यह सिस्टम का हिस्सा होना चाहिए।
माइकल

1
नगेट पैकेज अब Microsoft.AspNetCore.Cryptography.KeyDerivation है।
जेम्स ब्लेक

25

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

Sitepoint पर एक लेख से :

एक हैकर अभी भी वही कर सकता है जिसे डिक्शनरी अटैक कहा जाता है। दुर्भावनापूर्ण पार्टियाँ, उदाहरण के लिए, 100,000 पासवर्ड, जो वे जानती हैं कि लोग अक्सर उपयोग करते हैं (जैसे शहर के नाम, खेल टीम, आदि), उन्हें हैश कर सकते हैं, और फिर डेटाबेस में प्रत्येक पंक्ति के खिलाफ शब्दकोश में प्रत्येक प्रविष्टि की तुलना कर सकते हैं। तालिका। अगर हैकर्स को बिंगो मिल जाए तो! उनके पास आपका पासवर्ड है। हालांकि, इस समस्या को हल करने के लिए, हमें केवल हैश नमक की आवश्यकता है।

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

इस परिदृश्य में, न केवल एक हैकर को पासवर्ड का अनुमान लगाने की आवश्यकता होगी, बल्कि उन्हें नमक का भी अनुमान लगाना होगा। स्पष्ट पाठ में नमक जोड़ने से सुरक्षा में सुधार होता है: अब, यदि कोई हैकर एक शब्दकोश हमले की कोशिश करता है, तो उसे हर उपयोगकर्ता पंक्ति के नमक के साथ अपनी 100,000 प्रविष्टियाँ चाहिए। हालांकि यह अभी भी संभव है, सफलता की हैकिंग की संभावना मौलिक रूप से कम हो जाती है।

.NET में स्वचालित रूप से ऐसा करने की कोई विधि नहीं है, इसलिए आप ऊपर दिए गए समाधान के साथ जाएंगे।


साल्ट का उपयोग इंद्रधनुष की तालिकाओं जैसी चीजों से बचाव के लिए किया जाता है। शब्दकोश हमलों से बचाव के लिए एक कार्य कारक (जिसे कुंजी स्ट्रेचिंग के रूप में भी जाना जाता है) को किसी अच्छे केडीएफ की तरह आवश्यक है: en.wikipedia.org/wiki/Key_stretching
Erwan Legrand

11

मैंने एक वर्ग बनाया है जिसमें निम्नलिखित विधि है:

  1. नमक बनाएँ
  2. हैश इनपुट
  3. मान्य इनपुट

    public class CryptographyProcessor
    {
        public string CreateSalt(int size)
        {
            //Generate a cryptographic random number.
              RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
             byte[] buff = new byte[size];
             rng.GetBytes(buff);
             return Convert.ToBase64String(buff);
        }
    
    
          public string GenerateHash(string input, string salt)
          { 
             byte[] bytes = Encoding.UTF8.GetBytes(input + salt);
             SHA256Managed sHA256ManagedString = new SHA256Managed();
             byte[] hash = sHA256ManagedString.ComputeHash(bytes);
             return Convert.ToBase64String(hash);
          }
    
          public bool AreEqual(string plainTextInput, string hashedInput, string salt)
          {
               string newHashedPin = GenerateHash(plainTextInput, salt);
               return newHashedPin.Equals(hashedInput); 
          }
     }

    `



3

मैंने Microsoft द्वारा प्रदान की गई बुनियादी कक्षाओं के साथ हैशिंग की प्रक्रिया को आसान बनाने के लिए एक पुस्तकालय SimpleHashing.Net बनाया है । साधारण एसएचए वास्तव में पर्याप्त सुरक्षित रूप से संग्रहीत पासवर्ड रखने के लिए पर्याप्त नहीं है।

लाइब्रेरी Bcrypt से हैश प्रारूप के विचार का उपयोग करती है, लेकिन चूंकि कोई आधिकारिक एमएस कार्यान्वयन नहीं है, इसलिए मैं उपयोग करना पसंद करता हूं जो कि फ्रेमवर्क में उपलब्ध है (यानी PBKDF2), लेकिन यह बॉक्स से थोड़ा बहुत कठिन है।

यह लाइब्रेरी का उपयोग करने का एक त्वरित उदाहरण है:

ISimpleHash simpleHash = new SimpleHash();

// Creating a user hash, hashedPassword can be stored in a database
// hashedPassword contains the number of iterations and salt inside it similar to bcrypt format
string hashedPassword = simpleHash.Compute("Password123");

// Validating user's password by first loading it from database by username
string storedHash = _repository.GetUserPasswordHash(username);
isPasswordValid = simpleHash.Verify("Password123", storedHash);

2

यह है कि मैं इसे कैसे करता हूं .. मैं हैश बनाता हूं और इसे ProtectedDataएपीआई का उपयोग करके संग्रहीत करता हूं :

    public static string GenerateKeyHash(string Password)
    {
        if (string.IsNullOrEmpty(Password)) return null;
        if (Password.Length < 1) return null;

        byte[] salt = new byte[20];
        byte[] key = new byte[20];
        byte[] ret = new byte[40];

        try
        {
            using (RNGCryptoServiceProvider randomBytes = new RNGCryptoServiceProvider())
            {
                randomBytes.GetBytes(salt);

                using (var hashBytes = new Rfc2898DeriveBytes(Password, salt, 10000))
                {
                    key = hashBytes.GetBytes(20);
                    Buffer.BlockCopy(salt, 0, ret, 0, 20);
                    Buffer.BlockCopy(key, 0, ret, 20, 20);
                }
            }
            // returns salt/key pair
            return Convert.ToBase64String(ret);
        }
        finally
        {
            if (salt != null)
                Array.Clear(salt, 0, salt.Length);
            if (key != null)
                Array.Clear(key, 0, key.Length);
            if (ret != null)
                Array.Clear(ret, 0, ret.Length);
        } 
    }

    public static bool ComparePasswords(string PasswordHash, string Password)
    {
        if (string.IsNullOrEmpty(PasswordHash) || string.IsNullOrEmpty(Password)) return false;
        if (PasswordHash.Length < 40 || Password.Length < 1) return false;

        byte[] salt = new byte[20];
        byte[] key = new byte[20];
        byte[] hash = Convert.FromBase64String(PasswordHash);

        try
        {
            Buffer.BlockCopy(hash, 0, salt, 0, 20);
            Buffer.BlockCopy(hash, 20, key, 0, 20);

            using (var hashBytes = new Rfc2898DeriveBytes(Password, salt, 10000))
            {
                byte[] newKey = hashBytes.GetBytes(20);

                if (newKey != null)
                    if (newKey.SequenceEqual(key))
                        return true;
            }
            return false;
        }
        finally
        {
            if (salt != null)
                Array.Clear(salt, 0, salt.Length);
            if (key != null)
                Array.Clear(key, 0, key.Length);
            if (hash != null)
                Array.Clear(hash, 0, hash.Length);
        }
    }

    public static byte[] DecryptData(string Data, byte[] Salt)
    {
        if (string.IsNullOrEmpty(Data)) return null;

        byte[] btData = Convert.FromBase64String(Data);

        try
        {
            return ProtectedData.Unprotect(btData, Salt, DataProtectionScope.CurrentUser);
        }
        finally
        {
            if (btData != null)
                Array.Clear(btData, 0, btData.Length);
        }
    }

    public static string EncryptData(byte[] Data, byte[] Salt)
    {
        if (Data == null) return null;
        if (Data.Length < 1) return null;

        byte[] buffer = new byte[Data.Length];

        try
        {
            Buffer.BlockCopy(Data, 0, buffer, 0, Data.Length);
            return System.Convert.ToBase64String(ProtectedData.Protect(buffer, Salt, DataProtectionScope.CurrentUser));
        }
        finally
        {
            if (buffer != null)
                Array.Clear(buffer, 0, buffer.Length);
        }
    }

बचत करते समय और बाद में तुलना करते समय मैं इसे कैसे कहूं?
SearchForKnowledge 14

2

मैं सभी उत्तर पढ़ता हूं और मुझे लगता है कि वे पर्याप्त, विशेष रूप से @Michael लेखों के साथ धीमी गति से हैशिंग और @CodesInChaos अच्छी टिप्पणी करते हैं, लेकिन मैंने हैशिंग / मान्य करने के लिए अपने कोड स्निपेट को साझा करने का फैसला किया जो उपयोगी हो सकता है और इसके लिए Microsoft.AspNet.Cryptography की आवश्यकता नहीं है .क्रेडरशिप ]।

    private static bool SlowEquals(byte[] a, byte[] b)
            {
                uint diff = (uint)a.Length ^ (uint)b.Length;
                for (int i = 0; i < a.Length && i < b.Length; i++)
                    diff |= (uint)(a[i] ^ b[i]);
                return diff == 0;
            }

    private static byte[] PBKDF2(string password, byte[] salt, int iterations, int outputBytes)
            {
                Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(password, salt);
                pbkdf2.IterationCount = iterations;
                return pbkdf2.GetBytes(outputBytes);
            }

    private static string CreateHash(string value, int salt_bytes, int hash_bytes, int pbkdf2_iterations)
            {
                // Generate a random salt
                RNGCryptoServiceProvider csprng = new RNGCryptoServiceProvider();
                byte[] salt = new byte[salt_bytes];
                csprng.GetBytes(salt);

                // Hash the value and encode the parameters
                byte[] hash = PBKDF2(value, salt, pbkdf2_iterations, hash_bytes);

                //You need to return the salt value too for the validation process
                return Convert.ToBase64String(hash) + ":" + 
                       Convert.ToBase64String(hash);
            }

    private static bool ValidateHash(string pureVal, string saltVal, string hashVal, int pbkdf2_iterations)
            {
                try
                {
                    byte[] salt = Convert.FromBase64String(saltVal);
                    byte[] hash = Convert.FromBase64String(hashVal);

                    byte[] testHash = PBKDF2(pureVal, salt, pbkdf2_iterations, hash.Length);
                    return SlowEquals(hash, testHash);
                }
                catch (Exception ex)
                {
                    return false;
                }
            }

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


एक व्यस्त लूप बनाने के बजाय, एक कृत्रिम गैर-व्यस्त देरी में क्यों नहीं रखा गया। जैसे Task.Delay का उपयोग करना। यह एक क्रूर बल प्रयास में देरी करेगा लेकिन सक्रिय धागे को अवरुद्ध नहीं करेगा।
गब्बर

आपकी सलाह के लिए @gburton धन्यवाद। मैं इसकी जांच करूंगा।
QMaster

CreateHash में एक टाइपो है: आप Convert.oBase64String (हैश) को नमक के बजाय कंसीनेट कर रहे हैं। इसके अलावा, यह एक अच्छा जवाब है जो अन्य उत्तरों पर टिप्पणियों में उठाए गए हर मुद्दे को बहुत अधिक स्वीकार करता है।
ज़ेमेरज़

2

System.Web.Helpers.CryptoMicrosoft से NuGet पैकेज का उपयोग करें । यह स्वचालित रूप से हैश में नमक जोड़ता है।

आपके पास इस तरह से एक पासवर्ड है: var hash = Crypto.HashPassword("foo");

आप इस तरह से एक पासवर्ड सत्यापित करते हैं: var verified = Crypto.VerifyHashedPassword(hash, "foo");


1

यदि आप asp.net या .net कोर का उपयोग नहीं करते हैं, तो> = .Net मानक 2.0 परियोजनाओं में एक आसान तरीका भी है।

पहले आप हैश, नमक और पुनरावृति संख्या का वांछित आकार निर्धारित कर सकते हैं जो हैश पीढ़ी की अवधि से संबंधित है:

private const int SaltSize = 32;
private const int HashSize = 32;
private const int IterationCount = 10000;

पासवर्ड हैश और नमक को उत्पन्न करने के लिए आप कुछ इस तरह से उपयोग कर सकते हैं:

public static string GeneratePasswordHash(string password, out string salt)
{
    using (Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, SaltSize))
    {
        rfc2898DeriveBytes.IterationCount = IterationCount;
        byte[] hashData = rfc2898DeriveBytes.GetBytes(HashSize);
        byte[] saltData = rfc2898DeriveBytes.Salt;
        salt = Convert.ToBase64String(saltData);
        return Convert.ToBase64String(hashData);
    }
}

यह सत्यापित करने के लिए कि उपयोगकर्ता द्वारा दर्ज किया गया पासवर्ड मान्य है या नहीं, आप अपने डेटाबेस के मानों की जाँच कर सकते हैं:

public static bool VerifyPassword(string password, string passwordHash, string salt)
{
    using (Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, SaltSize))
    {
        rfc2898DeriveBytes.IterationCount = IterationCount;
        rfc2898DeriveBytes.Salt = Convert.FromBase64String(salt);
        byte[] hashData = rfc2898DeriveBytes.GetBytes(HashSize);
        return Convert.ToBase64String(hashData) == passwordHash;
    }
}

निम्नलिखित इकाई परीक्षण उपयोग दिखाता है:

string password = "MySecret";

string passwordHash = PasswordHasher.GeneratePasswordHash(password, out string salt);

Assert.True(PasswordHasher.VerifyPassword(password, passwordHash, salt));
Assert.False(PasswordHasher.VerifyPassword(password.ToUpper(), passwordHash, salt));

Microsoft Rfc2898DeriveBytes स्रोत


-1

मूल प्रश्न के इस भाग के जवाब में "क्या हैशिंग पासवर्ड के लिए कोई अन्य C # विधि है" आप ASP.NET पहचान v3.0 https://www.nuget.org/packages/Microsoft.AspNet.Identity का उपयोग करके इसे प्राप्त कर सकते हैं । EntityFramework / 3.0.0-RC1 फाइनल

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity;
using System.Security.Principal;

namespace HashTest{


    class Program
    {
        static void Main(string[] args)
        {

            WindowsIdentity wi = WindowsIdentity.GetCurrent();

            var ph = new PasswordHasher<WindowsIdentity>();

            Console.WriteLine(ph.HashPassword(wi,"test"));

            Console.WriteLine(ph.VerifyHashedPassword(wi,"AQAAAAEAACcQAAAAEA5S5X7dmbx/NzTk6ixCX+bi8zbKqBUjBhID3Dg1teh+TRZMkAy3CZC5yIfbLqwk2A==","test"));

        }
    }


}

-1
 protected void m_GenerateSHA256_Button1_Click(objectSender, EventArgs e)
{
string salt =createSalt(10);
string hashedPassword=GenerateSHA256Hash(m_UserInput_TextBox.Text,Salt);
m_SaltHash_TextBox.Text=Salt;
 m_SaltSHA256Hash_TextBox.Text=hashedPassword;

}
 public string createSalt(int size)
{
 var rng= new System.Security.Cyptography.RNGCyptoServiceProvider();
 var buff= new byte[size];
rng.GetBytes(buff);
 return Convert.ToBase64String(buff);
}


 public string GenerateSHA256Hash(string input,string salt)
{
 byte[]bytes=System.Text.Encoding.UTF8.GetBytes(input+salt);
 new System.Security.Cyptography.SHA256Managed();
 byte[]hash=sha256hashString.ComputedHash(bytes);
 return bytesArrayToHexString(hash);
  }

अन्य विधि स्ट्रिंग पासवर्ड है = HashPasswordForStoringInConfigFile (TextBox1.Text, SHA1)
shukla

-6
create proc [dbo].[hash_pass] @family nvarchar(50), @username nvarchar(50), @pass nvarchar(Max),``` @semat nvarchar(50), @tell nvarchar(50)

as insert into tbl_karbar values (@family,@username,(select HASHBYTES('SHA1' ,@pass)),@semat,@tell)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.