Esempio n. 1
0
        /// <summary>
        /// Encrypt a new password.This will also include key derivation value, num bytes, iterations, salt,
        /// </summary>
        /// <returns>
        /// Encrypted value of the password provided.
        /// </returns>
        public static string EncryptNewPassword(EncryptionConfig encrConfig, string password)
        {
            var randomSalt = new byte[16];

            //populate new salt w/ random bytes
            using (RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider())
            {
                rngCsp.GetBytes(randomSalt);
            }

            EncryptionLevelConfig encrLevel = encrConfig.Levels.Find(e => e.Id == encrConfig.CurrentLevel);

            if (encrLevel == null)
            {
                throw new ArgumentNullException($"Encryption Config Level is missing. Check appSettings.json. Current Level: {encrConfig.CurrentLevel}");
            }

            // derive a 256-bit sub key (use HMACSHA256 with 20,000 iterations)
            var hashed = Convert.ToBase64String(KeyDerivation.Pbkdf2(
                                                    password: password,
                                                    salt: randomSalt,
                                                    prf: encrLevel.PRF,
                                                    iterationCount: encrLevel.Iterations,
                                                    numBytesRequested: encrLevel.NumBytes));

            //return

            return($"{((int)encrLevel.Id).ToString()}{_delimiter}" +
                   $"{Convert.ToBase64String(randomSalt)}{_delimiter}" +
                   $"{hashed}");
        }
Esempio n. 2
0
        /// <summary>
        /// Validate an existing password, Pass in the user's existing encoded password (a concatenated string separated by $
        /// with <encryption config id>$<salt>$<hash>). Encrypt the incoming password using the same
        /// settings in the encoded value and see if it matches on the hash
        /// </summary>
        /// <param name="encoded"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public static bool ValidatePassword(EncryptionConfig encrConfig, string encoded, string password, out bool updatePasswordEncryption)
        {
            updatePasswordEncryption = false;
            if (string.IsNullOrEmpty(encoded))
            {
                return(false);
            }
            if (string.IsNullOrEmpty(password))
            {
                return(false);
            }

            string[] passwordParts = encoded.Split(_delimiter);
            if (passwordParts.Length != 3)
            {
                return(false);
            }

            //parse parts into their positions. Then take the plain password and excrypt to see if it matches the hash
            int encrId = Convert.ToInt32(passwordParts[0]);
            EncryptionLevelConfig encrLevel = encrConfig.Levels.Find(e => e.Id == encrId);

            if (encrLevel == null)
            {
                throw new ArgumentNullException($"Encryption Config is missing. Check appSettings.json. Current Level: {encrConfig.CurrentLevel}");
            }

            KeyDerivationPrf prf = (KeyDerivationPrf)Convert.ToInt16(encrLevel.PRF);
            int numBytes         = Convert.ToInt32(encrLevel.NumBytes);
            int iterations       = Convert.ToInt32(encrLevel.Iterations);
            var convertedSalt    = Convert.FromBase64String(passwordParts[1]);

            //perform hash
            var hash = KeyDerivation.Pbkdf2(
                password: password,
                salt: convertedSalt,
                prf: prf,
                iterationCount: iterations,
                numBytesRequested: numBytes);
            var hashed = Convert.ToBase64String(hash);

            //add support to update pw to latest level if current pw was a lower level.
            //have to get UserDAL the new password and it has to save it.
            updatePasswordEncryption = encrConfig.CurrentLevel > encrId;

            //true if they match, existing hash in 3rd position
            return(hashed == passwordParts[2]);
        }