C# Random Password Generator

2019-04-28 13:43发布

问题:

Here is the code: (passwordLengthBox is a NumericUpDown Box, r and k are random numbers)

    private void generateButton_Click(object sender, EventArgs e)
            {
                int r, k;
                int passwordLength = (Int32)passwordLengthBox.Value;
                string password = "";
                char[] upperCase = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
                char[] lowerCase = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' };
                int[] numbers = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
                Random rRandom = new Random();



                for (int i = 0; i < passwordLength; i++)
                {
                    r = rRandom.Next(3);

                    if (r == 0)
                    {
                        k = rRandom.Next(0, 25);
                        password += upperCase[k];
                    }

                    else if (r == 1)
                    {
                        k = rRandom.Next(0, 25);
                        password += lowerCase[k];
                    }

                    else if (r == 2)
                    {
                        k = rRandom.Next(0, 9);
                        password += numbers[k];
                    }

                }

                textBox.Text = password;
            }

What this program does is to create a random password with letters (both upper case and lower case) and numbers at the length that I choose. The problem is that the program does not make the password length as I chose.

For example: if I type 5 in the NumericUpDown Box (passwordLengthBox) that sets the Password Length sometimes its giving me passwords that are 5 chars long and sometime 6/7/8 chars long passwords.

What is my mistake?

回答1:

Problem is here:

int[] numbers = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };

With that declaration every time a number is appended into password it is taken as ASCII number, not a real value. So you're adding integers from 48 to 57, what makes result string longer then expected.

e.g. when 6 is generated as a random number, you're appending something like: ((int)'6').ToString() into your password variable, what actually adds 54 instead of 6.

Declare that array as char[] and it will works fine.



回答2:

You could try this little method instead instead.

public static string Random(int length)
{
    try
    {
        byte[] result = new byte[length];
        for (int index = 0; index < length; index++)
        {
            result[index] = (byte)new Random().Next(33, 126);
        }
        return System.Text.Encoding.ASCII.GetString(result);
     }
     catch (Exception ex)
     {
        throw new Exception(ex.Message, ex);
     }
}

The only difference with this is that it will use alphanumeric chars too, for example it may generate strings like f6Dx3$5d£4hG7

take a look at www.asciitable.com and work out the character range you want to use.

For Nathan, here is another way you could do it, if you know exactly which characters you want...

public static string Random(int length)
{
    string allowed = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    return new string(allowed
        .OrderBy(o => Guid.NewGuid())
        .Take(length)
        .ToArray());
}


回答3:

Here is a slight improvement on the answer from series0ne. That answer gave a password with the same character. (e.g. %%%%%)

        var random = new Random((int) DateTime.Now.Ticks);
        try
        {
            var result = new byte[length];
            for (var index = 0; index < length; index++)
            {
                result[index] = (byte) random.Next(33, 126);
            }
            return System.Text.Encoding.ASCII.GetString(result);
        }
        catch (Exception ex)
        {
            throw new Exception(ex.Message, ex);
        }


回答4:

Here My Complete Function to generate random password with desired length (thanks to Viacheslav Smityukh)

    private String GeneratePassword(int genlen = 21, bool usenumbers = true, bool uselowalphabets = true, bool usehighalphabets = true, bool usesymbols = true)
    {

        var upperCase = new char[]
            {
                'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
                'V', 'W', 'X', 'Y', 'Z'
            };

        var lowerCase = new char[]
            {
                'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u',
                'v', 'w', 'x', 'y', 'z'
            };

        var numerals = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };

        var symbols = new char[]
            {
                '~', '`', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '{', '[', '}', ']', '-', '_', '=', '+', ':',
                ';', '|', '/', '?', ',', '<', '.', '>'
            };

        char[] total = (new char[0])
                        .Concat(usehighalphabets ? upperCase : new char[0])
                        .Concat(uselowalphabets ? lowerCase : new char[0])
                        .Concat(usenumbers ? numerals : new char[0])
                        .Concat(usesymbols ? symbols : new char[0])
                        .ToArray();

        var rnd = new Random();

        var chars = Enumerable
            .Repeat<int>(0, genlen)
            .Select(i => total[rnd.Next(total.Length)])
            .ToArray();

        return new string(chars);
    }


回答5:

You can try the following code:

var numberOfChars = 6;

var upperCase = new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
var lowerCase = new char[] { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' };
var numbers = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
var rnd = new Random();

var total = upperCase
    .Concat(lowerCase)
    .Concat(numbers)
    .ToArray();

var chars = Enumerable
    .Repeat<int>(0, numberOfChars)
    .Select(i => total[rnd.Next(total.Length)])
    .ToArray();

var result = new string(chars);