Over a year ago, I've created a small form-based software.

It's purpose, as the title states, is random string generation.

It has options to combine numerical, small caps, large caps and special characters within the ASCII character set (94 in total). It will have support for UTF-8 soon (and will be marked as optional/experimental, because some websites do not allow anything but ASCII for passwords).

It uses RNGCryptoServiceProvider class and it's methods (GetBytes() and ToString()) to produce an output.

If we select all options (entire ASCII), we have 94 characters. We specify we want our output to be 64 characters long.

Our strength in bits is: 94^64 or log (base 2, 94) * 64 = 419

EDIT: Example: 4Ed(R{MQ_U9pQ#?9k'V2p1bpW+UrEBkebif9w'Qsp>n7i~PF,]DCdV18sqilN(ou

Question 1: Is it safe to use this output as a strong password?

Question 2: Is there anything else I should implement to enhance security?

Programming language: C#

IDE: SharpDevelop 4.4

Framework: .NET 4.5

  • At this point, it is trully resistant to bruteforce since it is way longer than usual password and it uses special characters, numbers and uppercases. If you are a hundred percent sure that RNGCryptoServiceProvider is truly random and that the output cannot be guessed, then yes it is safe to use this output as a strong password (resistant to bruteforce, dictionnary attacks). No, I don't think you should add anything to this generation.
    – Shashimee
    May 30, 2017 at 8:32
  • 1
    How do you convert the random bytes to ASCII characters?
    – Sjoerd
    May 30, 2017 at 8:52
  • @Sjoerd I cast the characters into an array, when each of the checkboxes are selected (small and/or large caps, number and special characters). The array is called char, b are bytes from RNGCryptoService. ... { result.Append(chars[b % (chars.Length)]); } tbOutput.Text = Convert.ToString(result); May 30, 2017 at 9:32
  • What's the point in having an output strength larger than 200 bits or so? And why do you want to add non-ascii support? May 30, 2017 at 10:15
  • Reducing a byte modulo a non-power-of-two leads to biased output. I'd use a 64-bit integer instead, reducing the bias. See How can I generate random alphanumeric strings in C#? for my implementation. May 30, 2017 at 10:17

3 Answers 3


The naive way of doing this:

... {
    result.Append(chars[b % (chars.Length)]);
tbOutput.Text = Convert.ToString(result);

will produces a password with non uniform character distribution, which is a weakness.

One way to generate unbiased output (untested, and I'm not a C# programmer, so some of the syntax might be off), note that this is probably not the most efficient method for doing this:

RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); 
System.Text.StringBuilder result = new System.Text.StringBuilder();

// assumption: chars.Length < ulong.MaxValue
ulong bound = ulong.MaxValue - (ulong.MaxValue % chars.Length);

while (result.Length < desiredPwLen) {
    // assumption: ulong is 64-bit
    ulong rndNum;
    do { 
        byte[] rndBytes = new byte[8]; // assumption: 1 byte is 8 bits, so 8 bytes is 64 bits
        rndNum = BitConverter.ToUInt64(rndBytes, 0);
    } while (rndNum >= bound); // rndNum above bound is biased, so we discard them, and roll again

    result.Append(chars[rndNum % chars.Length]);
string password = result.ToString();

Answer to your Questions:

  1. Is it safe to use this output as a strong password?

Probably yes, while your password encoding method has the weakness I mentioned above, if the length of your password are long enough, then it would have compensated for the bias.

  1. Is there anything else I should implement to enhance security?

I've provided above an improvement that fixes the bias.


On a security point of view, what you describe looks ok, provided you actually ask a character from a set (said differently get a random int in the range 1-94 for full set of size of actual set for a subset).

On a usability point of view, what you describe is not far from the password generator of the excellent Keypass. In fact, they provide different sets of special characters:

  • you can include separately -, _, and space
  • parenthesis have their own class ((){}[]<>)
  • all other special characters are in another class

I assume they had to implement that because some (poorly designed) security rules require it.

As advanced features, they also allow:

  • each character may only appear once in the password string
  • do not allow similar characters (0 and O, 1 and l)

Here again it had to be implemented to cope with stupid security rules.

It is up to you do include or not those rules, it mainly depends on the expected usage.

You could also look at other existing password generators to see if other restrictions could be relevant.


As serge hinted at, whether it is "safe" depends on what you do with it. I've recently had some pain dealing with ensuring that generated passwords will work when pasted into config files or even mail-merged into .bat files. It turns out there is a lot of badly written software out there which provides no means for safely escaping strings and I've seen problems with quotes, IO redirection characters and more.

Regarding the 'classes' - these rules usually exist to encourage human beings to pick better passwords (but I've not seen any serious research on whether they actually work). This negates the possibility of using a smaller "safe" character set (lowercase + uppercase + digits) with a longer length to achieve the same entropy.

Without seeing your code, I have some reservations about your estimate of the entropy. You seem to be using RNGCryptoServiceProvider.toString() on a binary string but the documentation reveals little about how this conversion is done. While I would consider anything longer than 10 characters (and requiring rules such as classes) too difficult to remember, there are contexts where there is a required minimum complexity.

  • This software is meant for elevating the bar on password security. You mentioned that the output would be difficult to remember. That is the actual goal, to discourage such actions. It promotes creating a password that would be used with a password manager. May 30, 2017 at 15:34

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .