Generating a random password is simple, but generating a secure one is harder if you don’t know what you’re doing. When I looked through the password generation algorithm at work, I found (and fixed) several vulnerabilities and bugs, one of which allowed a remote attacker to crack any known account with a generated password in a couple of minutes.
The password generator itself was just inadequate, but an API misunderstanding made it extremely severe:
The following method signature was used for the password generation:
public static string GenerateReadablePassword(int length, int seed)
On reading “int seed”, your head should be ringing with warning bells. More on that later. The real kicker was the invocation:
string Password = GenerateReadablePassword(10, DateTime.Now.Millisecond);
If you’re familiar with the C# API, you’re likely rolling on the floor about now. Otherwise, the part about
DateTime.Now will give you the shivers. And then you realize that this wouldn’t compile without a cast unless
DateTime.Now.Millisecond is an int or narrower, which would make for a pretty lousy timestamp. Oh yes… This is the number of milliseconds into the current second.
A new account got one of 1000 possible passwords, for an effective “two characters, no uppercase or symbols” policy.
Even if this had been the proper epoch time in milliseconds, it still wouldn’t have been secure. There are only 86 400 000 milliseconds in a day, and only 28 million of them are during office hours. If you can narrow it down to a specific hour, you have 3 million possible ones. And if you can hear the beep of the user’s e-mail client as the (plain-text) password e-mail is received, you’re back down to a few thousand.
Going from a timestamp to an actual high quality pseudo-random seed is better, but it still doesn’t win any prizes. You then have a best case of 232 possible passwords regardless of how long you specify the password to be.
Another example of this, included in our source code, was a copy of the first google hit for “generate random password C#”. I won’t link to it in case I increase its standing. It’s a code sample that claims that it “Generates random password, which complies with the strong password rules”, and here is an excerpt:
// Generate 4 random bytes. RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); rng.GetBytes(randomBytes); // Convert 4 bytes into a 32-bit integer value. int seed = (randomBytes & 0x7f) << 24 | randomBytes << 16 | randomBytes << 8 | randomBytes; // Now, this is real randomization. Random random = new Random(seed);
No, this is not real randomization, this is 31 bits of high quality randomness sprinkled with a snake oil vinaigrette. Any password of any length generated by this function will not be more secure than a proper 5-character alphanumeric password. You have a secure PRNG right there! Use it!