Example #1
0
        /// <summary>
        /// Creates a new instance of <see cref="PasswordHasher"/>.
        /// </summary>
        public PasswordHasher()
        {
            var options = new PasswordHasherOptions();

            rng       = RandomNumberGenerator.Create();
            iterCount = options.IterationCount;
            symKey    = new RijndaelManaged
            {
                Mode    = CipherMode.CBC,
                Padding = PaddingMode.PKCS7
            };
        }
Example #2
0
        public void OptionsRoundTrip(PasswordHasherAlgorithms algorithm, int expectedSize)
        {
            // Arrange
            var options = new PasswordHasherOptions(algorithm);

            // Act & assert - success case
            Assert.Equal(expectedSize, options.HashSize);

            // Arrange
            options.HashAlgorithm = PasswordHasherAlgorithms.SHA1;
            options.SaltSize      = expectedSize;
            options.HashAlgorithm = algorithm;

            // Act & assert - failure case
            Assert.Equal(expectedSize, options.HashSize);
        }
Example #3
0
        public static IOptions <PasswordHasherOptions> BuildOptions(int?saltSize = null, int?iterations = null)
        {
            var options = new PasswordHasherOptions();

            if (saltSize.HasValue)
            {
                options.SaltSize = saltSize.Value;
            }

            if (iterations.HasValue)
            {
                options.Iterations = iterations.Value;
            }

            return(Options.Create(options));
        }
        public PasswordHasher(IOptions <PasswordHasherOptions> options = null)
        {
            if (options == null)
            {
                options = Options.Create(new PasswordHasherOptions());
            }
            _options = options.Value;
            switch (_options.Version)
            {
            case PasswordHasherVersion.V1:
                _hasher = new PassowrdHasherV1(this);
                break;

            default:
                break;
            }
        }
        /// <summary>
        /// Resets all options back to default. This should generally not be called after the application sets Application specific options.
        /// </summary>
        public static void ResetDefaults()
        {
            //////////////////////////////////////////////////////////
            // Hasher Initialize
            //////////////////////////////////////////////////////////
            HasherOptions = new HasherOptions()
            {
                HashFingerprintLowercase = true,
                Salt    = "GLOBALSALT_902834vtn029384ytv20384tyvb13084tyv1b08ty1084vn",
                UseSalt = false
            };

            //////////////////////////////////////////////////////////
            // PasswordHasher Initialize
            //////////////////////////////////////////////////////////
            PasswordHasherOptions = new PasswordHasherOptions()
            {
                // NOTE: Changing these Value will break existing encrypted data.
                //		 These are defaults only. It is recommended that each Application
                //		create a custom Salt for individual security
                Salt        = "6c5573acf3177dd019aa3cc3349349370d27b472744a9e5ed7a0385f686cdbb3fdba9d79b88a0b2a500543d5375a20e25177cf65c493f7a9a65dab85c9d71bab",
                PepperChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqurtuvwxyz0123456789!@#$%^&*()_+?><:"
            };

            //////////////////////////////////////////////////////////
            // SymmetricEncryptorOptions Initialize
            //////////////////////////////////////////////////////////
            SymmetricEncryptorOptions = new SymmetricEncryptorOptions()
            {
                // NOTE: Changing these Value will break existing encrypted data.
                //		 These are defaults only. It is recommended that each Application
                //		create a custom Salt for individual security
                Salt = "13c035d5c0b55becec39f3cf6c8adc81c5db5818f8e4fc537d5cccd805df2b5bfb22c43d6846e50b364794d2784fbb90922e9c62882f464385162186f6035168",
                HashFingerprintLowercase = true,
                InitializationVector     = "29C7B95FA4B76027B183EF75A10325D40AFF4FA5D444C45BEE714CBFDF92EE6C1D5E0D82D190B714AD5EEF0AC947C19596DF460F6F154C4A0C85EF39F95A2F8E",
                KeySalt = "72E7D56BAD8C4377C1E57E29EEE9BB0AD218D898EA3714F175702AD5D0E507873257B5B429624A8E406435CC8BBDD89194F5E0A42E92C5FA061D881B972FC56B",
                IVSalt  = "F755FC686D4F2DA387D54F92B9C70CCF1B267B525A5DED28B8504C03A56E1B47EA33BFDC3C241041469AA28C0732A66671D7A8A51FCEBD6FE3B72758CDC2EC63",
            };
        }
        /// <summary>
        /// Derives a key from the specified password.
        /// </summary>
        /// <param name="password">The password.</param>
        /// <param name="options">The options.</param>
        /// <returns></returns>
        /// <exception cref="ArgumentExcetption">If the given hash lengh exceeds the lenght defined in the rfc standard</exception>
        public override string Compute(string password, PasswordHasherOptions options)
        {
            throw new NotSupportedException();

            // create a new HMAC
            HMAC hmac = HMACFactory.CreateInstance(options.HashType);
            ulong hLen = Convert.ToUInt64(hmac.HashSize / 8);
            ulong dkLen = Convert.ToUInt64(options.HashSize);

            // sanity check, section 5.2 in rfc standard.
            ulong maxLength = UInt32.MaxValue * hLen;
            if (options.HashSize > maxLength)
            {
                throw new ArgumentException("Provided hash length is too big for the current options, it violates the rfc standard");
            }

            // algorithm start
            uint byteBlocks = Convert.ToUInt32(Math.Ceiling( (decimal)options.HashSize / (decimal)hLen));
            uint bytesInLastBlock = Convert.ToUInt32(dkLen - (byteBlocks - 1) * hLen);
            IList<byte[]> blocks = new List<byte[]>();

            // the algorithm is 1 based in the RFC, so add a dummy byte at index 0
            blocks.Add(new byte[0]);
            for (uint i = 1; i <= byteBlocks; i++)
            {
                byte[] current = F(password, options.Salt, Convert.ToUInt32(Math.Pow(2.0d, options.WorkFactor)), i, options.HashType, hLen);
                blocks.Add(current);
            }

            // copy all blocks except the last one into the resulting hash
            ulong resultingHashSize = byteBlocks * hLen;
            if (byteBlocks > 1)
            {
                resultingHashSize += bytesInLastBlock;
            }

            byte[] resultingHash = new byte[resultingHashSize];
            int startIndex = 0;
            for (uint i = 1; i < blocks.Count-1; i++)
            {
                byte[] current = blocks[(int)i];
                startIndex = Convert.ToInt32((i - 1) * hLen);
                current.CopyTo(resultingHash, startIndex);
            }

            // copy "bytesInLastBlock" bytes into the resulting hash
            byte[] last = blocks[blocks.Count-1];
            for (int i = 0; i < bytesInLastBlock; i++)
            {
                resultingHash[startIndex] = last[i];
                startIndex++;
            }

            string encodedHash = String.Format("$9d${0}${1}${2}",
                                              	options.WorkFactor.ToString().PadLeft(2, '0'),
                                               Convert.ToBase64String(options.Salt),
                                               Convert.ToBase64String(resultingHash));

            hmac.Clear();
            return encodedHash;
        }
 /// <summary>
 /// Defines the password hasher options.
 /// </summary>
 /// <param name="options">The password hasher options</param>
 public static void PasswordHasher(PasswordHasherOptions options)
 {
     options.IterationCount = 12000;
 }
 /// <summary>
 /// Derives a key from the specified password.
 /// </summary>
 /// <param name="password">The password.</param>
 /// <param name="options">The options.</param>
 /// <returns></returns>
 public abstract string Compute(string password, PasswordHasherOptions options);
