C# – How to generate random password

This article delivers proposal of algorithm to generate random passwords or actually random strings which are generated in safe manner and can be used as passwords, discount codes etc. Also, it is configurable, so that you can easily define expected length of string, pool of available characters or minimal number of occurrences of particular elements. All is encapsulated within a class, ready to reuse in your project. In this articles we’ll go through small code snippets and describe them in details, but full class can be also found at the end.

Everything starts with defining a class and including required namespaces with using keyword. For the purpose of this post we’ll call the class PasswordGenerator, but feel free to rename it, so that it fits your naming convention.

Now, let’s create private enum called CharType which defines types of characters which will be used when generating new strings. By default we’ve got lowercase letters, uppercase letters, digits and special chars. Having such enumeration type will help us keeping code more readable.

Next we’ll define few public properties which purpose is configuration of generator’s object. Using them it is possible to set expected length of output string and also specify minimum occurrences of particular char types. For example if you require generated password to have minimum 1 digit, then set value of MinDigits to 1.

For each group it is necessary to specify actual characters which are available. All these are stored in private _chars dictionary. Below collections can be freely changed depending on your own demands.

When processing new password it is needed to keep current state of minimal requirements. Algorithm generates result character by character in random manner, so in every iteration it has to know how many of particular types are still to be drawn. For example if it is configured to have minimum 3 digits in an output, algorithm needs to control it to make sure initial conditions will be met. Such state is stored in private dictionary called _outstandingChars.

At the beginning of every string generation it is necessary to reset previously described state dictionary. For such purpose we’ve got ResetOutstanding function which sets values to the ones defined in the configuration properties.

During consecutive chars generation algorithm has to care about updating state object. For example if special character is drawn, then _outstandingChars[CharType.Special] should be decreased by one. So that, code is kept clean let’s encapsulate this logic in DecreaseOutstanding function. As you can see below, there is additional condition which checks whether value is greater than zero. The reason is we just need that information until there are no outstanding characters of particular type, which means we need information until _outstandingChars[type] is 0. The function receives type of character in parameter, so that it can handle all types defined in CharType enum.

Another function to be implemented is DrawChar which takes variable number of CharType arguments and returns a single char. These input decide which type of characters are taken into consideration when drawing another char. If nothing is passed then function looks at all types. A random index of item to be returned from available chars collection is made with RandomNumberGenerator class which is cryptographic random number generator (in opposite to Random class). As a result of what it is safe to be used where security is a concern. As you can see below DrawChar function calls previously described DecreaseOutstanding which happens after result char is known.

Last part of our class is Generate function. In opposite to previous ones, it’s public and it’s the one which returns fully generated password. At the beginning it checks whether configured properties are valid, which means whether expected string length is greater than or equal to sum of minimum number of lowercases, uppercases, digits and specials. If it’s not then argument exception is being thrown. Then ResetOutstanding is called which has been described above and new StringBuilder object is instantiated. After that a for loop is started which does the same number of iterations as it is set in Length property. In the other words, every loop iteration draws one character. Within for’s body there are two possible routes. First one takes place when number of outstanding items equals to number of outstanding chars to be drawn. It’s easy to describe on an example: if expected password length is 4, minimum number of uppercases is 2 and minimum number of digits is 2, then we cannot look for character within all types. Scope of search has to be narrowed down just to uppercases and digits. Such decision is being made on each iteration validating with current state of outstanding chars. First route calls DrawChar function with argument which is an array of outstanding types. A result is being appended to password object. Second route (inside else block) is situation where number of chars still to be generated is greater than number of outstanding items in _outstandingChars object. In such situation algorithm doesn’t need to filter out the random pool as that stage any character is valid.

Full class code:

Below is an example of usage where expected password is 8 characters long and contains at least 1 lowercase, 1 uppercase, 1 digit and 1 special.