Generating Random Passwords
Asked Answered
E

35

288

When a user on our site loses his password and heads off to the Lost Password page we need to give him a new temporary password. I don't really mind how random this is, or if it matches all the "needed" strong password rules, all I want to do is give them a password that they can change later.

The application is a Web application written in C#. so I was thinking of being mean and going for the easy route of using part of a Guid. i.e.

Guid.NewGuid().ToString("d").Substring(1,8)

Suggesstions? thoughts?

Enthuse answered 10/9, 2008 at 18:45 Comment(3)
A few good solutions here, but a little advice: Don't generate passwords containing any of these characters: Oo0Ili (you see why) :)Allisonallissa
I've added an answer that uses KeePass as a password generator, and of the many options exposed I also included the option to exclude look alike characters, as mentioned by @stian.net.Hallowed
Generate random password online and in some programming languaues.Menace
K
666

There's always System.Web.Security.Membership.GeneratePassword(int length, int numberOfNonAlphanumericCharacters).

Kokoruda answered 10/9, 2008 at 22:44 Comment(19)
Didn't know that the Framework has such a method! Awesome! Will swap out my current code for this!Enthuse
I found it after spending almost a day perfecting my own pw gen code. Image how I felt ;)Kokoruda
AFAIK this method does not generate a password complying to a password policy on the domain so it's not suitable for every usage.Negativism
This works even if you haven't taken a dependency on ASP.NET Membership, but if you've decided to use a different provider, this becomes an awkward choice since it relies in part on other Membership configuration.Discombobulate
The main problem with this solution is that you can't control the character set, so you can't eliminate visually ambiguous characters (0oOl1i!|) which can be really important in practice.Unwise
Any equivalent API for MVC 5.Bronze
Another strange thing is that even when you set the second parameter (numberOfNonAlphanumericCharacters) to 0, you get a password containing parentheses and other punctuation characters. For me alphanumeric means [a-zA-Z0-9].Saddlery
@JennyO'Reilly You're right, a more descriptive parameter name would have been minimumNumberOfAlphaNumericCharacters but that's a little long.Kokoruda
Anything for ASP.NET Core ?Electrothermal
This works in .Net Core, or could work, but it doesn't always generate digits so it fails..Ly
@Ly see my comment from 2016-02-06 above, it's probably the same issue.Kokoruda
Not really, I generated a password with length 15 and min 5 non-alphanumeric characters. However on the first pass (chances are probably pretty slim, but still) it didn't generate a password with number in it. So it failed in Identity, since it needs numbers, letters and non-alphanumeric. Fixed it by adding a number, letter and non-numeric char to the generated password, since it's just a placeholder until the person chooses a real password (required).Ly
What about Core? I can't even compile if I write this and nothing works in using statemtesMarisamariscal
Although the OP states he is using this in a Web application, I think this creates an unneeded dependency on a library that could be supplanted with less than 10 lines of code.Gamages
@Ly It definitely won't work in .NET Core: github.com/PowerShell/PowerShell/issues/5352Puccini
you deserve two trophies if you miss the first one. Good JobTrusteeship
Great answer for .NET Core: https://mcmap.net/q/22178/-alternative-to-system-web-security-membership-generatepassword-in-aspnetcore-netcoreapp1-0Isbella
One lazy but secure thought is to repeat the call until the password fits the requirements. If you don't want certain characters, just ask for a longer password and remove any unwanted characters (ones, zeros, i's, oh's, and el's, or triple repeats). Be careful, though, if you start throwing out characters to match rules, as you may end up with a higher percentage of rare characters (such as digits) at the end of the password, which makes it slightly less secure, perhaps. Better to throw it out and try it again.Hewart
perfect, I used is as Membership.GeneratePassword(12, 0)Leenaleeper
C
141
public string CreatePassword(int length)
{
        const string valid = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
        StringBuilder res = new StringBuilder();
        Random rnd = new Random();
        while (0 < length--)
        {
            res.Append(valid[rnd.Next(valid.Length)]);
        }
        return res.ToString();
}

This has a good benefit of being able to choose from a list of available characters for the generated password (e.g. digits only, only uppercase or only lowercase etc.)

Cookgeneral answered 10/9, 2008 at 18:47 Comment(11)
this method (base 62) is superior than the GUID(base 16) on strength: an 8-char hex string is equivalent to a 4-5 char alphanumeric oneGiacometti
Random is not cryptographically secure; System.Security.Cryptography.RNGCryptoServiceProvider is a better choice.Pietra
This would generate the same password each time the method is called, as the Random class is instantiated each time. This could be made secure by moving Random out of this method and reusing the instance.Blowzy
No, it would not. Unless two people decided to change passwords at the very same clock time.Cookgeneral
@Pietra How would you replace Random with RNGCryptoServiceProvider?Vladikavkaz
See my answer for a simple implementation. RNGCryptoServiceProvider generates bytes of high-entropy data, so you can just convert that output to characters. If you want, you could then strip out any non-alphanumeric characters if you want.Pietra
If I need a string, that contains numbers, letters and capital letters, and If I generate short string (like 8 characters long), there is still a chance, that it will produce result, which doesnt fit my requirements.Downes
@Downes has a very relevant point. Do NOT use this implementation! It will fail on any Windows machine with enforced password policy!Bendick
quote from question: don't care "if it matches all the "needed" strong password rules"...thanks for downvoting this answer thoughCookgeneral
This did create the same password many times for me; only 150 distinct values out of 500.Shoebill
only because of the way you are testing it: learn.microsoft.com/en-us/dotnet/api/…Cookgeneral
G
47

The main goals of my code are:

  1. The distribution of strings is almost uniform (don't care about minor deviations, as long as they're small)
  2. It outputs more than a few billion strings for each argument set. Generating an 8 character string (~47 bits of entropy) is meaningless if your PRNG only generates 2 billion (31 bits of entropy) different values.
  3. It's secure, since I expect people to use this for passwords or other security tokens.

The first property is achieved by taking a 64 bit value modulo the alphabet size. For small alphabets (such as the 62 characters from the question) this leads to negligible bias. The second and third property are achieved by using RNGCryptoServiceProvider instead of System.Random.

using System;
using System.Security.Cryptography;

public static string GetRandomAlphanumericString(int length)
{
    const string alphanumericCharacters =
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
        "abcdefghijklmnopqrstuvwxyz" +
        "0123456789";
    return GetRandomString(length, alphanumericCharacters);
}

public static string GetRandomString(int length, IEnumerable<char> characterSet)
{
    if (length < 0)
        throw new ArgumentException("length must not be negative", "length");
    if (length > int.MaxValue / 8) // 250 million chars ought to be enough for anybody
        throw new ArgumentException("length is too big", "length");
    if (characterSet == null)
        throw new ArgumentNullException("characterSet");
    var characterArray = characterSet.Distinct().ToArray();
    if (characterArray.Length == 0)
        throw new ArgumentException("characterSet must not be empty", "characterSet");

    var bytes = new byte[length * 8];
    new RNGCryptoServiceProvider().GetBytes(bytes);
    var result = new char[length];
    for (int i = 0; i < length; i++)
    {
        ulong value = BitConverter.ToUInt64(bytes, i * 8);
        result[i] = characterArray[value % (uint)characterArray.Length];
    }
    return new string(result);
}

