ASP.NET পরিচয়ের ডিফল্ট পাসওয়ার্ড হ্যাশার - এটি কীভাবে কাজ করে এবং এটি সুরক্ষিত?


162

আমি ভাবছি যে পাসওয়ার্ড হ্যাশারটি এমভিসি 5 এবং এএসপি.নেট আইডেন্টিটি ফ্রেমওয়ার্কের সাথে উপস্থিত ইউজার ম্যানেজারে ডিফল্টভাবে প্রয়োগ করা হয়েছে , তা কি যথেষ্ট নিরাপদ? এবং যদি তাই হয়, আপনি যদি আমাকে ব্যাখ্যা করতে পারেন যে এটি কীভাবে কাজ করে?

আইপাসওয়ার্ডহেশার ইন্টারফেসটি দেখতে এমন দেখাচ্ছে:

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
শিব

@ শিভা ধন্যবাদ, আমি পৃষ্ঠাটির লাইব্রেরি এবং ভিডিওটি সন্ধান করব। তবে আমি বরং বাহ্যিক গ্রন্থাগারের সাথে ডিল করতে হবে না। যদি আমি এটি এড়াতে পারি তবে না।
আন্দ্রে সান্দে কক

2
এফওয়াইআই: সুরক্ষার জন্য স্ট্যাকওভারফ্লো সমতুল্য। সুতরাং আপনি প্রায়শই এখানে একটি ভাল / সঠিক উত্তর পাবেন। বিশেষজ্ঞরা সিকিউরিটি.স্ট্যাকেক্সচেঞ্জ ডটকম-এ রয়েছেন বিশেষত মন্তব্যটি "এটি কি নিরাপদ" আমি একই ধরণের প্রশ্ন জিজ্ঞাসা করেছি এবং উত্তরের গভীরতা এবং গুণমানটি আশ্চর্যজনক ছিল।
ফিল soady

@ ফিলসোয়াডি ধন্যবাদ, এটি অবশ্যই উপলব্ধি করে চলেছে, আমি ইতিমধ্যে অন্যান্য কয়েকটি "সাব-ফোরাম" এর মধ্যে রয়েছি, যদি আমার উত্তর না পাওয়া যায় তবে আমি ব্যবহার করতে পারি, আমি সেখানে চলে যাব securiry.stackexchange.com। এবং টিপ জন্য ধন্যবাদ!
আন্দ্রে সান্দে কক

উত্তর:


227

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

হ্যাশ:

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
@ অ্যান্ড্রেসনেডহানসেন, ঠিক এবং আমি আপনাকে সুরক্ষা বা ক্রিপ্টোগ্রাফি এসই তে জিজ্ঞাসা করার পরামর্শ দিচ্ছি। "এটি কি সুরক্ষিত" অংশটি সেই সম্পর্কিত প্রসঙ্গে আরও ভালভাবে সম্বোধন করা যেতে পারে।
অ্যান্ড্রু সাভিনিখ

1
উপরের উত্তরে বর্ণিত শ্যাশিরপুজাক্কাল
অ্যান্ড্রু সাভিনিখ

3
@ অ্যান্ড্রুস্যাভিনিখ আমি জানি, সে কারণেই আমি জিজ্ঞাসা করছি - আসলে কী? কোডটি আরও স্মার্ট দেখাতে? ;) দশমিক সংখ্যা ব্যবহার করে আমার জন্য জিনিস গণনা করার কারণটি হ'ল অনেক বেশি স্বজ্ঞাত (আমাদের 10 টি আঙুলের পরে রয়েছে - কমপক্ষে আমাদের বেশিরভাগ), তাই হেক্সাডেসিমালগুলি ব্যবহার করে বেশ কিছু কিছু ঘোষণা করা একটি অপ্রয়োজনীয় কোড অবলোকনের মতো মনে হয়।
অ্যান্ড্রু সাইরুল

