কীভাবে একটি পাসওয়ার্ড হ্যাশ করবেন


117

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

উত্তর:


62

আপডেট : এই উত্তরটি গুরুতরভাবে প্রকাশিত । পরিবর্তে https://stackoverflow.com/a/10402129/251311 থেকে সুপারিশগুলি ব্যবহার করুন ।

আপনি হয় ব্যবহার করতে পারেন

var md5 = new MD5CryptoServiceProvider();
var md5data = md5.ComputeHash(data);

অথবা

var sha1 = new SHA1CryptoServiceProvider();
var sha1data = sha1.ComputeHash(data);

dataবাইট অ্যারে হিসাবে আপনি ব্যবহার করতে পারেন হিসাবে পেতে

var data = Encoding.ASCII.GetBytes(password);

এবং থেকে ফিরে স্ট্রিং পেতে md5dataবাsha1data

var hashedPassword = ASCIIEncoding.GetString(md5data);

11
আমি সত্যিই SHA1 ব্যবহার করার পরামর্শ দেব। আপনি যদি কোনও বিদ্যমান সিস্টেমের সাথে পশ্চাদগম সামঞ্জস্যতা বজায় না রাখেন তবে MD5 হ'ল না। এছাড়াও, আপনি যখন এটি বাস্তবায়ন ব্যবহারের কাজটি সম্পন্ন করেন তখন আপনি কোনও usingবিবৃতিতে রেখেছিলেন বা Clear()এটিতে কল করে তা নিশ্চিত করুন।
vcsjones

3
@ ভিসিএস জোন্স: আমি এখানে পবিত্র-যুদ্ধ করতে চাই না, তবে md5প্রায় সব ধরণের কাজের জন্যই যথেষ্ট ভাল। এর দুর্বলতাগুলি খুব নির্দিষ্ট পরিস্থিতিগুলিকেও বোঝায় এবং প্রায় আক্রমণকারীকে ক্রিপ্টোগ্রাফি সম্পর্কে অনেক কিছু জানার প্রয়োজন হয় to
zerkms

4
@ জারকামস পয়েন্টটি নেওয়া হয়েছে, তবে পশ্চাদপটে সামঞ্জস্যের কোনও কারণ না থাকলে MD5 ব্যবহার করার কোনও কারণ নেই। "দুঃখিত চেয়ে ভাল নিরাপদ".
vcsjones

4
এই সময়ে MD5 ব্যবহার করার কোনও কারণ নেই। গণনার সময় তুচ্ছ বলে মনে করাতে বিদ্যমান সিস্টেমের সাথে সামঞ্জস্যতা ছাড়া এমডি 5 ব্যবহার করার কোনও কারণ নেই। এমনকি এমডি 5 "যথেষ্ট ভাল" ব্যবহারকারীর সাথে আরও বেশি সুরক্ষিত এসএইচএ-এর কোনও দাম নেই। আমি নিশ্চিত zerkms এটি জানেন প্রশ্নটি প্রশ্নকর্তার জন্য আরও।
জেরাল্ড ডেভিস