(This is a copy of my answer to How can I generate random 8 character, alphanumeric strings in C#?)

Gynecology answered 28/9, 2013 at 14:42 Comment(3)
If UInt64.MaxValue is not evenly divisible by characterArray.Length then the randomly selected characters will not be evenly distributed (though this will be a very small effect).Bridoon
@JeffWalkerCodeRanger That's why I said negligible bias, not no bias. Even with a petabyte of output you have less than a 1% to distinguish this from a perfectly unbiased string generator. The additional complexity of perfect unbiasing is clearly not worth the rather theoretical gain in randomness here.Gynecology
For those using .NET Core, substitute "new RNGCryptoServiceProvider().GetBytes(bytes);" with "System.Security.Cryptography.RandomNumberGenerator.Create().GetBytes(bytes);"Know
P
34
public string GenerateToken(int length)
{
    using (RNGCryptoServiceProvider cryptRNG = new RNGCryptoServiceProvider())
    {
        byte[] tokenBuffer = new byte[length];
        cryptRNG.GetBytes(tokenBuffer);
        return Convert.ToBase64String(tokenBuffer);
    }
}

(You could also have the class where this method lives implement IDisposable, hold a reference to the RNGCryptoServiceProvider, and dispose of it properly, to avoid repeatedly instantiating it.)

It's been noted that as this returns a base-64 string, the output length is always a multiple of 4, with the extra space using = as a padding character. The length parameter specifies the length of the byte buffer, not the output string (and is therefore perhaps not the best name for that parameter, now I think about it). This controls how many bytes of entropy the password will have. However, because base-64 uses a 4-character block to encode each 3 bytes of input, if you ask for a length that's not a multiple of 3, there will be some extra "space", and it'll use = to fill the extra.

If you don't like using base-64 strings for any reason, you can replace the Convert.ToBase64String() call with either a conversion to regular string, or with any of the Encoding methods; eg. Encoding.UTF8.GetString(tokenBuffer) - just make sure you pick a character set that can represent the full range of values coming out of the RNG, and that produces characters that are compatible with wherever you're sending or storing this. Using Unicode, for example, tends to give a lot of Chinese characters. Using base-64 guarantees a widely-compatible set of characters, and the characteristics of such a string shouldn't make it any less secure as long as you use a decent hashing algorithm.

Pietra answered 12/7, 2014 at 9:24 Comment(7)
I think you mean to put tokenBuffer where you have linkBuf.Fermium
When I use this code and pass in a length of 10, the returned string is always 16 characters long and the final 2 characters are always "==". Am I using it incorrectly? Is the length specified in hex?Fermium
The specified length is the number of bytes of randomness (or "entropy", as it's known technically). However, the returned value is base-64 encoded, which means that because of how base-64 encoding works, the output length is always a multiple of 4. Sometimes, that's more characters than it needs to encode all the characters, so it uses = characters to pad out the rest.Pietra
RNGCryptoServiceProvider is an IDisposable, so I would implement it with the using pattern (i.e. using (var cryptRNG = new RNGCryptoServiceProvider()) { ... })Chemotherapy
@Chemotherapy A valid point, and a good suggestion. I've added that to my code sample.Pietra
Note that this solution might not always create passwords with numerical and special characters - in case that is a precondition for the generation of the password.Outrage
Thanks!! Works wonderfully. I needed password regeneration for FTP server, and this did the trick nicely.Sparse
L
26

This is a lot larger, but I think it looks a little more comprehensive: http://www.obviex.com/Samples/Password.aspx

///////////////////////////////////////////////////////////////////////////////
// SAMPLE: Generates random password, which complies with the strong password
//         rules and does not contain ambiguous characters.
//
// To run this sample, create a new Visual C# project using the Console
// Application template and replace the contents of the Class1.cs file with
// the code below.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
// 
// Copyright (C) 2004 Obviex(TM). All rights reserved.
// 
using System;
using System.Security.Cryptography;

/// <summary>
/// This class can generate random passwords, which do not include ambiguous 
/// characters, such as I, l, and 1. The generated password will be made of
/// 7-bit ASCII symbols. Every four characters will include one lower case
/// character, one upper case character, one number, and one special symbol
/// (such as '%') in a random order. The password will always start with an
/// alpha-numeric character; it will not start with a special symbol (we do
/// this because some back-end systems do not like certain special
/// characters in the first position).
/// </summary>
public class RandomPassword
{
    // Define default min and max password lengths.
    private static int DEFAULT_MIN_PASSWORD_LENGTH  = 8;
    private static int DEFAULT_MAX_PASSWORD_LENGTH  = 10;

    // Define supported password characters divided into groups.
    // You can add (or remove) characters to (from) these groups.
    private static string PASSWORD_CHARS_LCASE  = "abcdefgijkmnopqrstwxyz";
    private static string PASSWORD_CHARS_UCASE  = "ABCDEFGHJKLMNPQRSTWXYZ";
    private static string PASSWORD_CHARS_NUMERIC= "23456789";
    private static string PASSWORD_CHARS_SPECIAL= "*$-+?_&=!%{}/";

    /// <summary>
    /// Generates a random password.
    /// </summary>
    /// <returns>
    /// Randomly generated password.
    /// </returns>
    /// <remarks>
    /// The length of the generated password will be determined at
    /// random. It will be no shorter than the minimum default and
    /// no longer than maximum default.
    /// </remarks>
    public static string Generate()
    {
        return Generate(DEFAULT_MIN_PASSWORD_LENGTH, 
                        DEFAULT_MAX_PASSWORD_LENGTH);
    }

    /// <summary>
    /// Generates a random password of the exact length.
    /// </summary>
    /// <param name="length">
    /// Exact password length.
    /// </param>
    /// <returns>
    /// Randomly generated password.
    /// </returns>
    public static string Generate(int length)
    {
        return Generate(length, length);
    }

    /// <summary>
    /// Generates a random password.
    /// </summary>
    /// <param name="minLength">
    /// Minimum password length.
    /// </param>
    /// <param name="maxLength">
    /// Maximum password length.
    /// </param>
    /// <returns>
    /// Randomly generated password.
    /// </returns>
    /// <remarks>
    /// The length of the generated password will be determined at
    /// random and it will fall with the range determined by the
    /// function parameters.
    /// </remarks>
    public static string Generate(int   minLength,
                                  int   maxLength)
    {
        // Make sure that input parameters are valid.
        if (minLength <= 0 || maxLength <= 0 || minLength > maxLength)
            return null;

        // Create a local array containing supported password characters
        // grouped by types. You can remove character groups from this
        // array, but doing so will weaken the password strength.
        char[][] charGroups = new char[][] 
        {
            PASSWORD_CHARS_LCASE.ToCharArray(),
            PASSWORD_CHARS_UCASE.ToCharArray(),
            PASSWORD_CHARS_NUMERIC.ToCharArray(),
            PASSWORD_CHARS_SPECIAL.ToCharArray()
        };

        // Use this array to track the number of unused characters in each
        // character group.
        int[] charsLeftInGroup = new int[charGroups.Length];

        // Initially, all characters in each group are not used.
        for (int i=0; i<charsLeftInGroup.Length; i++)
            charsLeftInGroup[i] = charGroups[i].Length;

        // Use this array to track (iterate through) unused character groups.
        int[] leftGroupsOrder = new int[charGroups.Length];

        // Initially, all character groups are not used.
        for (int i=0; i<leftGroupsOrder.Length; i++)
            leftGroupsOrder[i] = i;

        // Because we cannot use the default randomizer, which is based on the
        // current time (it will produce the same "random" number within a
        // second), we will use a random number generator to seed the
        // randomizer.

        // Use a 4-byte array to fill it with random bytes and convert it then
        // to an integer value.
        byte[] randomBytes = new byte[4];

        // Generate 4 random bytes.
        RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
        rng.GetBytes(randomBytes);

        // Convert 4 bytes into a 32-bit integer value.
        int seed = BitConverter.ToInt32(randomBytes, 0);

        // Now, this is real randomization.
        Random  random  = new Random(seed);

        // This array will hold password characters.
        char[] password = null;

        // Allocate appropriate memory for the password.
        if (minLength < maxLength)
            password = new char[random.Next(minLength, maxLength+1)];
        else
            password = new char[minLength];

        // Index of the next character to be added to password.
        int nextCharIdx;

        // Index of the next character group to be processed.
        int nextGroupIdx;

        // Index which will be used to track not processed character groups.
        int nextLeftGroupsOrderIdx;

        // Index of the last non-processed character in a group.
        int lastCharIdx;

        // Index of the last non-processed group.
        int lastLeftGroupsOrderIdx = leftGroupsOrder.Length - 1;

        // Generate password characters one at a time.
        for (int i=0; i<password.Length; i++)
        {
            // If only one character group remained unprocessed, process it;
            // otherwise, pick a random character group from the unprocessed
            // group list. To allow a special character to appear in the
            // first position, increment the second parameter of the Next
            // function call by one, i.e. lastLeftGroupsOrderIdx + 1.
            if (lastLeftGroupsOrderIdx == 0)
                nextLeftGroupsOrderIdx = 0;
            else
                nextLeftGroupsOrderIdx = random.Next(0, 
                                                     lastLeftGroupsOrderIdx);

            // Get the actual index of the character group, from which we will
            // pick the next character.
            nextGroupIdx = leftGroupsOrder[nextLeftGroupsOrderIdx];

            // Get the index of the last unprocessed characters in this group.
            lastCharIdx = charsLeftInGroup[nextGroupIdx] - 1;

            // If only one unprocessed character is left, pick it; otherwise,
            // get a random character from the unused character list.
            if (lastCharIdx == 0)
                nextCharIdx = 0;
            else
                nextCharIdx = random.Next(0, lastCharIdx+1);

            // Add this character to the password.
            password[i] = charGroups[nextGroupIdx][nextCharIdx];

            // If we processed the last character in this group, start over.
            if (lastCharIdx == 0)
                charsLeftInGroup[nextGroupIdx] = 
                                          charGroups[nextGroupIdx].Length;
            // There are more unprocessed characters left.
            else
            {
                // Swap processed character with the last unprocessed character
                // so that we don't pick it until we process all characters in
                // this group.
                if (lastCharIdx != nextCharIdx)
                {
                    char temp = charGroups[nextGroupIdx][lastCharIdx];
                    charGroups[nextGroupIdx][lastCharIdx] = 
                                charGroups[nextGroupIdx][nextCharIdx];
                    charGroups[nextGroupIdx][nextCharIdx] = temp;
                }
                // Decrement the number of unprocessed characters in
                // this group.
                charsLeftInGroup[nextGroupIdx]--;
            }

            // If we processed the last group, start all over.
            if (lastLeftGroupsOrderIdx == 0)
                lastLeftGroupsOrderIdx = leftGroupsOrder.Length - 1;
            // There are more unprocessed groups left.
            else
            {
                // Swap processed group with the last unprocessed group
                // so that we don't pick it until we process all groups.
                if (lastLeftGroupsOrderIdx != nextLeftGroupsOrderIdx)
                {
                    int temp = leftGroupsOrder[lastLeftGroupsOrderIdx];
                    leftGroupsOrder[lastLeftGroupsOrderIdx] = 
                                leftGroupsOrder[nextLeftGroupsOrderIdx];
                    leftGroupsOrder[nextLeftGroupsOrderIdx] = temp;
                }
                // Decrement the number of unprocessed groups.
                lastLeftGroupsOrderIdx--;
            }
        }

        // Convert password characters into a string and return the result.
        return new string(password);
     }
}

/// <summary>
/// Illustrates the use of the RandomPassword class.
/// </summary>
public class RandomPasswordTest
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main(string[] args)
    {
        // Print 100 randomly generated passwords (8-to-10 char long).
        for (int i=0; i<100; i++)
            Console.WriteLine(RandomPassword.Generate(8, 10));
    }
}
//
// END OF FILE
///////////////////////////////////////////////////////////////////////////////
Lame answered 10/9, 2008 at 18:47 Comment(4)
It turns out that there is support for this by the framework. So I am accepting that answer rather!Enthuse
Generating only 2^31 different passwords, even with long output sizes, is a bit on the low side. Might be enough against online attacks, but certainly to small for offline attacks. => I wouldn't recommend this.Gynecology
This is still a good answer because the "built-in" support is really Membership, and what if you've decided not to use ASP.NET Membership? It still works, since the dependency is System.Web.dll, but it's a little awkward because the method is not self contained. @GEOCHET: Thanks for posting this alternative.Discombobulate
I changed these lines RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); rng.GetBytes(randomBytes); to randomBytes = RandomNumberGenerator.GetBytes(4); in my project in order to get rid of the obsolete message of RNGCryptoServiceProvider.Botts
M
8