1
@ মিহাই অ্যালেক্সান্দ্রু-আয়নুত - var hashedPassword = HashPassword(password); var result = VerifyHashedPassword(hashedPassword, password);আপনাকে যা করতে হবে তা হ'ল। এর পরে resultসত্য থাকে।
অ্যান্ড্রু সাভিনিখ

43

কারণ আজকাল এএসপি.এনইটি ওপেন সোর্স, আপনি এটি গিটহাব: এসপনেট.এডেন্টিটি 3.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
গিটহাবের উত্স হ'ল Asp.Net.Identity 3.0 যা এখনও পূর্বরূপে রয়েছে। 2.0 হ্যাশ ফাংশনের উত্স কোডপ্লেক্স
ডেভিড

1
নতুন বাস্তবায়নটি এখন github.com/dotnet/aspnetcore/blob/master/src/Identity/… এর অধীনে পাওয়া যাবে । তারা অন্যান্য সংগ্রহশালা সংরক্ষণাগারভুক্ত করেছে;)
ফ্র্যান্জহবার 23

32

আমি গ্রহণযোগ্য উত্তরটি বুঝতে পেরেছি এবং এটিতে ভোট দিয়েছি তবে ভেবেছিলাম আমার সাধারণ লোকদের উত্তর এখানে ফেলে দেব ...

একটি হ্যাশ তৈরি করা হচ্ছে

  1. আরএফসি 2898 ডেরিভাইটস ফাংশনটি ব্যবহার করে লব এলোমেলোভাবে উত্পাদিত হয় যা একটি হ্যাশ এবং লবণ তৈরি করে। Rfc2898 ডেরিভাইটস ইনপুটগুলি হ'ল পাসওয়ার্ড, উত্পন্ন লবণের আকার এবং হ্যাশিং পুনরাবৃত্তি সম্পাদনের সংখ্যা number https://msdn.microsoft.com/en-us/library/h83s4e12(v=vs.110).aspx
  2. তারপরে লবণ এবং হ্যাশগুলি একসাথে আটকানো হয় (প্রথমে লব এর পরে হ্যাশ হয়) এবং স্ট্রিং হিসাবে এনকোড হয় (সুতরাং লবণের হ্যাশটিতে এনকোড থাকে)। এই এনকোডড হ্যাশ (যার মধ্যে লবণ এবং হ্যাশ রয়েছে) ব্যবহারকারীর বিরুদ্ধে ডাটাবেসে সংরক্ষণ করা হয় (সাধারণত)।

একটি হ্যাশের বিপরীতে একটি পাসওয়ার্ড চেক করা হচ্ছে

কোনও ব্যবহারকারী প্রবেশ করায় এমন পাসওয়ার্ড পরীক্ষা করতে check

  1. সঞ্চিত হ্যাশ পাসওয়ার্ড থেকে লবণ বের করা হয়।
  2. ব্যবহারকারীদের ইনপুট পাসওয়ার্ডটি হ্যাফ করতে লব ব্যবহার করা হয় Rfc2898 ডেরিভাইটসের একটি ওভারলোড ব্যবহার করে যা একটি উত্পন্ন করার পরিবর্তে লবণ নেয়। https://msdn.microsoft.com/en-us/library/yx129kfs(v=vs.110).aspx
  3. সঞ্চিত হ্যাশ এবং পরীক্ষার হ্যাশটি তখন তুলনা করা হয়।

হ্যাশ

