Verify() 공개 메소드

Hashes the raw password bytes and verifies that the password results in the specified hash. The ArgonType must of this PasswordHasher object must match what was used to generate expectedHash. The other parameters (timeCost, etc.) do not need to match and the parameters embedded in the expectedHash will be used. Hashing the password should result in this hash The raw password bytes to hash and compare its result to expectedHash Whether the password results in the expectedHash when hashed
public Verify ( string expectedHash, byte password ) : bool
expectedHash string
password byte
리턴 bool
예제 #1
0
        private static void Run(PasswordHasher hasher, string pwd, string salt, bool rawOnly, bool encodedOnly)
        {
            try
            {
                if (rawOnly)
                {
                    Console.WriteLine(ToHex(hasher.HashRaw(pwd, salt)));
                    return;
                }

                if (encodedOnly)
                {
                    Console.WriteLine(hasher.Hash(pwd, salt));
                    return;
                }

                var    startTime = DateTime.Now;
                string encoded   = hasher.Hash(pwd, salt);
                var    stopTime  = DateTime.Now;

                HashMetadata metadata = PasswordHasher.ExtractMetadata(encoded);

                Console.WriteLine("Hash:\t\t" + ToHex(metadata.Hash));
                Console.WriteLine("Encoded:\t" + encoded);
                Console.WriteLine("{0:0.000} seconds", (stopTime - startTime).TotalSeconds);

                if (hasher.Verify(encoded, pwd))
                {
                    Console.WriteLine("Verification ok");
                }
                else
                {
                    throw new Argon2Exception("verifying", Argon2Error.VERIFY_MISMATCH);
                }
            }
            catch (Exception ex)
            {
                Fatal(ex.Message);
            }
        }
예제 #2
0
        // This code is more complicated than necessary IF you do not care about attackers enumerating your user list via timing attacks
        public ActionResult Login(string username, string password)
        {
            // Do profiling to determine what the optimal time and memory cost would be for your server setup
            // Ideally, PasswordHasher.Hash should take about 200ms to perform as a good balance between security and responsiveness
            // Prefer to increase MemoryCost instead of TimeCost (increasing MemoryCost will also increase the overall time)
            // TODO: Edit your web.config or app.config to contain the following keys within your <configuration><appSettings>...</appSettings></configuration>:
            // TODO: <add key="PasswordHasher.TimeCost" value="3" />
            // TODO: <add key="PasswordHasher.MemoryCost" value="65536" />
            // If you are updating the time cost or memory cost (because, e.g., you moved to faster hardware) then 
            // add PasswordHasher.OldTimeCost and PasswordHasher.OldMemoryCost keys with the previous values to ensure timing attacks cannot
            // be done to enumerate the possible users. Remove OldTimeCost and OldMemoryCost when the migration is finished.

            string timeCostStr = (ConfigurationManager.AppSettings["PasswordHasher.TimeCost"] ?? "3");
            string memoryCostStr = (ConfigurationManager.AppSettings["PasswordHasher.MemoryCost"] ?? "65536");
            uint timeCost = uint.Parse(timeCostStr);
            uint memoryCost = uint.Parse(memoryCostStr);
            uint oldTimeCost = uint.Parse(ConfigurationManager.AppSettings["PasswordHasher.OldTimeCost"] ?? timeCostStr);
            uint oldMemoryCost = uint.Parse(ConfigurationManager.AppSettings["PasswordHasher.OldMemoryCost"] ?? memoryCostStr);

            bool costsDiffer = (timeCost != oldTimeCost || memoryCost != oldMemoryCost);

            string hashFormat = "$argon2i$m={0},t={1},p=1$AAAAAAAAAAAAAAAAAAAAAA$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
            string dummyHash = string.Format(hashFormat, memoryCost, timeCost);
            string oldDummyHash = string.Format(hashFormat, oldMemoryCost, oldTimeCost);

            var passwordHasher = new PasswordHasher(timeCost, memoryCost);
            
            // Get the user from the database in hopefully some constant-time fashion so that timing attacks
            // cannot be used to enumerate valid usernames
            User user = GetUser(username);
            string passwordHash = (user != null ? user.PasswordHash : dummyHash);
            bool updatedCost;
            string newPasswordHash;

            HashMetadata hashMetadata = PasswordHasher.ExtractMetadata(passwordHash);
            bool usingOldCosts = (hashMetadata.MemoryCost != memoryCost || hashMetadata.TimeCost != timeCost);

            // always compare against a password hash even if the user is not found (when that happens, we compare against dummyHash)
            // to prevent timing attacks from enumerating a list of valid usernames
            if (passwordHasher.VerifyAndUpdate(passwordHash, password, out updatedCost, out newPasswordHash))
            {
                // VerifyAndUpdate will generate a new password hash if the time or memory cost from ConfigurationManager.AppSettings
                // does not match what was used to generate the password hash which was stored in the database.
                // This allows you to easily update the password hashing cost if you upgrade to better server hardware by
                // modifying the PasswordHasher.TimeCost and PasswordHasher.MemoryCost parameters.
                if (updatedCost)
                {
                    // As users successfully log in, update their password hash to the hash with the updated cost
                    user.PasswordHash = newPasswordHash;
                    UpdateUser(user);
                }
                else if(costsDiffer)
                {
                    // run the verification with the old costs so that each login attempt performs a hash
                    // with the new costs and with the old costs to ensure the timing is consistent
                    passwordHasher.Verify(oldDummyHash, password);
                }

                // Successful login
                LogInUser(user);
                return RedirectToAction("Index", "Home");
            }

            // if we're migrating password hashes from the old cost parameters to new cost parameters, we want
            // each login attempt to perform a single hash with the new cost parameters and a single hash with
            // the old cost parameters so that the timing is consistent.
            if(costsDiffer)
                passwordHasher.Verify((usingOldCosts ? dummyHash : oldDummyHash), password);

            // User failed to login
            var model = new LoginViewModel {ErrorMessage = "Username or Password is incorrect."};
            return View(model);
        }
예제 #3
0
        private static void Run(PasswordHasher hasher, string pwd, string salt, bool rawOnly, bool encodedOnly)
        {
            try
            {
                if (rawOnly)
                {
                    Console.WriteLine(ToHex(hasher.HashRaw(pwd, salt)));
                    return;
                }

                if (encodedOnly)
                {
                    Console.WriteLine(hasher.Hash(pwd, salt));
                    return;
                }

                var startTime = DateTime.Now;
                string encoded = hasher.Hash(pwd, salt);
                var stopTime = DateTime.Now;
                
                HashMetadata metadata = PasswordHasher.ExtractMetadata(encoded);

                Console.WriteLine("Hash:\t\t" + ToHex(metadata.Hash));
                Console.WriteLine("Encoded:\t" + encoded);
                Console.WriteLine("{0:0.000} seconds", (stopTime - startTime).TotalSeconds);

                if(hasher.Verify(encoded, pwd))
                    Console.WriteLine("Verification ok");
                else
                    throw new Argon2Exception("verifying", Argon2Error.VERIFY_MISMATCH);
            }
            catch (Exception ex)
            {
                Fatal(ex.Message);
            }
        }