I created this class that uses RNGCryptoServiceProvider and it is flexible. Example:

var generator = new PasswordGenerator(minimumLengthPassword: 8,
                                      maximumLengthPassword: 15,
                                      minimumUpperCaseChars: 2,
                                      minimumNumericChars: 3,
                                      minimumSpecialChars: 2);
string password = generator.Generate();
Maddocks answered 31/5, 2014 at 19:2 Comment(2)
Thats great, whats the license on that class? Can I use it?Ranket
Use it just like you want!Maddocks
E
7

I don't like the passwords that Membership.GeneratePassword() creates, as they're too ugly and have too many special characters.

This code generates a 10 digit not-too-ugly password.

string password = Guid.NewGuid().ToString("N").ToLower()
                      .Replace("1", "").Replace("o", "").Replace("0","")
                      .Substring(0,10);

Sure, I could use a Regex to do all the replaces but this is more readable and maintainable IMO.

Ebba answered 21/1, 2011 at 10:9 Comment(3)
A GUID shouldn't be abused as crypto PRNGGynecology
If you're going to use this method, you can use .ToString("N") and you won't have to replace the "-". There is also no need to replace "l", since it's not a hex digit.Protoactinium
Totally see why you did this. I just needed a short lived (less than a day) password that didn't have to be too unique per user. Yanking out the ones and zeros is a great way to drop the confusion. I also just shifted mine to uppercase and then cut the length to 6. Like the 'N' suggestion, too. Thanks!Reform
X
7

I know that this is an old thread, but I have what might be a fairly simple solution for someone to use. Easy to implement, easy to understand, and easy to validate.

Consider the following requirement:

I need a random password to be generated which has at least 2 lower-case letters, 2 upper-case letters and 2 numbers. The password must also be a minimum of 8 characters in length.

The following regular expression can validate this case:

^(?=\b\w*[a-z].*[a-z]\w*\b)(?=\b\w*[A-Z].*[A-Z]\w*\b)(?=\b\w*[0-9].*[0-9]\w*\b)[a-zA-Z0-9]{8,}$

It's outside the scope of this question - but the regex is based on lookahead/lookbehind and lookaround.