কভারগুলির নীচে SHA1 হ্যাশ ফাংশন ( https://en.wikedia.org/wiki/SHA-1 ) ব্যবহার করে হ্যাশ তৈরি করা হয় । এই ফাংশনটি পুনরাবৃত্তভাবে 1000 বার বলা হয় (ডিফল্ট পরিচয় বাস্তবায়নে)

কেন এটি নিরাপদ?

  • এলোমেলো লবণের অর্থ একটি আক্রমণকারী পাসওয়ার্ড চেষ্টা ও ভাঙতে হ্যাশগুলির একটি পূর্ব-উত্পন্ন টেবিল ব্যবহার করতে পারে না। তাদের প্রতিটি লবণের জন্য একটি হ্যাশ টেবিল তৈরি করা দরকার। (এখানে ধরে নিচ্ছি যে হ্যাকার আপনার লবণের সাথেও আপস করেছে)
  • যদি 2 পাসওয়ার্ড অভিন্ন হয় তবে তাদের আলাদা আলাদা হ্যাশ থাকবে। (অর্থাত্ আক্রমণকারীরা 'সাধারণ' পাসওয়ার্ডগুলি নির্ধারণ করতে পারে না)
  • প্রত্যাশাজনকভাবে SHA1 কে 1000 বার কল করার অর্থ আক্রমণকারীকেও এটি করা দরকার do ধারণাটি হ'ল সুপার কম্পিউটারে সময় না থাকলে তাদের কাছে হ্যাশ থেকে পাসওয়ার্ড জোর করার মতো পর্যাপ্ত সংস্থান থাকবে না। প্রদত্ত নুনের জন্য একটি হ্যাশ টেবিল তৈরি করার সময়টি ব্যাপকভাবে ধীর করে দেয়।

তোমার ব্যাখ্যার জন্য ধন্যবাদ. "একটি হ্যাশ 2 তৈরি করা" তে আপনি উল্লেখ করেছেন যে লবণ এবং হ্যাশ একসাথে ছড়িয়ে পড়েছে, আপনি কি জানেন যে এটি এসপনেট ব্যবহারকারীদের সারণীতে পাসওয়ার্ডহ্যাশটিতে সঞ্চিত আছে। আমার দেখার জন্য কোথাও লবণ জমা আছে?
ইউনিকর্ন 2

1
@ ইউনিকর্ন 2 যদি আপনি অ্যান্ড্রু সাভিনিখের জবাবটি একবার দেখে নেন ... হ্যাশিংয়ের বিভাগে দেখে মনে হচ্ছে যে লাইটটি বাইট অ্যারের প্রথম 16 বাইটে সংরক্ষণ করা হয়েছে যা বেস 64৪ এনকোডড এবং ডাটাবেজে লিখিত আছে। আপনি পাসওয়ার্ডহ্যাশ টেবিলটিতে এই বেস 64 এনকোডড স্ট্রিংটি দেখতে সক্ষম হবেন। বেস 64 স্ট্রিং সম্পর্কে আপনি যা বলতে পারেন তা হ'ল এর প্রথম তৃতীয়টি হল লবণ। অর্থবহ লবণটি পাসওয়ার্ডহ্যাশ টেবিলটিতে সঞ্চিত পূর্ণ স্ট্রিংয়ের বেস 64 এর ডিকোড সংস্করণের প্রথম 16 বাইট হয়
নেট্রাস

@ ন্যাট্রেস, হ্যাশ এবং লবণের সম্পর্কে আমার বোঝা বরং মূল বিষয়, তবে যদি হ্যাশ পাসওয়ার্ড থেকে লবণটি সহজেই বের করা হয় তবে প্রথমে সল্ট দেওয়ার কী অর্থ। আমি ভেবেছিলাম যে লবণের অর্থ হ্যাশিং অ্যালগরিদমের অতিরিক্ত ইনপুট যা সহজেই অনুমান করা যায় না।
এনসাউথ

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

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

আপনার কাস্টম অ্যাপ্লিকেশন-ব্যবহারকারী ম্যানেজারে আপনি পাসওয়ার্ডহ্যাশার সম্পত্তিটিকে উপরের কোড সহ শ্রেণীর নাম সেট করেছেন set


এই জন্য .. _passwordHashBytes = bytes.GetBytes(SaltByteSize); আমার ধারণা আপনি এটি বোঝাতে চেয়েছিলেন _passwordHashBytes = bytes.GetBytes(HashByteSize);.. আপনার
দৃশ্যে
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.