11
তিনটি বড় ভুল: 1) এএসসিআইআই চুপচাপ অস্বাভাবিক চরিত্রগুলির সাথে পাসওয়ার্ডকে হ্রাস করে 2) সাধারণ MD5 / SHA-1 / SHA-2 দ্রুত। 3) আপনার একটি লবণ প্রয়োজন। | পরিবর্তে PBKDF2, bcrypt বা স্ক্রিপ্ট ব্যবহার করুন। আরবিসিডিএফ 2 আরএফসি 2898 ডেরিভাইটস ক্লাসে সবচেয়ে সহজ (
ডাব্লুপি

298

এখানে অন্যান্য উত্তরগুলির বেশিরভাগই আজকের সেরা অনুশীলনের সাথে কিছুটা পুরানো। যেমন Rfc2898DeriveBytesপাসওয়ার্ডগুলি সংরক্ষণ এবং যাচাই করতে PBKDF2 / ব্যবহার করার আবেদন এখানে । নিম্নলিখিত কোডটি এই পোস্টে একটি একা ক্লাসে রয়েছে: একটি সল্ট পাসওয়ার্ড হ্যাশ কীভাবে সংরক্ষণ করবেন তার আরেকটি উদাহরণ । বেসিকগুলি সত্যই সহজ, সুতরাং এখানে এটি ভেঙে গেছে:

পদক্ষেপ 1 একটি ক্রিপ্টোগ্রাফিক PRNG দিয়ে লবণের মান তৈরি করুন:

byte[] salt;
new RNGCryptoServiceProvider().GetBytes(salt = new byte[16]);

পদক্ষেপ 2 আরএফসি 2898 ডেরিভাইটগুলি তৈরি করুন এবং হ্যাশটির মান পান:

var pbkdf2 = new Rfc2898DeriveBytes(password, salt, 100000);
byte[] hash = pbkdf2.GetBytes(20);

পদক্ষেপ 3 পরবর্তী ব্যবহারের জন্য লবণ এবং পাসওয়ার্ড বাইট একত্রিত করুন:

byte[] hashBytes = new byte[36];
Array.Copy(salt, 0, hashBytes, 0, 16);
Array.Copy(hash, 0, hashBytes, 16, 20);

পদক্ষেপ 4 সংযুক্ত লবণ + হ্যাশটিকে স্টোরেজের জন্য স্ট্রিংয়ে পরিণত করুন

string savedPasswordHash = Convert.ToBase64String(hashBytes);
DBContext.AddUser(new User { ..., Password = savedPasswordHash });

পদক্ষেপ 5 একটি সঞ্চিত পাসওয়ার্ডের বিরুদ্ধে ব্যবহারকারী-প্রবেশ করা পাসওয়ার্ড যাচাই করুন

/* Fetch the stored value */
string savedPasswordHash = DBContext.GetUser(u => u.UserName == user).Password;
/* Extract the bytes */
byte[] hashBytes = Convert.FromBase64String(savedPasswordHash);
/* Get the salt */
byte[] salt = new byte[16];
Array.Copy(hashBytes, 0, salt, 0, 16);
/* Compute the hash on the password the user entered */
var pbkdf2 = new Rfc2898DeriveBytes(password, salt, 100000);
byte[] hash = pbkdf2.GetBytes(20);
/* Compare the results */
for (int i=0; i < 20; i++)
    if (hashBytes[i+16] != hash[i])
        throw new UnauthorizedAccessException();

দ্রষ্টব্য: আপনার নির্দিষ্ট অ্যাপ্লিকেশনটির কার্য সম্পাদনের প্রয়োজনীয়তার উপর নির্ভর করে মান 100000হ্রাস করা যেতে পারে। সর্বনিম্ন মানটি প্রায় হওয়া উচিত 10000


8
@ ড্যানিয়েল মূলত পোস্টটি হ্যাশের চেয়ে বেশি নিরাপদ কিছু ব্যবহার করার বিষয়ে about যদি আপনি কেবল পাসওয়ার্ড হ্যাশ করেন, এমনকি লবণের সাথেও, আপনার ব্যবহারকারীর পাসওয়ার্ডগুলি আপলোড করার আগে বলার সুযোগ পাওয়ার আগেই আপত্তি করা হবে (এবং সম্ভবত বিক্রি / প্রকাশিত হবে)। বিকাশকারীর পক্ষে সহজ নয়, আক্রমণকারীর পক্ষে এটি সহজ করতে উপরের কোডটি ব্যবহার করুন।
csharptest.net

2
@ ডাটভিএম নং, প্রতিবার আপনি একটি হ্যাশ সঞ্চয় করার জন্য নতুন লবণ। এজন্য এটি স্টোরেজের জন্য হ্যাশের সাথে একত্রিত হয়েছে যাতে আপনি কোনও পাসওয়ার্ড যাচাই করতে পারেন।
csharptest.net

9
@ সিপরিয়ান জিজি পুরো পয়েন্টটি আপনার সক্ষম হবেন বলে মনে করছেন না।
csharptest.net

9
যদি কেউ একটি ভেরিফাইপাওয়ার্ড পদ্ধতি করে থাকে, আপনি যদি লিনক এবং একটি বুলিয়ানের জন্য একটি সংক্ষিপ্ত কল ব্যবহার করতে চান তবে এটি করতে হবে: হ্যাশ.সিকুইয়েন্সএকুয়াল (হ্যাশবাইটস.সকিপ (_সাল্টসাইজ)) রিটার্ন করুন;
জেসি কাস্তিলো

2
@ csharptest.net আপনি কোন ধরণের অ্যারে মাপের পরামর্শ দিচ্ছেন? অ্যারের আকারটি যাইহোক সুরক্ষাকে প্রভাবিত করে? আমি হ্যাশিং / ক্রিপ্টোগ্রাফি সম্পর্কে তেমন কিছুই জানি না
ল্যানি

71

Csharptest.net এর দুর্দান্ত উত্তরের ভিত্তিতে আমি এর জন্য একটি ক্লাস লিখেছি:

public static class SecurePasswordHasher
{
    /// <summary>
    /// Size of salt.
    /// </summary>
    private const int SaltSize = 16;

    /// <summary>
    /// Size of hash.
    /// </summary>
    private const int HashSize = 20;

    /// <summary>
    /// Creates a hash from a password.
    /// </summary>
    /// <param name="password">The password.</param>
    /// <param name="iterations">Number of iterations.</param>
    /// <returns>The hash.</returns>
    public static string Hash(string password, int iterations)
    {
        // Create salt
        byte[] salt;
        new RNGCryptoServiceProvider().GetBytes(salt = new byte[SaltSize]);

        // Create hash
        var pbkdf2 = new Rfc2898DeriveBytes(password, salt, iterations);
        var hash = pbkdf2.GetBytes(HashSize);

        // Combine salt and hash
        var hashBytes = new byte[SaltSize + HashSize];
        Array.Copy(salt, 0, hashBytes, 0, SaltSize);
        Array.Copy(hash, 0, hashBytes, SaltSize, HashSize);

        // Convert to base64
        var base64Hash = Convert.ToBase64String(hashBytes);

        // Format hash with extra information
        return string.Format("$MYHASH$V1${0}${1}", iterations, base64Hash);
    }

    /// <summary>
    /// Creates a hash from a password with 10000 iterations
    /// </summary>
    /// <param name="password">The password.</param>
    /// <returns>The hash.</returns>
    public static string Hash(string password)
    {
        return Hash(password, 10000);
    }

    /// <summary>
    /// Checks if hash is supported.
    /// </summary>
    /// <param name="hashString">The hash.</param>
    /// <returns>Is supported?</returns>
    public static bool IsHashSupported(string hashString)
    {
        return hashString.Contains("$MYHASH$V1$");
    }

    /// <summary>
    /// Verifies a password against a hash.
    /// </summary>
    /// <param name="password">The password.</param>
    /// <param name="hashedPassword">The hash.</param>
    /// <returns>Could be verified?</returns>
    public static bool Verify(string password, string hashedPassword)
    {
        // Check hash
        if (!IsHashSupported(hashedPassword))
        {
            throw new NotSupportedException("The hashtype is not supported");
        }

        // Extract iteration and Base64 string
        var splittedHashString = hashedPassword.Replace("$MYHASH$V1$", "").Split('$');
        var iterations = int.Parse(splittedHashString[0]);
        var base64Hash = splittedHashString[1];

        // Get hash bytes
        var hashBytes = Convert.FromBase64String(base64Hash);

        // Get salt
        var salt = new byte[SaltSize];
        Array.Copy(hashBytes, 0, salt, 0, SaltSize);

        // Create hash with given salt
        var pbkdf2 = new Rfc2898DeriveBytes(password, salt, iterations);
        byte[] hash = pbkdf2.GetBytes(HashSize);

        // Get result
        for (var i = 0; i < HashSize; i++)
        {
            if (hashBytes[i + SaltSize] != hash[i])
            {
                return false;
            }
        }
        return true;
    }
}

ব্যবহার:

// Hash
var hash = SecurePasswordHasher.Hash("mypassword");

// Verify
var result = SecurePasswordHasher.Verify("mypassword", hash);

একটি নমুনা হ্যাশ এটি হতে পারে:

$MYHASH$V1$10000$Qhxzi6GNu/Lpy3iUqkeqR/J1hh8y/h5KPDjrv89KzfCVrubn

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


আপনি যদি নেট নেট সম্পর্কে আগ্রহী হন তবে আমার কাছে কোড রিভিউতে । নেট কোর সংস্করণও রয়েছে ।


1
কেবলমাত্র যাচাই করার জন্য, আপনি যদি হ্যাশিং ইঞ্জিনটি আপগ্রেড করেন তবে আপনি নিজের হ্যাশের ভি 1 বিভাগটি বাড়িয়ে দিবেন এবং কীটি বন্ধ করে দেবেন?
মাইক কোলে

1
হ্যাঁ সেই পরিকল্পনা। তারপরে V1এবং আপনার V2যা যাচাইকরণের পদ্ধতির ভিত্তিতে আপনি সিদ্ধান্ত নেবেন ।
ক্রিশ্চিয়ান গোলহার্ড্ট

উত্তর এবং ক্লাসের জন্য ধন্যবাদ। আমরা কথা হিসাবে এটি বাস্তবায়ন করছি।
মাইক কোলে

2
হ্যাঁ @ নেলসনসিলভা। লবণের কারণেই ।
ক্রিশ্চিয়ান গোলহার্ড্ট

1
এই কোডটির সমস্ত অনুলিপি / আটকানো (আমাকে সহ) সহ, আমি আশা করি কেউ কথা বলেছে এবং যদি কোনও সমস্যা পাওয়া যায় তবে পোস্টটি সংশোধিত হয়ে যায়! :)
পেটিস