The following code will create a random set of characters which match this requirement:

public static string GeneratePassword(int lowercase, int uppercase, int numerics) {
    string lowers = "abcdefghijklmnopqrstuvwxyz";
    string uppers = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    string number = "0123456789";

    Random random = new Random();

    string generated = "!";
    for (int i = 1; i <= lowercase; i++)
        generated = generated.Insert(
            random.Next(generated.Length), 
            lowers[random.Next(lowers.Length - 1)].ToString()
        );

    for (int i = 1; i <= uppercase; i++)
        generated = generated.Insert(
            random.Next(generated.Length), 
            uppers[random.Next(uppers.Length - 1)].ToString()
        );

    for (int i = 1; i <= numerics; i++)
        generated = generated.Insert(
            random.Next(generated.Length), 
            number[random.Next(number.Length - 1)].ToString()
        );

    return generated.Replace("!", string.Empty);

}

To meet the above requirement, simply call the following:

String randomPassword = GeneratePassword(3, 3, 3);

The code starts with an invalid character ("!") - so that the string has a length into which new characters can be injected.

It then loops from 1 to the # of lowercase characters required, and on each iteration, grabs a random item from the lowercase list, and injects it at a random location in the string.

It then repeats the loop for uppercase letters and for numerics.

This gives you back strings of length = lowercase + uppercase + numerics into which lowercase, uppercase and numeric characters of the count you want have been placed in a random order.

X answered 11/1, 2013 at 21:57 Comment(2)
Don't use System.Random for security critical stuff like passwords. Use RNGCryptoServiceProviderGynecology
lowers[random.Next(lowers.Length - 1)].ToString() This code will never generate a 'z'. random.Next produces integers less than the number provided, so you should not subtract that extra one from the length.Otherworld
H
7

I'll add another ill-advised answer to the pot.

I have a use case where I need random passwords for machine-machine communication, so I don't have any requirement for human readability. I also don't have access to Membership.GeneratePassword in my project, and don't want to add the dependency.

I am fairly certain Membership.GeneratePassword is doing something similar to this, but here you can tune the pools of characters to draw from.

public static class PasswordGenerator
{
    private readonly static Random _rand = new Random();

    public static string Generate(int length = 24)
    {
        const string lower = "abcdefghijklmnopqrstuvwxyz";
        const string upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        const string number = "1234567890";
        const string special = "!@#$%^&*_-=+";

        // Get cryptographically random sequence of bytes
        var bytes = new byte[length];
        new RNGCryptoServiceProvider().GetBytes(bytes);

        // Build up a string using random bytes and character classes
        var res = new StringBuilder();
        foreach(byte b in bytes)
        {
            // Randomly select a character class for each byte
            switch (_rand.Next(4))
            {
                // In each case use mod to project byte b to the correct range
                case 0:
                    res.Append(lower[b % lower.Count()]);
                    break;
                case 1:
                    res.Append(upper[b % upper.Count()]);
                    break;
                case 2:
                    res.Append(number[b % number.Count()]);
                    break;
                case 3:
                    res.Append(special[b % special.Count()]);
                    break;
            }
        }
        return res.ToString();
    }
}

And some example output:

PasswordGenerator.Generate(12)
"pzY=64@-ChS$"
"BG0OsyLbYnI_"
"l9#5^2&adj_i"
"#++Ws9d$%O%X"
"IWhdIN-#&O^s"

To preempt complaints about the use of Random: The primary source of randomness is still the crypto RNG. Even if you could deterministically preordain the sequence coming out of Random (say it only produced 1) you still wouldn't know the next char that would be picked (though that would limit the range of possibilities).

One simple extension would be to add weighting to the different character sets, which could be as simple as upping the max value and adding fall-through cases to increase weight.

switch (_rand.Next(6))
{
    // Prefer letters 2:1
    case 0:
    case 1:
        res.Append(lower[b % lower.Count()]);
        break;
    case 2:
    case 3:
        res.Append(upper[b % upper.Count()]);
        break;
    case 4:
        res.Append(number[b % number.Count()]);
        break;
    case 5:
        res.Append(special[b % special.Count()]);
        break;
}

For a more humanistic random password generator I once implemented a prompt system using the EFF dice-word list.

Huffish answered 12/3, 2019 at 21:18 Comment(0)
A
5

For this sort of password, I tend to use a system that's likely to generate more easily "used" passwords. Short, often made up of pronouncable fragments and a few numbers, and with no intercharacter ambiguity (is that a 0 or an O? A 1 or an I?). Something like

string[] words = { 'bur', 'ler', 'meh', 'ree' };
string word = "";

Random rnd = new Random();
for (i = 0; i < 3; i++)
   word += words[rnd.Next(words.length)]

int numbCount = rnd.Next(4);
for (i = 0; i < numbCount; i++)
  word += (2 + rnd.Next(7)).ToString();

return word;

(Typed right into the browser, so use only as guidelines. Also, add more words).

Anderaanderea answered 10/9, 2008 at 18:53 Comment(0)
U
2

I created this method similar to the available in the membership provider. This is usefull if you don't want to add the web reference in some applications.

It works great.

public static string GeneratePassword(int Length, int NonAlphaNumericChars)
    {
        string allowedChars = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789";
        string allowedNonAlphaNum = "!@#$%^&*()_-+=[{]};:<>|./?";
        Random rd = new Random();

        if (NonAlphaNumericChars > Length || Length <= 0 || NonAlphaNumericChars < 0)
            throw new ArgumentOutOfRangeException();

            char[] pass = new char[Length];
            int[] pos = new int[Length];
            int i = 0, j = 0, temp = 0;
            bool flag = false;

            //Random the position values of the pos array for the string Pass
            while (i < Length - 1)
            {
                j = 0;
                flag = false;
                temp = rd.Next(0, Length);
                for (j = 0; j < Length; j++)
                    if (temp == pos[j])
                    {
                        flag = true;
                        j = Length;
                    }

                if (!flag)
                {
                    pos[i] = temp;
                    i++;
                }
            }

            //Random the AlphaNumericChars
            for (i = 0; i < Length - NonAlphaNumericChars; i++)
                pass[i] = allowedChars[rd.Next(0, allowedChars.Length)];

            //Random the NonAlphaNumericChars
            for (i = Length - NonAlphaNumericChars; i < Length; i++)
                pass[i] = allowedNonAlphaNum[rd.Next(0, allowedNonAlphaNum.Length)];

            //Set the sorted array values by the pos array for the rigth posistion
            char[] sorted = new char[Length];
            for (i = 0; i < Length; i++)
                sorted[i] = pass[pos[i]];

            string Pass = new String(sorted);

            return Pass;
    }
Upturn answered 15/5, 2012 at 12:0 Comment(1)
Don't use System.Random for security critical stuff like passwords. Use RNGCryptoServiceProviderGynecology
H
2

I've always been very happy with the password generator built-in to KeePass. Since KeePass is a .Net program, and open source, I decided to dig around the code a bit. I ended up just referncing KeePass.exe, the copy provided in the standard application install, as a reference in my project and writing the code below. You can see how flexible it is thanks to KeePass. You can specify length, which characters to include/not include, etc...

using KeePassLib.Cryptography.PasswordGenerator;
using KeePassLib.Security;


