public bool VerifyHashedPassword(byte[] decodedHashedPassword, string providedPassword)
        {
            var paddingMode = (PaddingMode)BufferUtil.ReadNetworkByteOrder(decodedHashedPassword, 1);
            var cipherMode  = (CipherMode)BufferUtil.ReadNetworkByteOrder(decodedHashedPassword, 5);

            var salt = new byte[32];

            Buffer.BlockCopy(decodedHashedPassword, 9, salt, 0, salt.Length);
            var iv = new byte[16];

            Buffer.BlockCopy(decodedHashedPassword, 9 + salt.Length, iv, 0, iv.Length);
            var expectedKey = new byte[decodedHashedPassword.Length - salt.Length - iv.Length - 9];

            Buffer.BlockCopy(decodedHashedPassword, 9 + salt.Length + iv.Length, expectedKey, 0, expectedKey.Length);

            var cipher = Aes.Create();

            cipher.KeySize = 256;
            cipher.Padding = paddingMode;
            cipher.Mode    = cipherMode;
            cipher.Key     = salt;
            cipher.IV      = iv;

            var decryptor             = cipher.CreateDecryptor();
            var expectedPasswordBytes = decryptor.TransformFinalBlock(expectedKey, 0, expectedKey.Length);
            var expectedPassword      = Encoding.UTF8.GetString(expectedPasswordBytes);

            return(providedPassword.Equals(expectedPassword));
        }
Example #2
0
        public bool VerifyHashedPassword(byte[] decodedHashedPassword, string providedPassword)
        {
            // Read header information
            var prf        = (KeyDerivationPrf)BufferUtil.ReadNetworkByteOrder(decodedHashedPassword, 1);
            var iterCount  = (int)BufferUtil.ReadNetworkByteOrder(decodedHashedPassword, 5);
            var saltLength = (int)BufferUtil.ReadNetworkByteOrder(decodedHashedPassword, 9);

            // Read the salt: must be >= 128 bits
            if (saltLength < 128 / 8)
            {
                return(false);
            }
            var salt = new byte[saltLength];

            Buffer.BlockCopy(decodedHashedPassword, 13, salt, 0, salt.Length);

            // Read the subkey (the rest of the payload): must be >= 128 bits
            var subkeyLength = decodedHashedPassword.Length - 13 - salt.Length;

            if (subkeyLength < 128 / 8)
            {
                return(false);
            }
            var expectedSubkey = new byte[subkeyLength];

            Buffer.BlockCopy(decodedHashedPassword, 13 + salt.Length, expectedSubkey, 0, expectedSubkey.Length);

            // Hash the incoming password and verify it
            var actualSubKey = KeyDerivation.Pbkdf2(providedPassword, salt, prf, iterCount, subkeyLength);

            return(iterCount > 0 && BufferUtil.ByteArraysEqual(actualSubKey, expectedSubkey));
        }