সি # তে হ্যাশ এবং লবণের পাসওয়ার্ড


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

পাসওয়ার্ডগুলি হ্যাশ করার জন্য এবং এটিতে লবণ যুক্ত করার জন্য কি আর কোনও সি # পদ্ধতি রয়েছে?


এখানে একটি লাইব্রেরি রয়েছে যা লবণ এনক্রিপ্টো.কম্প্লেক্স.কমের
ওমু

6
লবণ উত্পন্ন করার জন্য প্রথম পদ্ধতিতে আপনার আকারটি কী পাস করতে হবে?
শেন লেব্ল্যাঙ্ক

6
লিঙ্কটি নষ্ট হয়ে গেছে।
ওসমানরাইফগুনস

@ শ্যানলেব্ল্যাঙ্ক আপনার ফাংশন আউটপুট হিসাবে কমপক্ষে বিট করা উচিত। SHA1ক্রিপ্টো-গ্রেড নয়, তাই আপনার কমপক্ষে ব্যবহার করা উচিত SHA256, যা 256 বিট বা 32 বাইট আউটপুট করে। তবে, 256 বিটগুলি সহজেই বেসের 64 তে রূপান্তরিত হয় না, কারণ প্রতিটি বেস 64 চর 6 বিট এনকোড করে, এবং 256 সম্পূর্ণ 6 দ্বারা বিভাজ্য নয়, সুতরাং আপনার 6 (বেস 64 এর জন্য) এবং 8 (একটি বাইটে বিটের জন্য) এর একটি সাধারণ বিভাজন প্রয়োজন 256 এর বেশি বিট, যা 264 কামড় বা 33 বাইট। টিএলডিআর: 33 ব্যবহার করুন।
ভিএসও

উত্তর:


248

প্রকৃতপক্ষে স্ট্রিং রূপান্তরগুলির সাথে এটি এক ধরণের অদ্ভুত membership যা সদস্যপদ প্রদানকারী তাদের কনফিগারেশন ফাইলগুলিতে রাখে does হ্যাশ এবং সল্টগুলি বাইনারি ব্লব হয়, আপনি যদি না পাঠ্য ফাইলে না রাখতে চান তবে আপনার সেগুলিতে স্ট্রিংয়ে রূপান্তর করতে হবে না।

আমার বইয়ের শুরু, এএসপি.নেট সুরক্ষা , (ওহ, শেষ অবধি বইটি ফুটিয়ে তোলার বাহানা) আমি নিম্নলিখিতটি করি

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
তুলনা বাইটআরাইয়ের জন্য নিফটি লিনকিউ স্টেটমেন্ট রিফ্যাক্টর return array1.Length == array2.Length && !array1.Where((t, i) => t != array2[i]).Any();
শিকারি

6
@ ব্রেটস্কি প্রযুক্তিগতভাবে হ্যাঁ, তবে প্রতিটি ব্যবহারকারীর জন্য একটি অনন্য লবণের কারণে রেইনবো টেবিলগুলি (সাধারণত হ্যাশ পাসওয়ার্ড ক্র্যাক করার সর্বাধিক দক্ষ উপায় হিসাবে গ্রহণ করা হয়) ব্যবহারিকভাবে অকেজো হয়ে যায়। এটি একটি দ্রুত ওভারভিউটি কীভাবে পাসওয়ার্ডগুলি সুরক্ষিতভাবে সংরক্ষণ করতে হবে এবং কেন / কীভাবে এটি সমস্ত কাজ করে সে সম্পর্কে একটি গভীরতর কিন্তু অবিশ্বাস্য ওভারভিউ দেয় না।
রেঞ্জার

3
@ হান্টার: অবিচ্ছিন্ন সময় তৈরি করার জন্য আপনার একটি .ToList () যুক্ত করা উচিত। উদাহরণস্বরূপ: অ্যারে 1 ফেরান। অন্যথায়, লিনকিউ সমান নয় এমন একটি বাইট খুঁজে পাওয়ার সাথে সাথে ফিরে আসবে।
অ্যালেক্স রৌলার্ড

17
একটি দ্রুত হ্যাশ-ফাংশন ব্যবহার করার জন্য -1। PBKDF2, bcrypt বা scrypt এর মতো ধীরগতির নির্মাণ ব্যবহার করুন।
কোডসইনচাউস

48

ব্লোডার্ট কি বলেছে, তবে কিছুটা কম কোড সহ। লিনক ব্যবহার করুন বা 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);
}

আপনার বাইট অ্যারের সাথে তুলনা করার জন্য লিনকের একটি সহজ উপায় রয়েছে।

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

    return _passwordHash.SequenceEqual(passwordHash);
}