public static string GeneratePassword(int passwordLength, bool lowerCase, bool upperCase, bool digits,
        bool punctuation, bool brackets, bool specialAscii, bool excludeLookAlike)
    {
        var ps = new ProtectedString();
        var profile = new PwProfile();
        profile.CharSet = new PwCharSet();
        profile.CharSet.Clear();

        if (lowerCase)
            profile.CharSet.AddCharSet('l');
        if(upperCase)
            profile.CharSet.AddCharSet('u');
        if(digits)
            profile.CharSet.AddCharSet('d');
        if (punctuation)
            profile.CharSet.AddCharSet('p');
        if (brackets)
            profile.CharSet.AddCharSet('b');
        if (specialAscii)
            profile.CharSet.AddCharSet('s');

        profile.ExcludeLookAlike = excludeLookAlike;
        profile.Length = (uint)passwordLength;
        profile.NoRepeatingCharacters = true;

        KeePassLib.Cryptography.PasswordGenerator.PwGenerator.Generate(out ps, profile, null, _pool);

        return ps.ReadString();
    }
Hallowed answered 14/6, 2015 at 15:2 Comment(0)
J
1

I like to look at generating passwords, just like generating software keys. You should choose from an array of characters that follow a good practice. Take what @Radu094 answered with and modify it to follow good practice. Don't put every single letter in the character array. Some letters are harder to say or understand over the phone.

You should also consider using a checksum on the password that was generated to make sure that it was generated by you. A good way of accomplishing this is to use the LUHN algorithm.

Jarid answered 10/9, 2008 at 18:54 Comment(0)
Z
1

Here is a solution that uses RNGCryptoServiceProvider to mimic the functionality of Membership.GeneratePassword from the System.Web.Security namespace.

I needed a drop-in replacement for running it in Azure Function.

It can be tested here: https://dotnetfiddle.net/V0cNJw

public static string GeneratePassword(int length, int numberOfNonAlphanumericCharacters)
{
    const string allowedChars = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789";
    const string nonAlphanumericChars = "!@#$%^&*()_-+=[{]};:<>|./?";
    var randNum = new byte[4];
    using (var rng = new RNGCryptoServiceProvider())
    {
        rng.GetBytes(randNum);
        var randomSeed = BitConverter.ToInt32(randNum, 0);
        var random = new Random(randomSeed);
        var chars = new char[length];
        var allowedCharCount = allowedChars.Length;
        var nonAlphanumericCharCount = nonAlphanumericChars.Length;
        var numNonAlphanumericCharsAdded = 0;
        for (var i = 0; i < length; i++)
        {
            if (numNonAlphanumericCharsAdded < numberOfNonAlphanumericCharacters && i < length - 1)
            {
                chars[i] = nonAlphanumericChars[random.Next(nonAlphanumericCharCount)];
                numNonAlphanumericCharsAdded++;
            }
            else
            {
                chars[i] = allowedChars[random.Next(allowedCharCount)];
            }
        }
        return new string(chars);
    }
}

Here is a version that runs on .Net 6.0+ Sandbox: https://dotnetfiddle.net/XqgTSg

public static string GeneratePassword(int length, int numberOfNonAlphanumericCharacters)
{
    const string allowedChars = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789";
    const string nonAlphanumericChars = "!@#$%^&*()_-+=[{]};:<>|./?";
    var randNum = new byte[4];
    using (var rng = RandomNumberGenerator.Create())
    {
        rng.GetBytes(randNum);
        var randomSeed = BitConverter.ToInt32(randNum, 0);
        var random = new Random(randomSeed);
        var chars = new char[length];
        var allowedCharCount = allowedChars.Length;
        var nonAlphanumericCharCount = nonAlphanumericChars.Length;
        var numNonAlphanumericCharsAdded = 0;
        for (var i = 0; i < length; i++)
        {
            if (numNonAlphanumericCharsAdded < numberOfNonAlphanumericCharacters && i < length - 1)
            {
                chars[i] = nonAlphanumericChars[random.Next(nonAlphanumericCharCount)];
                numNonAlphanumericCharsAdded++;
            }
            else
            {
                chars[i] = allowedChars[random.Next(allowedCharCount)];
            }
        }
        return new string(chars);
    }
}
Zambia answered 14/2, 2023 at 15:0 Comment(0)
W
1

How about this?

// Add using System.Security.Cryptography;
Convert.ToBase64String(RandomNumberGenerator.GetBytes(8));
Worldshaking answered 20/9, 2023 at 6:50 Comment(0)
A
0
public static string GeneratePassword(int passLength) {
        var chars = "abcdefghijklmnopqrstuvwxyz@#$&ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        var random = new Random();
        var result = new string(
            Enumerable.Repeat(chars, passLength)
                      .Select(s => s[random.Next(s.Length)])
                      .ToArray());
        return result;
    }
Analyze answered 25/6, 2018 at 12:16 Comment(2)
Please explain your answerGreasy
This function works very well with a few changes. 1. Added entropy if you are doing multiple calls at once. This means called Sleep() or some other entropy causing function between calls. 2. Increase the number and randomness of the source characters. I created a series of 500 char passwords with keypass excluding a bunch of similar and other escapable characters I did not want to deal with and used the resulting 2000 character string. The randomness after only even 100ms of Entropy was pretty good.Topsyturvy
M
0

This package allows you to generate a random password while fluently indicating which characters it should contain (if needed):

https://github.com/prjseal/PasswordGenerator/

Example:

var pwd = new Password().IncludeLowercase().IncludeUppercase().IncludeSpecial();
var password = pwd.Next();
Makepeace answered 27/1, 2020 at 14:24 Comment(0)
G
0

If you want to make use of the cryptographically secure random number generation used by System.Web.Security.Membership.GeneratePassword but also want to restrict the character set to alphanumeric characters, you can filter the result with a regex:

static string GeneratePassword(int characterCount)
{
    string password = String.Empty;
    while(password.Length < characterCount)
        password += Regex.Replace(System.Web.Security.Membership.GeneratePassword(128, 0), "[^a-zA-Z0-9]", string.Empty);
    return password.Substring(0, characterCount);
}
Gabble answered 24/2, 2020 at 19:2 Comment(0)
T
0

check this code... I added the .remove(length) to improve anaximander's response

            public string GeneratePassword(int length)
            {
                using(RNGCryptoServiceProvider cryptRNG = new RNGCryptoServiceProvider();)
               {
                      byte[] tokenBuffer = new byte[length];
                      cryptRNG.GetBytes(tokenBuffer);
                      return Convert.ToBase64String(tokenBuffer).Remove(length);
                }
                          
            }
Timbuktu answered 23/2, 2021 at 13:48 Comment(1)
You should wrap this inside a using() block since RNGCryptoServiceProvider implements IDisposable.Clara
W
0

