我正在尝试创建类似于基本随机密码生成器的内容,包括大写,小写和数字 - 但由于某种原因,这
static void Main(string[] args)
{
bool validLength = false;
int userDefinedLength = 0;
Console.WriteLine("How many characters would you like your password to be?");
do
{
try
{
userDefinedLength = int.Parse(Console.ReadLine());
validLength = true;
if (userDefinedLength < 3)
{
Console.WriteLine("Please enter something larger than 3.");
validLength = false;
}
}
catch (Exception)
{
Console.WriteLine("Please input a valid integer length.");
}
} while (validLength == false);
char[] passwordArray = new char[userDefinedLength];
int asciiValue = 0;
char asciiChar = ' ';
bool validPassword = false;
Random ranAsciiGroup = new Random();
Random ascValue = new Random();
do
{
for (int i = 0; i < passwordArray.Length; i++)
{
int randomAsc = 0;
randomAsc = ranAsciiGroup.Next(1, 4);
//Console.WriteLine(randomAsc);
if (randomAsc == 1)
{
asciiValue = ascValue.Next(65, 91);
//Console.WriteLine(asciiValue);
}
else if (randomAsc == 2)
{
asciiValue = ascValue.Next(97, 123);
//Console.WriteLine(asciiValue);
}
else if (randomAsc == 3)
{
asciiValue = ascValue.Next(48, 58);
//Console.WriteLine(asciiValue);
}
asciiChar = (char)asciiValue;
passwordArray[i] = asciiChar;
//validPassword = true;
}
bool isDigit = false;
bool isUpper = false;
bool isLower = false;
for (int i = 0; i < passwordArray.Length; i++)
{
if (char.IsDigit(passwordArray[i]))
{
isDigit = true;
}
if (char.IsUpper(passwordArray[i]))
{
isUpper = true;
}
if (char.IsLower(passwordArray[i]))
{
isLower = true;
}
}
if (isDigit == true && isUpper == true && isLower == true)
{
validPassword = true;
}
} while (validPassword == false);
Console.WriteLine("Your password is...");
Console.ForegroundColor = ConsoleColor.DarkGreen;
foreach (char c in passwordArray)
{
Console.Write(c);
}
Console.ReadLine();
}
它产生的密码似乎没有使用任何小于6的数字。它产生的一些字符非常重复 - 例如小写字母往往具有比其他字符更多的字符 - 或者根本不显示的字符。我将在这里留下100个字符的例子。
m9nj88m8GBpF7Hk87E8p9CAE987pEj7pm7j89iHplo7DIpB87B9irlAk9Ik9C8q8i97B9o8l8GDjj88j898Dmk9A69969Ino988I
答案 0 :(得分:2)
种子RNG
不要忘记播种随机的实例,例如
var random = new System.Random(Environment.TickCount);
此外,一个实例应该足够了。
消除重复
如果您希望确保表示所有字符,您可以使用其他随机选择技术。例如,您可以生成一个非常长的字符串,其中包含您想要的所有字符,随机排序,然后获取第一个 n 字符。这种方法可以完全消除重复的字符并保证最终使用每个字符。例如:
using System;
using System.Linq;
public class Program
{
static readonly Random _random = new System.Random(Environment.TickCount);
const string dictionary = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklpmnopqrstuvwxyz0123456789!@#$%^&*()_+-=";
static string GetPassword(int length)
{
return new String
(
dictionary
.OrderBy( a => _random.NextDouble() )
.Take(length)
.ToArray()
);
}
public static void Main()
{
var s = GetPassword(30);
Console.WriteLine(s);
}
}
在这个例子中,我们将字符串视为Enumerable<char>
(是的,这是允许的)并使用LINQ方法对其进行随机排序并获取第一个 n 字符。然后,我们将结果传递给包含答案的新System.String
的构造函数。
示例输出:
运行#1:
!#t(hfTz0rB5cvKy1d$oeVI2mnsCba
运行#2:
y7Y(MB1pWH$wO5XPD0b+%Rkn9a4F!_
运行#3:
tH92lnh*sL+WOaTYR160&xiZpC5@G3
对我来说很随意。
受控重复
上述解决方案当然只允许字典中每个字符的一个实例。但也许你希望它们能够出现不止一次,但不能太多。如果您想要受控制的,有限数量的可能重复,您可以进行一些小改动:
static string GetPassword(int length, int maxRepeats)
{
return new String
(
Enumerable.Range(0, maxRepeats)
.SelectMany( i => dictionary )
.OrderBy( a => _random.NextDouble() )
.Take(length)
.ToArray()
);
}
在此示例中,我们克隆字典maxRepeats
次并使用SelectMany
连接它们。然后我们随机排序这个巨大的字符串,并将第一个 n 字符作为密码。
答案 1 :(得分:0)
System.Random
类并非设计为强RNG,它被设计为快速RNG。如果您需要高质量的随机数生成器,则需要使用基于System.Security.Cryptography.RandomNumberGenerator
类的生成器。
Here is a gist I found使用加密随机生成器作为现有随机类的内部。
运行它with the new generator给了我
您可以看到的mm77D5EDjO0OhOOe8kppiY0toc0HWQjpo37b4LFj56LvcQvA4jE83J8BS8xeX6zcEr2Od8A70v2xFKiY0ROY3gN105rZt6PE8F2i
似乎没有您找到的偏见。