C#: Generate Readable Passwords
On a recent project I found it necessary to replace the Forms Based Authentication Membership provider generated passwords with some of my own choosing, in order to make the passwords actually readable and typeable. Call me a usability-nut, but I consider passwords like t7(N4(Jm9{]M@@ and |NxXl&^ah;z4]- (both actual ResetPassword() result examples) to be neither readable nor typeable.
So I followed Mark Fitzpatrick's approach, which essentially is to take the output of the ResetPassword method and use it as the old password input for the ChangePassword method. But now I still needed a new password, so since nothing came out of a cursory Google search, I concocted the utility method below. Note that this is neither rocket surgery nor particularly brainy science and it may not suit your purpose, but it generates a random 9-10 character password from a set of 1.5+ million, which did the trick for me:
UPDATE: The random number generator in .NET isn’t all that random, unless you force it to be – see GetRandomIndex method at the bottom.
UPDATE 2: Silly me – you have to apply the .Next() method of the SAME random instance, otherwise you end up with very recognizable patterns. Removed the GetRandomIndex method and added _randomInstance member variable.
//Create a static instance of the Random class, on which to operate private static Random _randomInstance = new Random(); /// <summary> /// Generates a random, but readable, password, at least 8 characters and containing one or more /// lowercase and uppercase letters, numbers, and symbols. /// </summary> /// <returns>The random password</returns> internal static string GenerateReadablePassword() { //simple short words string[] words = new string[40] { "Rocket", "Ship", "Plane", "Train", "Boat", "Space", "Earth", "Venus", "Mars", "Moon", "Valley", "Water", "Land", "Beach", "Field", "Puppy", "Kitten", "Tiger", "Turtle", "Bird", "Texas", "Maine", "Kansas", "Florida", "Alaska", "Hand", "Head", "Foot", "Wrist", "Elbow", "Happy", "Smile", "Grin", "Humor", "Spirit", "Soccer", "Cricket", "Tennis", "Bowling", "Yummy" }; //alphabets: don't include those that can be misinterpreted for another letter/number string alphabets = "abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXY"; //numbers: exclude 0 (~= O or o), 1 (~= I, or l) and 2 (~= z) string numbers = "3456789"; //common symbols: no brackets, parentheses or slashes string symbols = "!@#$+=&*?"; //put the elements together in a random format, but don't stick an alphabet immediately after a word string[] formats = new string[18] { "{1}{2}{3}{0}", "{1}{2}{0}{3}", "{2}{3}{1}{0}", "{3}{0}{2}{1}", "{0}{2}{3}{1}", "{1}{3}{0}{2}", "{3}{1}{2}{0}", "{0}{2}{1}{3}", "{1}{3}{2}{0}", "{2}{0}{3}{1}", "{3}{1}{0}{2}", "{0}{3}{1}{2}", "{1}{0}{2}{3}", "{2}{1}{3}{0}", "{0}{3}{2}{1}", "{1}{0}{3}{2}", "{2}{1}{0}{3}", "{3}{2}{1}{0}" }; //combine the elements string password = string.Format(GetRandomString(formats), //random format GetRandomString(words), //0 GetRandomStringCharacter(alphabets), //1 GetRandomStringCharacter(numbers), //2 GetRandomStringCharacter(symbols) //3 ); //post fill the password with numbers as necessary while (password.Length < 8) { password += GetRandomStringCharacter(numbers); } return password; } /// <summary> /// Gets the random string character. /// </summary> /// <param name="inputString">The input string.</param> /// <returns></returns> private static char GetRandomStringCharacter(string inputString) { return inputString[_randomInstance.Next(0, inputString.Length)]; } /// <summary> /// Gets the random string. /// </summary> /// <param name="inputStringArray">The input string array.</param> /// <returns></returns> private static string GetRandomString(string[] inputStringArray) { return inputStringArray[_randomInstance.Next(0, inputStringArray.Length)]; }
Labels: c#, howto, me-me-me, moss, programming, sharepoint
3 Comments:
This comment has been removed by the author.
By Lalo, at Thursday, June 23, 2011 1:16:00 PM
I created a variant of your code, which uses 3 custom words easy to remember for the user(taken from the name or current city).
This variant doesn't use symbols or upper case letters, instead puts two digits spread apartlike:
y96mexico
3apedro4
59mdelossantos
mexico75k
The code is here
(the description is spanish, but the code is still english):
http://laloah.wordpress.com/2011/06/23/generador-de-contrasenas-faciles-de-recordar-en-c/
By Lalo, at Thursday, June 23, 2011 1:18:00 PM
Nice that you liked it and that you found a reuse for it. Your version is probably plenty good for casual passwords...
By Oskar Austegard, at Thursday, June 23, 2011 1:23:00 PM
Post a Comment
<< Home