How to Generate the Random Password in C#.
Output : (https://prnt.sc/11fac8v)
Run : https://onlinegdb.com/HJe5OHBLu

    private static Random random = new Random();
    public static void Main()
    {
        Console.WriteLine("Random password with length of 8 character.");
        Console.WriteLine("===========================================");
        Console.WriteLine("Capital latters : 2");
        Console.WriteLine("Number latters : 2");
        Console.WriteLine("Special latters : 2");
        Console.WriteLine("Small latters : 2");
        Console.WriteLine("===========================================");
        Console.Write("The Random Password : ");
        Console.WriteLine(RandomStringCap(2) + RandomStringNum(2) + RandomStringSpe(2) + RandomStringSml(2));
        Console.WriteLine("===========================================");
    }
    public static string RandomStringCap(int length)
    {
        const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        return new string(Enumerable.Repeat(chars, length)
                         .Select(s => s[random.Next(s.Length)]).ToArray());
    }
    public static string RandomStringNum(int length)
    {
        const string chars = "0123456789";
        return new string(Enumerable.Repeat(chars, length)
                         .Select(s => s[random.Next(s.Length)]).ToArray());
    }
    public static string RandomStringSml(int length)
    {
        const string chars = "abcdefghijklmnopqrstuvwxyz";
        return new string(Enumerable.Repeat(chars, length)
                         .Select(s => s[random.Next(s.Length)]).ToArray());
    }
    public static string RandomStringSpe(int length)
    {
        const string chars = "!@#$%^&*_-=+";
        return new string(Enumerable.Repeat(chars, length)
                         .Select(s => s[random.Next(s.Length)]).ToArray());
    }
Wrangler answered 15/4, 2021 at 5:1 Comment(2)
While this code snippet may solve the question, including an explanation really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion.Adsorbate
@Adsorbate I got my mistake, thanks for your suggestion buddy.Wrangler
S
0

Inspired by the answer from @kitsu.eb, but using RandomNumberGenerator instead of Random or RNGCryptoServiceProvider (deprecated in .NET 6), and added a few more special characters.

Optional parameter to exclude characters that will be escaped when using System.Text.Json.JsonSerializer.Serialize - for example & which is escaped as \u0026 - so that you can guarantee the length of the serialized string will match the length of the password.

For .NET Core 3.0 and above.

public static class PasswordGenerator
{
    const string lower = "abcdefghijklmnopqrstuvwxyz";
    const string upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    const string number = "1234567890";
    const string special = "!@#$%^&*()[]{},.:`~_-=+"; // excludes problematic characters like ;'"/\
    const string specialJsonSafe = "!@#$%^*()[]{},.:~_-="; // excludes problematic characters like ;'"/\ and &`+

    const int lowerLength = 26; // lower.Length
    const int upperLength = 26; // upper.Length;
    const int numberLength = 10; // number.Length;
    const int specialLength = 23; // special.Length;
    const int specialJsonSafeLength = 20; // specialJsonSafe.Length;

    public static string Generate(int length = 96, bool jsonSafeSpecialCharactersOnly = false)
    {
        Span<char> result = length < 1024 ? stackalloc char[length] : new char[length].AsSpan();

        for (int i = 0; i < length; ++i)
        {
            switch (RandomNumberGenerator.GetInt32(4))
            {
                case 0:
                    result[i] = lower[RandomNumberGenerator.GetInt32(0, lowerLength)];
                    break;
                case 1:
                    result[i] = upper[RandomNumberGenerator.GetInt32(0, upperLength)];
                    break;
                case 2:
                    result[i] = number[RandomNumberGenerator.GetInt32(0, numberLength)];
                    break;
                case 3:
                    if (jsonSafeSpecialCharactersOnly)
                    {
                        result[i] = specialJsonSafe[RandomNumberGenerator.GetInt32(0, specialJsonSafeLength)];
                    }
                    else
                    {
                        result[i] = special[RandomNumberGenerator.GetInt32(0, specialLength)];
                    }
                    break;
            }
        }

        return result.ToString();
    }
}
Sweaty answered 11/8, 2022 at 7:38 Comment(0)
M
0

Pretty easy way to require one from each group using Random and linq-to-objects.

  • Randomize each group
  • Select random amount from first group
  • Select remaining random amounts from following groups

 

Random rand = new Random();
int min = 8;
int max = 16;
int totalLen = rand.Next(min, max);
int remainingGroups = 4;
                
string[] allowedLowerChars = "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".Split(',');           
string [] allowedUpperChars = "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".Split(',');
string [] allowedNumbers = "1,2,3,4,5,6,7,8,9,0".Split(',');
string [] allowedSpecialChars = "!,@,#,$,%,&,?".Split(',');


var password = allowedLowerChars.OrderBy(c => rand.Next()).Take(rand.Next(1, totalLen-remainingGroups--)).ToList();
password.AddRange(allowedUpperChars.OrderBy(c => rand.Next()).Take(rand.Next(1, totalLen-password.Count-remainingGroups--)).ToList());
password.AddRange(allowedNumbers.OrderBy(c => rand.Next()).Take(rand.Next(1, totalLen-password.Count-remainingGroups--)).ToList());
password.AddRange(allowedSpecialChars.OrderBy(c => rand.Next()).Take(totalLen-password.Count).ToList());
password = password.OrderBy(c => rand.Next()).ToList(); // randomize groups
Massimo answered 30/9, 2022 at 19:21 Comment(0)
D
0

Since Random is not secure and RNGCryptoServiceProvider is obsolte I ended up doing this:

  // possible characters that password can have
  private const string passChars =
       "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
       "abcdefghijklmnopqrstuvwxyz" +
       "0123456789" +
       "!@#$%.-_"
       ;

    public static string GetRandomPassword(int length)
    {
        char[] p = new char[length];
        for (int i = 0; i < length; i++)
            p[i] = passChars[RandomNumberGenerator.GetInt32(0, passChars.Length)];
        return new string(p);
    }
Diplostemonous answered 6/2, 2023 at 15:49 Comment(0)
B
0

Here's my attempt cobbled together from the answers above which is pretty simple to follow and allows you to establish multiple character sets which are guaranteed to be included (needed for our complexity requirements).

using static System.Security.Cryptography.RandomNumberGenerator;
// Usage: GenerateRandomPassword(10, "abcdefghkmnpqrstwxyz", "ABCDEFGHJKMNPRTWXYZ", "2346789", "!*@#$%^&+=");
private static string GenerateRandomPassword(int len, params string[] types)
{
    if (types.Length > len) len = types.Length; // prevent errors
    if (len < 0 || types.Length < 1) return string.Empty;

    var chars = new char[len];
    var pos = 0;

    foreach (var type in types) // guarantee at least one char from each type
    {
        var charNum = GetInt32(0, type.Length);
        chars[pos++] = type[charNum];
    }

    while (pos < chars.Length)
    {
        var typeNum = GetInt32(0, types.Length);
        var type = types[typeNum];
        var charNum = GetInt32(0, type.Length);
        var charValue = type[charNum];
        if (chars.Contains(charValue)) continue; // prevent duplicates
        chars[pos++] = charValue;
    }

    return new string(chars.OrderBy(_ => GetInt32(0, len)).ToArray());
}
Butyrate answered 1/8, 2023 at 17:43 Comment(0)
H
0
protected void BtnRandomPasswordClick(object sender, EventArgs e)
{
    txtPassword.Text = CreateRandomPassword();
}

private string CreateRandomPassword()
{
    var chars = CreateRandomPasswordNumber() + CreateRandomPasswordUppercase() + CreateRandomPasswordLowercase() + CreateRandomPasswordSpecial();
    var stringChars = new char[12];
    var random1 = new Random();
    for (int i = 0; i < stringChars.Length; i++)
    {
        stringChars[i] = chars[random1.Next(chars.Length)];
    }
    var finalString = new String(stringChars);
    return finalString;
}

private string CreateRandomPasswordNumber()
{
    var chars = "0123456789";
    var stringChars = new char[30];
    var random1 = new Random();
    for (int i = 0; i < stringChars.Length; i++)
    {
        stringChars[i] = chars[random1.Next(chars.Length)];
    }
    var finalString = new String(stringChars);
    return finalString;
}

private string CreateRandomPasswordUppercase()
{
    var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    var stringChars = new char[30];
    var random1 = new Random();
    for (int i = 0; i < stringChars.Length; i++)
    {
        stringChars[i] = chars[random1.Next(chars.Length)];
    }
    var finalString = new String(stringChars);
    return finalString;
}

private string CreateRandomPasswordLowercase()
{
    var chars = "abcdefghijklmnopqrstuvwxyz";
    var stringChars = new char[30];
    var random1 = new Random();
    for (int i = 0; i < stringChars.Length; i++)
    {
        stringChars[i] = chars[random1.Next(chars.Length)];
    }
    var finalString = new String(stringChars);
    return finalString;
}

private string CreateRandomPasswordSpecial()
{
    var chars = "~`!@#$%^&*()!-+={[}]|\\:;\"',.?/";
    var stringChars = new char[30];
    var random1 = new Random();
    for (int i = 0; i < stringChars.Length; i++)
    {
        stringChars[i] = chars[random1.Next(chars.Length)];
    }
    var finalString = new String(stringChars);
    return finalString;
}

I found this method to be quite reliable after many tests.

Hangout answered 17/10, 2023 at 15:6 Comment(1)
Thank you for your interest in contributing to the Stack Overflow community. This question already has quite a few answers—including one that has been extensively validated by the community. Are you certain your approach hasn’t been given previously? If so, it would be useful to explain how your approach is different, under what circumstances your approach might be preferred, and/or why you think the previous answers aren’t sufficient. Can you kindly edit your answer to offer an explanation?Bemoan
E
0

.NET 6+, low allocation password generator with

  • at least one digit
  • at least one letter
  • all chars unique

requirements

public static String Generate(int length = 10, string symbols = "0123456789qwertyuioplkjhgfdsazxcvbnm")
{
    var password = "";

    do
    {
        password = String.Create(length, symbols, Generate);
    }
    while (!Verify(password));

    return password;
}

static void Generate(Span<char> password, string symbols)
{
    var availableChars = new HashSet<char>(symbols);

    Span<byte> randomBytes = stackalloc byte[password.Length];
    System.Security.Cryptography.RandomNumberGenerator.Fill(randomBytes);

    for (var i = 0; i < password.Length; i++)
    {
        var randomAvailableChar = availableChars.ElementAt(randomBytes[i] % availableChars.Count);
        password[i] = randomAvailableChar;
        availableChars.Remove(randomAvailableChar);
    }
}

static Boolean Verify(string password)
{
    return password.Any(ch => Char.IsDigit(ch)) // at least one digit
        && password.Any(ch => Char.IsLetter(ch)) // at least one letter
        && password.Length == password.Distinct().Count(); // all chars unique
}

Output examples:

80tez4fk1p
vniuhcak27
uezc9m1r45
e25my37wko
l4f5jr7ed6
ti8phxa41b
ojpw9lex32
q89xhfzo0d
v8ycx19607
63pbcrhkn5
Expellant answered 18/10, 2023 at 17:41 Comment(0)
R
-1

On my website I use this method:

    //Symb array
    private const string _SymbolsAll = "~`!@#$%^&*()_+=-\\|[{]}'\";:/?.>,<";

    //Random symb
    public string GetSymbol(int Length)
    {
        Random Rand = new Random(DateTime.Now.Millisecond);
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < Length; i++)
            result.Append(_SymbolsAll[Rand.Next(0, _SymbolsAll.Length)]);
        return result.ToString();
    }