তবে এই কোন বাস্তবায়ন করার আগে, খুঁজে বার করো পোস্টটি । পাসওয়ার্ড হ্যাশিংয়ের জন্য আপনি একটি ধীরে ধীরে হ্যাশ অ্যালগরিদম চাইতে পারেন।

এই লক্ষ্যে এমন Rfc2898DeriveBytesশ্রেণি রয়েছে যা ধীর (এবং ধীরে ধীরে তৈরি করা যেতে পারে), এবং এটি মূল প্রশ্নের দ্বিতীয় অংশের উত্তর দিতে পারে যাতে এটি একটি পাসওয়ার্ড এবং লবণ নিতে পারে এবং একটি হ্যাশ ফিরে আসতে পারে। আরও তথ্যের জন্য এই প্রশ্নটি দেখুন । দ্রষ্টব্য, স্ট্যাক এক্সচেঞ্জRfc2898DeriveBytes পাসওয়ার্ড হ্যাশিংয়ের জন্য ব্যবহার করছে (উত্স কোড এখানে )।


6
@ মুশিননশিন SHA256 একটি দ্রুত হ্যাশ। পাসওয়ার্ড হ্যাশিংয়ের জন্য ধীর হ্যাশ দরকার যেমন পিবিকেডিএফ 2, বিসিআরপিট বা স্ক্রিপ্ট। দেখুন নিরাপদে হ্যাশ পাসওয়ার্ডে কিভাবে? সুরক্ষার জন্য।
কোডসইনচাউস

32

আমি পড়ছি যে SHA256 এর মতো হ্যাশিং ফাংশনগুলি সত্যই পাসওয়ার্ডগুলি সংরক্ষণের উদ্দেশ্যে ব্যবহার করা হয়নি: https://patrickmn.com/security/store-passwords-securely/#notpasswordhashes

পরিবর্তে অভিযোজিত কী ডেরাইভেশন ফাংশনগুলির মতো পিবিকেডিএফ 2, বিসিক্রিপ্ট বা স্ক্রিপ্ট ছিল। মাইক্রোসফ্ট তাদের মাইক্রোসফ্ট-এ পাসওয়ার্ডহ্যাশারের জন্য লিখেছেন এমন একটি পিবিকেডিএফ 2 ভিত্তিক একটি এখানে রয়েছে spস্পেন নেট.আইডেন্টিটি লাইব্রেরি:

/* =======================
 * 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]));
}

নোট করুন এর জন্য মাইক্রোসফ্ট.এএসপনেটকোর.ক্রিপোগ্রাফি.কি- ডেরিভেশন নুগেট প্যাকেজ ইনস্টল করা হয়েছে যার জন্য .NET স্ট্যান্ডার্ড 2.0 (। নেট 4.6.1 বা তার বেশি) প্রয়োজন। .NET- র পূর্ববর্তী সংস্করণগুলির জন্য মাইক্রোসফ্টের সিস্টেম.বিউব.হেলপার্স লাইব্রেরি থেকে ক্রিপ্টো ক্লাসটি দেখুন ।

আপডেট নভেম্বর 2015
আপডেট অন্য মাইক্রোসফট লাইব্রেরি থেকে PBKDF2-HMAC-SHA256 এর পরিবর্তে PBKDF2-HMAC-SHA256 ব্যবহার করে হ্যাশিং ব্যবহার করা হয়েছে এমন একটি প্রয়োগকরণ ব্যবহারের আপডেট হওয়া উত্তর (নোট PBKDF2-HMAC-SHA1 এখনও সুরক্ষিত যদি এটির পরিমাণ যথেষ্ট থাকে)। আপনি সরলিকৃত কোডটি অনুলিপি করে উত্সটি পরীক্ষা করতে পারেন যেহেতু এটি পূর্ববর্তী উত্তর থেকে বাস্তবায়িত হ্যাশগুলি যাচাইকরণ এবং আপগ্রেড করার ক্ষেত্রে পরিচালনা করে, যদি আপনাকে ভবিষ্যতে এটিরকাউন্ট বাড়ানোর প্রয়োজন হয় তবে দরকারী।


1
নোট করুন এটি সম্ভবত আরও বেশি সংখ্যক পিবিকেডিএফ 2 আইটারকাউন্ট বাড়ানোর উপযুক্ত, আরও জন্য সিকিউরিটি.স্ট্যাকেক্সেঞ্জাং.কম / কিউ / 3959 দেখুন।
মাইকেল

2
1) PBKDF2SubkeyLength20 বাইট হ্রাস করুন । এটি প্রাকৃতিক আকারের চ এসএইচএ 1 এবং এর বাইরে এটি আক্রমণকারীকে ধীর না করে ডিফেন্ডারকে ধীর করে দেয়। 2) আমি পুনরাবৃত্তি গণনা বাড়ানোর প্রস্তাব দিই। আমি আপনার পারফরম্যান্স বাজেটের উপর নির্ভর করে 10 কে থেকে 100 কে সুপারিশ করছি। 3) একটি ধ্রুবক সময় তুলনা হয় আঘাত করতে পারে না, কিন্তু খুব ব্যবহারিক প্রভাব আছে।
কোডসইনচাওস

কীডেরিভিশনপিআরএফ, কীডেরিভেশন এবং ব্লককপি অপরিবর্তিত, তাদের ক্লাসগুলি কী?
mrbengi

@ এমআরবেঙ্গী আপনি কি মাইক্রোসফ্ট ইনস্টল করেছেন? এসপনেট.ক্রিপোগ্রাফি.কি-ডেরিভেশন নুগেট প্যাকেজের উল্লেখ আছে? যদি উপযুক্ত নয় এখানে একটি সংস্করণ যে nuget প্যাকেজ প্রয়োজন হয় না হয়। বাফার.ব্লককপি এটি সিস্টেমের অংশ থাকা উচিত।
মাইকেল

1
নুগেট প্যাকেজটি এখন মাইক্রোসফ্ট.আসপনেটকোর.ক্রিপোগ্রাফি.কি-ডেরিভেশন।
জেমস ব্লেক

25

হ্যাশটিতে জটিলতার অতিরিক্ত স্তর যুক্ত করার জন্য লবণ ব্যবহার করা হয়, যাতে শক্তিশালী ক্র্যাককে আরও শক্ত করা যায়।

সিটপয়েন্টের একটি নিবন্ধ থেকে :

অভিধানী আক্রমণ হিসাবে পরিচিত যাকে এখনও একজন হ্যাকার সম্পাদন করতে পারে। ক্ষতিকারক পক্ষগুলি উদাহরণস্বরূপ, 100,000 পাসওয়ার্ড যা তারা জানত যে লোকেরা প্রায়শই ব্যবহার করে (উদাহরণস্বরূপ শহরের নাম, স্পোর্টস দল ইত্যাদি), হ্যাশ করে এবং অভিধানের প্রত্যেকটি সারিটির সাথে ডাটাবেসের প্রতিটি সারিটির তুলনায় অভিধানের আক্রমণ করতে পারে টেবিল। হ্যাকাররা যদি ম্যাচ খুঁজে পান, বিঙ্গো! তাদের কাছে আপনার পাসওয়ার্ড রয়েছে। তবে এই সমস্যাটি সমাধান করার জন্য আমাদের কেবল হ্যাশ লাগানো দরকার।

একটি হ্যাশ লবণের জন্য, আমরা কেবল এলোমেলোভাবে পাঠ্যের একটি স্ট্রিং নিয়ে আসি, এটি ব্যবহারকারীর দ্বারা সরবরাহ করা পাসওয়ার্ডের সাথে একত্রিত করি, তারপরে এলোমেলোভাবে উত্পন্ন স্ট্রিং এবং পাসওয়ার্ড উভয়কে হ্যাশ হিসাবে এক সাথে মান হিসাবে আনা হয়। তারপরে আমরা হ্যাশ এবং লবণ দুটি পৃথক ক্ষেত্র হিসাবে ব্যবহারকারীদের সারণির মধ্যে সংরক্ষণ করি save

এই দৃশ্যে, কেবল কোনও হ্যাকারের পাসওয়ার্ড অনুমান করার প্রয়োজন হবে না, তাদের পাশাপাশি লবণেরও অনুমান করতে হবে। স্পষ্ট পাঠ্যে লবণ যুক্ত করা সুরক্ষার উন্নতি করে: এখন, কোনও হ্যাকার যদি অভিধানের আক্রমণ করার চেষ্টা করে, তবে অবশ্যই তাকে প্রতিটি ব্যবহারকারীর সারির লবণের সাথে তার 100,000 এন্ট্রি হ্যাশ করতে হবে। এটি এখনও সম্ভব হলেও, হ্যাকিংয়ের সাফল্যের সম্ভাবনা আমূল হ্রাস পাচ্ছে।

নেট এ স্বয়ংক্রিয়ভাবে এটি করার কোন পদ্ধতি নেই, সুতরাং আপনি উপরের সমাধানটি দিয়ে চলেছেন।


সল্টগুলি রংধনু টেবিলের মতো জিনিসগুলির বিরুদ্ধে রক্ষা করতে ব্যবহৃত হয়। অভিধান আক্রমণ থেকে রক্ষা করার জন্য কোনও কাজের ফ্যাক্টর (কী স্ট্রেচিং নামেও পরিচিত) যে কোনও ভাল কেডিএফের মতো প্রয়োজন: en.wikedia.org/wiki/Key_stretching
এরওয়ান লেগ্রান্ড

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

    `


5

বাহ, এই ভাল! http://sourceforge.net/projects/pwdtknet/ এবং এটি আরও ভাল কারণ ..... এটি কী স্ট্রেচিং সম্পাদন করে এবং এইচএমএএসএএসএএসএসিএলসি ব্যবহার করে :)


3

মাইক্রোসফ্ট দ্বারা সরবরাহিত বেসিক ক্লাসগুলির সাথে হ্যাশিংয়ের প্রক্রিয়াটিকে সহজ করার জন্য আমি একটি লাইব্রেরি সিম্পল হ্যাশিং. নেট তৈরি করেছি । পাসওয়ার্ডগুলি আর নিরাপদে সংরক্ষণের জন্য সাধারণ এসএএই যথেষ্ট নয়।

লাইব্রেরি হ'ল বিন্যাসের ধারণাটি ব্র্যাকপ্যাট থেকে ব্যবহার করেছে, তবে কোনও এমএস প্রয়োগকারী নেই বলে আমি ফ্রেমওয়ার্কে যা পাওয়া যায় তা ব্যবহার করতে পছন্দ করি (অর্থাত্ পিবিকেডিএফ 2), তবে এটি বাক্সের বাইরে কিছুটা শক্ত।

লাইব্রেরিটি কীভাবে ব্যবহার করবেন এটি এটি একটি দ্রুত উদাহরণ is

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

সংরক্ষণের সময় এবং পরে তুলনা করার সময় আমি কীভাবে এটি কল করব?
ফোরামক্লানজ

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

দয়া করে মনোযোগ দিন স্লোইকুয়ালস ফাংশন যা এত গুরুত্বপূর্ণ, অবশেষে, আমি এই সহায়তা আশা করি এবং দয়া করে আমাকে আরও ভাল পদ্ধতির বিষয়ে পরামর্শ দিতে দ্বিধা করবেন না।


ব্যস্ত লুপ তৈরির পরিবর্তে, কেন কৃত্রিম অ-ব্যস্ত দেরীতে রাখবেন না। যেমন টাস্ক.ডেলা ব্যবহার করে। এটি একটি দৃ force় বলের প্রয়াসকে বিলম্ব করবে তবে সক্রিয় থ্রেডটিকে অবরুদ্ধ করবে না।
gburton

@gburton আপনার পরামর্শের জন্য ধন্যবাদ। আমি এটি পরীক্ষা করে দেখব.
কিউমাস্টার

ক্রিয়েটহ্যাশে একটি টাইপ রয়েছে: আপনি কনভার্ট করছেন কনভার্ট o এগুলি ছাড়াও, এটি একটি দুর্দান্ত উত্তর যা অন্যান্য উত্তরগুলিতে মন্তব্যে উত্থাপিত প্রতিটি ইস্যুটিকে প্রায় অনেকটা সমাধান করে।
জেরেমেজ

2

System.Web.Helpers.Cryptoমাইক্রোসফ্ট থেকে নিউগেট প্যাকেজটি ব্যবহার করুন ।এটি স্বয়ংক্রিয়ভাবে হ্যাশটিতে লবণ যুক্ত করে।

আপনি এর মত একটি পাসওয়ার্ড হ্যাশ: var hash = Crypto.HashPassword("foo");

আপনি এটির মতো একটি পাসওয়ার্ড যাচাই করুন: var verified = Crypto.VerifyHashedPassword(hash, "foo");


1

আপনি যদি এসপ নেট বা নেট নেট ব্যবহার না করেন তবে> =। নেট স্ট্যান্ডার্ড 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));

মাইক্রোসফ্ট আরএফসি 2898 ডেরিভাইটস উত্স


-1

মূল প্রশ্নের "অংশীদাগুলি হ্যাশ করার জন্য অন্য কোনও সি # পদ্ধতি আছে কি?" এর উত্তরে আপনি এএসপি.নেট পরিচয় v3.0 https://www.nuget.org/packages/Mic 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);
  }

অন্য পদ্ধতিটি স্ট্রিং পাসওয়ার্ড = হ্যাশপ্যাসওয়ার্ডফোরসটারিংআইনকনফিগফিল (টেক্সটবক্স 1. পাঠ্য, এসএইএ 1)
অঙ্কুশ শুক্ল

-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)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.