Esempio n. 1
0
        /// <summary>
        /// Generates a password string with a specified length
        /// </summary>
        /// <param name="length">Length of the password that will be generated</param>
        /// <param name="generationFlags">Configuration for the password generation</param>
        /// <returns>The generated password</returns>
        public static string GeneratePassword(int length, PasswordGenerationFlags generationFlags = PasswordGenerationFlags.Default)
        {
            if (length <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            // Build character set
            string[] charSets = BuildCharacterSet(generationFlags).ToArray();
            if (charSets.Length == 0)
            {
                throw new ArgumentException("No char sets selected.", nameof(generationFlags));
            }
            if (length < charSets.Length)
            {
                throw new ArgumentException("Password length is too small to contain characters form all selected sets.", nameof(generationFlags));
            }

            // Use cryptographically safe random number generator
            using (var randomNumberGenerator = RandomNumberGenerator.Create())
            {
                // Generate random numbers
                var randomBytes = new byte[length];
                randomNumberGenerator.GetBytes(randomBytes);

                // Select generation method
                if (generationFlags.HasFlag(PasswordGenerationFlags.EquallyDistributed))
                {
                    int fullCharSetLength = charSets.Sum(charSet => charSet.Length);

                    // collect characters from the different char sets
                    var charCollector = new StringBuilder(length);
                    for (int i = 0; i < charSets.Length; i++)
                    {
                        string charSet          = charSets[i];
                        int    charsFromThisSet = i == charSets.Length - 1 ? length - charCollector.Length : (int)Math.Round((double)charSet.Length / fullCharSetLength * length);
                        for (int j = 0; j < charsFromThisSet; j++)
                        {
                            charCollector.Append(GetRandomCharFromCharSet(charSet, randomBytes[charCollector.Length]));
                        }
                    }

                    // shuffle characters
                    return(ShuffleCharacters(charCollector.ToString(), randomNumberGenerator));
                }
                else
                {
                    // Combine available characters to one single character set
                    string fullCharSet = ShuffleCharacters(string.Join(string.Empty, charSets), randomNumberGenerator);

                    // Build random password
                    return(new string(randomBytes.Select(number => GetRandomCharFromCharSet(fullCharSet, number)).ToArray()));
                }
            }
        }
        public void GeneratedPasswordsAreDifferent(PasswordGenerationFlags flags)
        {
            string lastPassword = null;

            for (int i = 0; i < 100; i++)
            {
                string password = Secrets.GeneratePassword(100, flags);
                Assert.Equal(100, password.Length);
                if (lastPassword == password)
                {
                    throw new XunitException("Duplicate detected.");
                }
                lastPassword = password;
            }
        }
Esempio n. 3
0
        private static IEnumerable <string> BuildCharacterSet(PasswordGenerationFlags generationFlags)
        {
            bool readable = generationFlags.HasFlag(PasswordGenerationFlags.ReadableCharSet);

            if (generationFlags.HasFlag(PasswordGenerationFlags.WithNumbers))
            {
                yield return(readable ? "23456789" : "1234567890");
            }

            if (generationFlags.HasFlag(PasswordGenerationFlags.WithUpperCaseChars))
            {
                yield return(readable ? "ABCDEFGHKLMNPQRSTUVWXYZ" : "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
            }

            if (generationFlags.HasFlag(PasswordGenerationFlags.WithLowerCaseChars))
            {
                yield return(readable ? "abcdefghkmnpqrstuvwxyz" : "abcdefghijklmnopqrstuvwxyz");
            }
        }