Edit string _SymbolsAll for your array list.

Retroaction answered 29/3, 2015 at 21:5 Comment(1)
As already stated in the edit description. If you link to your website without it being a code reference you are purely advertising which renders it spam so please remove that link from your answer.Piatt
T
-1

Added some supplemental code to the accepted answer. It improves upon answers just using Random and allows for some password options. I also liked some of the options from the KeePass answer but did not want to include the executable in my solution.

private string RandomPassword(int length, bool includeCharacters, bool includeNumbers, bool includeUppercase, bool includeNonAlphaNumericCharacters, bool includeLookAlikes)
{
    if (length < 8 || length > 128) throw new ArgumentOutOfRangeException("length");
    if (!includeCharacters && !includeNumbers && !includeNonAlphaNumericCharacters) throw new ArgumentException("RandomPassword-Key arguments all false, no values would be returned");

    string pw = "";
    do
    {
        pw += System.Web.Security.Membership.GeneratePassword(128, 25);
        pw = RemoveCharacters(pw, includeCharacters, includeNumbers, includeUppercase, includeNonAlphaNumericCharacters, includeLookAlikes);
    } while (pw.Length < length);

    return pw.Substring(0, length);
}

private string RemoveCharacters(string passwordString, bool includeCharacters, bool includeNumbers, bool includeUppercase, bool includeNonAlphaNumericCharacters, bool includeLookAlikes)
{
    if (!includeCharacters)
    {
        var remove = new string[] { "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" };
        foreach (string r in remove)
        {
            passwordString = passwordString.Replace(r, string.Empty);
            passwordString = passwordString.Replace(r.ToUpper(), string.Empty);
        }
    }

    if (!includeNumbers)
    {
        var remove = new string[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
        foreach (string r in remove)
            passwordString = passwordString.Replace(r, string.Empty);
    }

    if (!includeUppercase)
        passwordString = passwordString.ToLower();

    if (!includeNonAlphaNumericCharacters)
    {
        var remove = new string[] { "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "-", "_", "+", "=", "{", "}", "[", "]", "|", "\\", ":", ";", "<", ">", "/", "?", "." };
        foreach (string r in remove)
            passwordString = passwordString.Replace(r, string.Empty);
    }

    if (!includeLookAlikes)
    {
        var remove = new string[] { "(", ")", "0", "O", "o", "1", "i", "I", "l", "|", "!", ":", ";" };
        foreach (string r in remove)
            passwordString = passwordString.Replace(r, string.Empty);
    }

    return passwordString;
}

This was the first link when I searched for generating random passwords and the following is out of scope for the current question but might be important to consider.

  • Based upon the assumption that System.Web.Security.Membership.GeneratePassword is cryptographically secure with a minimum of 20% of the characters being Non-Alphanumeric.
  • Not sure if removing characters and appending strings is considered good practice in this case and provides enough entropy.
  • Might want to consider implementing in some way with SecureString for secure password storage in memory.
Tomlinson answered 3/1, 2017 at 17:55 Comment(1)
FYI, you wouldn't need to include the KeyPass executable file, as it's open source (the source code is available for download here)Cruller
A
-1

validChars can be any construct, but I decided to select based on ascii code ranges removing control chars. In this example, it is a 12 character string.

string validChars = String.Join("", Enumerable.Range(33, (126 - 33)).Where(i => !(new int[] { 34, 38, 39, 44, 60, 62, 96 }).Contains(i)).Select(i => { return (char)i; }));
string.Join("", Enumerable.Range(1, 12).Select(i => { return validChars[(new Random(Guid.NewGuid().GetHashCode())).Next(0, validChars.Length - 1)]; }))
Adopt answered 3/10, 2017 at 18:11 Comment(0)
C
-2

This is short and it works great for me.

public static string GenerateRandomCode(int length)
{
    Random rdm = new Random();
    StringBuilder sb = new StringBuilder();

    for(int i = 0; i < length; i++)
        sb.Append(Convert.ToChar(rdm.Next(101,132)));

    return sb.ToString();
}
Clearance answered 27/10, 2013 at 0:59 Comment(3)
It may "work", but it's certainly not secure. Passwords need to be secure.Gynecology
I think random passwords are temporary passwords. Don't see why they have to be secure, and even if they do, you can add numbers and special characters in the range.Clearance
Adding numbers and special characters doesn't improve the security if you generate them using a predictable PRNG. If you know when a password was generated, you can narrow it down to only a few candidates.Gynecology
N
-2

Here Is what i put together quickly.

    public string GeneratePassword(int len)
    {
        string res = "";
        Random rnd = new Random();
        while (res.Length < len) res += (new Func<Random, string>((r) => {
            char c = (char)((r.Next(123) * DateTime.Now.Millisecond % 123)); 
            return (Char.IsLetterOrDigit(c)) ? c.ToString() : ""; 
        }))(rnd);
        return res;
    }
Nation answered 3/12, 2015 at 8:10 Comment(0)
P
-2
 Generate random password of specified length with 
  - Special characters   
  - Number
  - Lowecase
  - Uppercase

  public static string CreatePassword(int length = 12)
    {
        const string lower = "abcdefghijklmnopqrstuvwxyz";
        const string upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        const string number = "1234567890";
        const string special = "!@#$%^&*";

        var middle = length / 2;
        StringBuilder res = new StringBuilder();
        Random rnd = new Random();
        while (0 < length--)
        {
            if (middle == length)
            {
                res.Append(number[rnd.Next(number.Length)]);
            }
            else if (middle - 1 == length)
            {
                res.Append(special[rnd.Next(special.Length)]);
            }
            else
            {
                if (length % 2 == 0)
                {
                    res.Append(lower[rnd.Next(lower.Length)]);
                }
                else
                {
                    res.Append(upper[rnd.Next(upper.Length)]);
                }
            }
        }
        return res.ToString();
    }
Petit answered 9/2, 2018 at 8:38 Comment(3)
Code only answers arent encouraged as they dont provide much information for future readers please provide some explanation to what you have writtenWulfe
Creates the same password over and over again. Need to have instance of Random as staticDescant
Please note that this answer will generate the same password if called multiple times in a row!!! There must be added Entropy between calls if you wish to use the function to assign passwords using code to multiple records at once. Still Useful though....Topsyturvy
U
-2

I use this code for generate password with balance composition of alphabet, numeric and non_alpha_numeric chars.

public static string GeneratePassword(int Length, int NonAlphaNumericChars)
    {
        string allowedChars = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789";
        string allowedNonAlphaNum = "!@#$%^&*()_-+=[{]};:<>|./?";
        string pass = "";
        Random rd = new Random(DateTime.Now.Millisecond);
        for (int i = 0; i < Length; i++)
        {
            if (rd.Next(1) > 0 && NonAlphaNumericChars > 0)
            {
                pass += allowedNonAlphaNum[rd.Next(allowedNonAlphaNum.Length)];
                NonAlphaNumericChars--;
            }
            else
            {
                pass += allowedChars[rd.Next(allowedChars.Length)];
            }
        }
        return pass;
    }
Unteach answered 2/8, 2019 at 17:48 Comment(1)
Do not use this answer. It uses the regular "Random" class and not the cryptographically secure one.Denude
D
-5

Insert a Timer: timer1, 2 buttons: button1, button2, 1 textBox: textBox1, and a comboBox: comboBox1. Make sure you declare:

int count = 0;

Source Code:

 private void button1_Click(object sender, EventArgs e)
    {
    // This clears the textBox, resets the count, and starts the timer
        count = 0;
        textBox1.Clear();
        timer1.Start();
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
    // This generates the password, and types it in the textBox
        count += 1;
            string possible = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
            string psw = "";
            Random rnd = new Random { };
            psw += possible[rnd.Next(possible.Length)];
            textBox1.Text += psw;
            if (count == (comboBox1.SelectedIndex + 1))
            {
                timer1.Stop();
            }
    }
    private void Form1_Load(object sender, EventArgs e)
    {
        // This adds password lengths to the comboBox to choose from.
        comboBox1.Items.Add("1");
        comboBox1.Items.Add("2");
        comboBox1.Items.Add("3");
        comboBox1.Items.Add("4");
        comboBox1.Items.Add("5");
        comboBox1.Items.Add("6");
        comboBox1.Items.Add("7");
        comboBox1.Items.Add("8");
        comboBox1.Items.Add("9");
        comboBox1.Items.Add("10");
        comboBox1.Items.Add("11");
        comboBox1.Items.Add("12");
    }
    private void button2_click(object sender, EventArgs e)
    {
        // This encrypts the password
        tochar = textBox1.Text;
        textBox1.Clear();
        char[] carray = tochar.ToCharArray();
        for (int i = 0; i < carray.Length; i++)
        {
            int num = Convert.ToInt32(carray[i]) + 10;
            string cvrt = Convert.ToChar(num).ToString();
            textBox1.Text += cvrt;
        }
    }
Darwin answered 28/9, 2013 at 14:3 Comment(1)
Don't use System.Random for security.Gynecology
K
-5
public string Sifre_Uret(int boy, int noalfa)
{

    //  01.03.2016   
    // Genel amaçlı şifre üretme fonksiyonu


    //Fonskiyon 128 den büyük olmasına izin vermiyor.
    if (boy > 128 ) { boy = 128; }
    if (noalfa > 128) { noalfa = 128; }
    if (noalfa > boy) { noalfa = boy; }


    string passch = System.Web.Security.Membership.GeneratePassword(boy, noalfa);

    //URL encoding ve Url Pass + json sorunu yaratabilecekler pass ediliyor.
    //Microsoft Garanti etmiyor. Alfa Sayısallar Olabiliyorimiş . !@#$%^&*()_-+=[{]};:<>|./?.
    //https://msdn.microsoft.com/tr-tr/library/system.web.security.membership.generatepassword(v=vs.110).aspx


    //URL ve Json ajax lar için filtreleme
    passch = passch.Replace(":", "z");
    passch = passch.Replace(";", "W");
    passch = passch.Replace("'", "t");
    passch = passch.Replace("\"", "r");
    passch = passch.Replace("/", "+");
    passch = passch.Replace("\\", "e");

    passch = passch.Replace("?", "9");
    passch = passch.Replace("&", "8");
    passch = passch.Replace("#", "D");
    passch = passch.Replace("%", "u");
    passch = passch.Replace("=", "4");
    passch = passch.Replace("~", "1");

    passch = passch.Replace("[", "2");
    passch = passch.Replace("]", "3");
    passch = passch.Replace("{", "g");
    passch = passch.Replace("}", "J");


    //passch = passch.Replace("(", "6");
    //passch = passch.Replace(")", "0");
    //passch = passch.Replace("|", "p");
    //passch = passch.Replace("@", "4");
    //passch = passch.Replace("!", "u");
    //passch = passch.Replace("$", "Z");
    //passch = passch.Replace("*", "5");
    //passch = passch.Replace("_", "a");

    passch = passch.Replace(",", "V");
    passch = passch.Replace(".", "N");
    passch = passch.Replace("+", "w");
    passch = passch.Replace("-", "7");





    return passch;



}
Kumquat answered 1/3, 2016 at 12:4 Comment(2)
Could you explain what your code does, and why? From reviewSapir
Code only answers with no explanation are likely to be deleted.Unmentionable

© 2022 - 2024 — McMap. All rights reserved.