14

আমি আমার পাসওয়ার্ড এনক্রিপশনের জন্য একটি হ্যাশ এবং একটি লবণ ব্যবহার করি (এটি একই হ্যাশ যা অ্যাস্প। নেট সদস্যতা ব্যবহার করে):

private string PasswordSalt
{
   get
   {
      var rng = new RNGCryptoServiceProvider();
      var buff = new byte[32];
      rng.GetBytes(buff);
      return Convert.ToBase64String(buff);
   }
}

private string EncodePassword(string password, string salt)
{
   byte[] bytes = Encoding.Unicode.GetBytes(password);
   byte[] src = Encoding.Unicode.GetBytes(salt);
   byte[] dst = new byte[src.Length + bytes.Length];
   Buffer.BlockCopy(src, 0, dst, 0, src.Length);
   Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length);
   HashAlgorithm algorithm = HashAlgorithm.Create("SHA1");
   byte[] inarray = algorithm.ComputeHash(dst);
   return Convert.ToBase64String(inarray);
}

16
প্লেইন এসএএএ -1 ব্যবহারের জন্য -1, যা দ্রুত। একটি ধীর কী ডেরাইভেশন ফাংশন যেমন PBKDF2, bcrypt বা স্ক্রিপ্ট ব্যবহার করুন।
কোডসইনচাউস

