6

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?

4
  • Did you check that passwordLength contains the value you entered? Commented Mar 21, 2013 at 9:44
  • 1
    BTW: For clarity you should change the last else if to be just else with a Debug.Assert(r == 2), or add a trailing else that has a Debug.Assert(false) or equivalent. Commented Mar 21, 2013 at 9:52
  • @MatthewWatson There is no chance to get anything but 0, 1 or 2 from random.Next(3), so simple else should be OK. Commented Mar 21, 2013 at 9:54
  • 3
    You can use System.Web.Security.Membership.GeneratePassword(int length, int numberOfNonAlphanumericCharacters) to generate random passwords. Commented Mar 21, 2013 at 10:45

6 Answers 6

14

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.

Sign up to request clarification or add additional context in comments.

1 Comment

@Saurabh using "int[] numbers = {'0' ..." will store ASCII values. Hint is in "int[]"
11

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());
}

7 Comments

Not an answer to this question. It wasn't "how to generate random password".
@HenkHolterman, indeed, however code simplicity can solve problems just as easily.
Need to sleep the thread, provide a different seed, or pull the new Random() outside the loop -- on a fast computer this results in the same character being repeated over and over. Otherwise pretty decent solution.
Is there a way to break up the range of this, result[index] = (byte)random.Next(33, 126);? I need the range to be 48-57, 65-90, and 97-122. Thank you.
@Nathan, see my update...that should do it for you. Since Guid.NewGuid() is (virtually) guaranteed to produce a unique value, it will scramble the allowed characters in the string, and then Take the given length.
|
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);
    }

Comments

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);
        }

Comments

0

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);

Comments

0

Just another option which allows connecting it to a button/textbox to generate passwords of a certain length, hope this is useful to someone, this was thanks to one of the above comments and some extra from me.

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);
            }
        }
        public int control = 1;
        private async void button1_Click(object sender, EventArgs e)
        {
            if (control == 0) { yourPasswordBox.Text = ""; }
            control = Int32.Parse(yourLengthInputBox.Text);
            for (; control > 0;) {
                yourPasswordBox.Text = yourPasswordBox.Text + Random((1));
                await Task.Delay(1);
                control--;
                
            }
            
            
        }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.