/// <summary>
        /// Compares a hash, salt and plain password and sets IsValid
        /// </summary>
        public SecuredPassword(string plainPassword, byte[] hash, byte[] salt, HashStrategyKind hashStrategy)
        {
            _hash = hash;
            _salt = salt;
            SetHashStrategy(hashStrategy);
            byte[] newKey;
            switch (hashStrategy)
            {
            case HashStrategyKind.Pbkdf210001Iterations:
                var numberOfIterations = (int)_hashingParameter;
                if (numberOfIterations <= 10000)
                {
                    throw new ArgumentException("Iterations must be greater than 10000");
                }
                using (var deriveBytes = new Rfc2898DeriveBytes(plainPassword, salt, numberOfIterations, HashAlgorithmName.SHA256))
                {
                    newKey  = deriveBytes.GetBytes(_saltSize);
                    IsValid = newKey.SequenceEqual(hash);
                }
                break;

            case HashStrategyKind.Argon2WorkCost:
                SecureArray <byte> hashB = null;
                try
                {
                    var passwordBytes            = Encoding.ASCII.GetBytes(plainPassword);
                    var configOfPasswordToVerify = new Argon2Config
                    {
                        Type       = Argon2Type.DataIndependentAddressing,
                        Version    = Argon2Version.Nineteen,
                        TimeCost   = 10,
                        MemoryCost = (int)_hashingParameter,
                        Lanes      = 5,
                        Threads    = Environment.ProcessorCount,
                        Salt       = _salt,
                        Password   = passwordBytes,
                        HashLength = 20
                    };
                    var hashString = Encoding.ASCII.GetString(_hash);
                    if (configOfPasswordToVerify.DecodeString(hashString, out hashB) && hashB != null)
                    {
                        var argon2ToVerify = new Argon2(configOfPasswordToVerify);
                        using (var hashToVerify = argon2ToVerify.Hash())
                        {
                            if (!hashB.Buffer.Where((b, i) => b != hashToVerify[i]).Any())
                            {
                                IsValid = true;
                            }
                        }
                    }
                }
                finally
                {
                    hashB?.Dispose();
                }
                break;
            }
        }
Exemple #2
0
        internal static ObjectResult VerifyUser(string username, string password)
        {
            if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password))
            {
                return(new InvalidResult("Error: Username/Password are required."));
            }

            try
            {
                var result = from user in context.users
                             where user.username == username
                             select user;

                if (result.Count() == 0)
                {
                    return(new NotFoundResult("Error: User does not exist."));
                }

                string passwordHash = result.First().passwordHash;
                bool?  isAdmin      = result.First().isAdmin;
                //START CODE BLOCK
                //-- Code within used from
                //https://github.com/mheyman/Isopoh.Cryptography.Argon2/blob/master/README.md
                Argon2Config config = new Argon2Config
                {
                    Type       = Argon2Type.DataIndependentAddressing,
                    Version    = Argon2Version.Nineteen,
                    TimeCost   = 3,
                    MemoryCost = 32768,
                    Lanes      = 4,
                    Threads    = Environment.ProcessorCount,
                    Password   = Encoding.ASCII.GetBytes(password),
                    Salt       = Convert.FromBase64String(Properties.Settings.Default.Salt),
                    HashLength = 20
                };
                SecureArray <byte> hashB = null;
                try
                {
                    if (config.DecodeString(passwordHash, out hashB) && hashB != null)
                    {
                        var argon2ToVerify = new Argon2(config);
                        using (var hashToVerify = argon2ToVerify.Hash())
                        {
                            if (!hashB.Buffer.Where((b, i) => b != hashToVerify[i]).Any())
                            {
                                return(new OkResult(isAdmin.ToString()));
                            }
                            else
                            {
                                return(new WrongResult("Error: Username/Password is incorrect."));
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    return(new InvalidResult("Error: Failed to verify password."));
                }
                finally
                {
                    hashB?.Dispose();
                }
                //END CODE BLOCK
            }
            catch (Exception ex)
            {
                return(new InvalidResult("Error: Failed retrieving data from the database."));
            }
            return(new InvalidResult("Error: Failed to process verification."));
        }