1
  1. একটি লবণ তৈরি করুন,
  2. লবণের সাহায্যে একটি হ্যাশ পাসওয়ার্ড তৈরি করুন
  3. হ্যাশ এবং লবণ উভয় সংরক্ষণ করুন
  4. পাসওয়ার্ড এবং লবণের সাথে ডিক্রিপ্ট করুন ... সুতরাং বিকাশকারীরা ডিক্রিপ্ট পাসওয়ার্ডটি ক্যান না
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); 
      }
 }

1

@ csharptest.net এর এবং ক্রিশ্চিয়ান গোলহার্টের উত্তরগুলি দুর্দান্ত, আপনাকে অনেক ধন্যবাদ। কিন্তু কয়েক মিলিয়ন রেকর্ডের সাথে উত্পাদনে এই কোডটি চালানোর পরে, আমি আবিষ্কার করেছি সেখানে একটি মেমরি ফাঁস রয়েছে। আরএনজিক্রিপ্টো সার্ভিস প্রোভাইডার এবং আরএফসি 2898 ডেরিভ বাইটস ক্লাসগুলি আইডিসপোজেবল থেকে প্রাপ্ত কিন্তু আমরা সেগুলি নিষ্পত্তি করি না। যদি কারও নিষ্পত্তিযোগ্য সংস্করণ প্রয়োজন হয় তবে আমি উত্তর হিসাবে আমার সমাধানটি লিখব।