Example #9
0
 public PasswordOptions()
 {
     Hasher     = new PasswordHasherOptions();
     Validation = new PasswordValidationOptions();
 }
        public void UpdateMasterKey()
        {
            HashEncryptionParameters encryption1 = new(123, HashEncryptionAlgorithm.AES128, new byte[] { 43, 12, 64, 63, 1, 6, 74, 123, 4, 15, 11, 84, 26, 125, 11, 6 });
            HashEncryptionParameters encryption2 = new(456, HashEncryptionAlgorithm.AES128, new byte[] { 44, 12, 64, 63, 1, 6, 74, 123, 4, 15, 11, 84, 26, 125, 11, 6 });

            var options1 = new PasswordHasherOptions {
                EncryptionParameters = encryption1,
            };

            var options2_0 = new PasswordHasherOptions {
                EncryptionParameters = encryption2,
            };

            var options2_1 = new PasswordHasherOptions {
                EncryptionParameters       = encryption2,
                LegacyEncryptionParameters = { encryption1 },
            };

            var hasher = new PasswordHasher(PasswordHashAlgorithm.SHA512, 1000);

            string hash = hasher.Hash(Password);

            Assert.IsTrue(hasher.Verify(hash, Password));
            Assert.IsFalse(hasher.Verify(hash, NotThePassword));

            var hasher1 = new PasswordHasher(PasswordHashAlgorithm.SHA512, 1000, options1);

            Assert.IsTrue(hasher1.RequiresUpdate(hash));

            string hash1 = hasher1.Update(hash) !;

            Assert.AreNotEqual(hash1, hash);

            Assert.IsTrue(hasher1.Verify(hash1, Password));
            Assert.IsFalse(hasher1.Verify(hash1, NotThePassword));
            Assert.ThrowsException <FormatException>(() => hasher.Verify(hash1, Password));

            var hasher2_0 = new PasswordHasher(PasswordHashAlgorithm.SHA512, 1000, options2_0);

            Assert.IsTrue(hasher2_0.RequiresUpdate(hash));
            Assert.ThrowsException <FormatException>(() => hasher2_0.RequiresUpdate(hash1));

            string hash2_0 = hasher2_0.Update(hash) !;

            Assert.IsTrue(hasher2_0.Verify(hash2_0, Password));
            Assert.IsFalse(hasher2_0.Verify(hash2_0, NotThePassword));
            Assert.ThrowsException <FormatException>(() => hasher2_0.Update(hash1));

            var hasher2_1 = new PasswordHasher(PasswordHashAlgorithm.SHA512, 1000, options2_1);

            Assert.IsTrue(hasher2_1.RequiresUpdate(hash));
            Assert.IsTrue(hasher2_1.RequiresUpdate(hash1));

            string hash2_1 = hasher2_1.Update(hash1) !;

            Assert.AreNotEqual(hash2_1, hash2_0); // AES IV values should be different for each encryption
            Assert.AreNotEqual(hash2_1, hash1);

            Assert.IsTrue(hasher2_1.Verify(hash, Password));
            Assert.IsTrue(hasher2_1.Verify(hash1, Password));
            Assert.IsTrue(hasher2_1.Verify(hash2_1, Password));

            Assert.IsFalse(hasher2_1.Verify(hash, NotThePassword));
            Assert.IsFalse(hasher2_1.Verify(hash1, NotThePassword));
            Assert.IsFalse(hasher2_1.Verify(hash2_1, NotThePassword));
        }
Example #11
0
        public static IOptions <PasswordHasherOptions> BuildOptions(PasswordHasherAlgorithms algorithm, int?saltSize = null, int?iterations = null)
        {
            var options = new PasswordHasherOptions(algorithm, saltSize, iterations);

            return(Options.Create(options));
        }
        public override string Compute(string password, PasswordHasherOptions options)
        {
            string encodedHash = BCrypt.HashPassword(password, (int)options.WorkFactor );

            return encodedHash;
        }