public static class SecurePasswordHasher
{
    /// <summary>
    /// Size of salt.
    /// </summary>
    private const int SaltSize = 16;

    /// <summary>
    /// Size of hash.
    /// </summary>
    private const int HashSize = 20;

    /// <summary>
    /// Creates a hash from a password.
    /// </summary>
    /// <param name="password">The password.</param>
    /// <param name="iterations">Number of iterations.</param>
    /// <returns>The hash.</returns>
    public static string Hash(string password, int iterations)
    {
        // Create salt
        using (var rng = new RNGCryptoServiceProvider())
        {
            byte[] salt;
            rng.GetBytes(salt = new byte[SaltSize]);
            using (var pbkdf2 = new Rfc2898DeriveBytes(password, salt, iterations))
            {
                var hash = pbkdf2.GetBytes(HashSize);
                // Combine salt and hash
                var hashBytes = new byte[SaltSize + HashSize];
                Array.Copy(salt, 0, hashBytes, 0, SaltSize);
                Array.Copy(hash, 0, hashBytes, SaltSize, HashSize);
                // Convert to base64
                var base64Hash = Convert.ToBase64String(hashBytes);

                // Format hash with extra information
                return $"$HASH|V1${iterations}${base64Hash}";
            }
        }

    }

    /// <summary>
    /// Creates a hash from a password with 10000 iterations
    /// </summary>
    /// <param name="password">The password.</param>
    /// <returns>The hash.</returns>
    public static string Hash(string password)
    {
        return Hash(password, 10000);
    }

    /// <summary>
    /// Checks if hash is supported.
    /// </summary>
    /// <param name="hashString">The hash.</param>
    /// <returns>Is supported?</returns>
    public static bool IsHashSupported(string hashString)
    {
        return hashString.Contains("HASH|V1$");
    }

    /// <summary>
    /// Verifies a password against a hash.
    /// </summary>
    /// <param name="password">The password.</param>
    /// <param name="hashedPassword">The hash.</param>
    /// <returns>Could be verified?</returns>
    public static bool Verify(string password, string hashedPassword)
    {
        // Check hash
        if (!IsHashSupported(hashedPassword))
        {
            throw new NotSupportedException("The hashtype is not supported");
        }

        // Extract iteration and Base64 string
        var splittedHashString = hashedPassword.Replace("$HASH|V1$", "").Split('$');
        var iterations = int.Parse(splittedHashString[0]);
        var base64Hash = splittedHashString[1];

        // Get hash bytes
        var hashBytes = Convert.FromBase64String(base64Hash);

        // Get salt
        var salt = new byte[SaltSize];
        Array.Copy(hashBytes, 0, salt, 0, SaltSize);

        // Create hash with given salt
        using (var pbkdf2 = new Rfc2898DeriveBytes(password, salt, iterations))
        {
            byte[] hash = pbkdf2.GetBytes(HashSize);

            // Get result
            for (var i = 0; i < HashSize; i++)
            {
                if (hashBytes[i + SaltSize] != hash[i])
                {
                    return false;
                }
            }

            return true;
        }

    }
}

ব্যবহার:

// Hash
var hash = SecurePasswordHasher.Hash("mypassword");

// Verify
var result = SecurePasswordHasher.Verify("mypassword", hash);

0

আমি মনে করি কী-ডেরিভেশন.পিবিকেডিএফ 2 ব্যবহার করা আরএফসি 2898 ডেরিভাইটসের চেয়ে ভাল।

উদাহরণ এবং ব্যাখ্যা: এএসপি.নেট কোরটিতে হ্যাশ পাসওয়ার্ড

using System;
using System.Security.Cryptography;
using Microsoft.AspNetCore.Cryptography.KeyDerivation;
 
public class Program
{
    public static void Main(string[] args)
    {
        Console.Write("Enter a password: ");
        string password = Console.ReadLine();
 
        // generate a 128-bit salt using a secure PRNG
        byte[] salt = new byte[128 / 8];
        using (var rng = RandomNumberGenerator.Create())
        {
            rng.GetBytes(salt);
        }
        Console.WriteLine($"Salt: {Convert.ToBase64String(salt)}");
 
        // derive a 256-bit subkey (use HMACSHA1 with 10,000 iterations)
        string hashed = Convert.ToBase64String(KeyDerivation.Pbkdf2(
            password: password,
            salt: salt,
            prf: KeyDerivationPrf.HMACSHA1,
            iterationCount: 10000,
            numBytesRequested: 256 / 8));
        Console.WriteLine($"Hashed: {hashed}");
    }
}
 
/*
 * SAMPLE OUTPUT
 *
 * Enter a password: Xtw9NMgx
 * Salt: NZsP6NnmfBuYeJrrAKNuVQ==
 * Hashed: /OOoOer10+tGwTRDTrQSoeCxVTFr6dtYly7d0cPxIak=
 */

এটি নিবন্ধের একটি নমুনা কোড। এবং এটি ন্যূনতম সুরক্ষা স্তর। এটি বাড়াতে আমি কী-ডেরিভেশনপ্রফ.এইচএমএএসএইচএসএ 1 পরামিতির পরিবর্তে ব্যবহার করব

কীডেরিভিশনপ্রিফ.এইচএমএএসএএসএইচ 256 বা কীডেরিভিশনপ্রিফ। এইচএমএএসএএসএএসএ5512।

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

যোগ করার জন্য আরও একটি পয়েন্ট

হ্যাশ যাচাইকরণে সময় লাগে (এবং এটি ভাল)। যখন ব্যবহারকারী ভুল ব্যবহারকারীর নাম প্রবেশ করে তখন ব্যবহারকারীর নামটি ভুল কিনা তা যাচাই করতে সময় লাগে না। যখন ব্যবহারকারীর নামটি সঠিক হয় আমরা পাসওয়ার্ড যাচাই শুরু করি - এটি তুলনামূলকভাবে দীর্ঘ প্রক্রিয়া।

একজন হ্যাকারের পক্ষে এটি বোঝা খুব সহজ হবে যে ব্যবহারকারীর উপস্থিতি আছে কি নেই।

ব্যবহারকারীর নাম ভুল হলে অবিলম্বে উত্তর না ফেরানোর বিষয়টি নিশ্চিত করুন।

বলা বাহুল্য: কোনটি ভুল তা কখনই উত্তর দেবেন না। কেবল সাধারণ "শংসাপত্রগুলি ভুল"।


1
বিটিডাব্লু, পূর্ববর্তী উত্তর stackoverflow.com/a/57508528/11603057 সঠিক এবং ক্ষতিকারক নয়। এটি হ্যাশিংয়ের উদাহরণ, পাসওয়ার্ড হ্যাশিং নয়। কী ডেরাইভেশন প্রক্রিয়া চলাকালীন সিউডো-র্যান্ডম ফাংশনটির পুনরাবৃত্তি হওয়া আবশ্যক। এমন কিছু নেই. আমি এটি মন্তব্য করতে বা ডাউনটোট করতে পারি না (আমার নিম্ন খ্যাতি)। অনুচিত উত্তর মিস করবেন না দয়া করে!
অ্যালবার্ট লুবারস্কি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.