views:

305

answers:

6

I have a project in the works, and I'll need to associate a passcode with an item.
The password should be completely non sequential or easily guessable, yet simple to remember.

I thought about doing something like this.

string rand = System.Guid.NewGuid().ToString();
rand.Substring(0,3);

Return the first 4 digits of a GUID.

I was wondering if anyone else had something similar they worked on, and potentially a better solution than this.

Security is important as we don't want people to be able to guess the digits, however this isn't dealing with money or personal data so it doesn't have to be NSA capable :)

Thanks guys!

+1  A: 

I would suggest using the RandomNumberGenerator class, it will give you better results than GUID generation.

http://msdn.microsoft.com/en-us/library/system.security.cryptography.randomnumbergenerator%28VS.71%29.aspx

nullptr
+2  A: 

If you're thinking of a PIN-style code, I'd suggest using all digits (or possibly all letters) rather than the first four characters of a GUID. Many people are familiar with all-digit PINs; I suspect having a letter mixed in there might make it less easy for them to remember. But I have no evidence to back this up!

If a PIN is sufficient, you could just call Random.Next(0, 9) four times and concatenate the results. Be sure to eliminate "not random enough" results like when all four digits are the same! As unknown says, you can get statistically more random results from the crypto classes, but over four digits that's unlikely to matter.

itowlson
Agree, to add, randomness is very dependent on the seed. Use a good way of seeding and the Random.Next() will not follow a pattern. I learnt my lesson of using DateTime.Now.Millisecond as the seed which proved to be fatal.
o.k.w
+2  A: 

ASP .Net Membership provider has a method that generate passwords that could be helpful. http://msdn.microsoft.com/en-us/library/system.web.security.membership.generatepassword.aspx also you can look at the source code of the providers to see what they do internally http://weblogs.asp.net/scottgu/archive/2006/04/13/442772.aspx

Emmanuel
+1  A: 

What characteristics must your password have? If your primary criterion is memorability, then I would suggest something like this:

Go find a large corpus of English text and get all unique words of five or less letters out of it. Now, for any particular new password, randomly select three or four of these words. Then, at the end, add a random two-digit number.

How many passwords? Well, one hundred for the two-digit number, times (number of distinct words) to the power of (number of random words in a password). So if you take the base-two log of that, you'll get the entropy that you could have in these passwords -- if your random number generator is good enough.

In practice, if you lock accounts after a few bad password tries, then you'll foil attackers effectively as long as there are at least a few thousand possible passwords.

Ian
A: 

I think it's very difficult to achieve it.

A: 

If you want something that will provide your users with something that is relatively easy to remember, you can always use my PronouncablePasswords class.

I originally wrote this as an experiment in generating random passwords that were pronounceable by the end-user, rather than being complete gobbledygook. Of course, this reduces the security of the password, but for your purposes it sounds like this would be sufficient.

The function simply alternates between a vowel and a consonant (with some rudimentary exception rules), with "weighting" on the letters chosen based upon their occurrence in the English language. Note that this is by no means perfect, but it does do "what is says on the tin"!

Code:

using System;
using System.Collections.Generic;
using System.Text;

namespace PronouncablePasswords
{
    class PasswordGenerator
    {
        //string vowels = "aeiou";
        //string consonants = "bcdfghjklmnprstvwxyz";

        /*
           The reason for the duplicate letters is to add "weighting" to certain letters to allow them more chance
           of being randomly selected.  This is due to the fact that certain letters in the English language are more
           frequently used than others.

           The breakdown of usage is as follows (from most frequent to least frequent):
            1.  E                   (7)
            2.  T                   (6)
            3.  A, O, N, R, I, S    (5)
            4.  H                   (4)
            5.  D, L, F, C, M, U    (3)
            6.  G, Y, P, W, B       (2)
            7.  V, K, X, J, Q, Z    (1)
        */

        string vowels = "aaaaaeeeeeeeiiiiiooooouuu";
        string consonants = "bbcccdddfffgghhhhjklllmmmnnnnnpprrrrrsssssttttttvwwxyyz";

        string[] vowelafter = {"th", "ch", "sh", "qu"};
        string[] consonantafter = { "oo", "ee" };
        Random rnd = new Random();

        public string GeneratePassword(int length)
        {
            string pass = "";
            bool isvowel = false;

            for (int i = 0; i < length; i++)
            {
                if (isvowel)
                {
                    if (rnd.Next(0, 5) == 0 && i<(length-1))
                    {
                        pass += consonantafter[rnd.Next(0, consonantafter.Length)];
                    }
                    else
                    {
                        pass += vowels.Substring(rnd.Next(0, vowels.Length), 1);
                    }
                }
                else
                {
                    if (rnd.Next(0, 5) == 0 && i<(length-1))
                    {
                        pass += vowelafter[rnd.Next(0, vowelafter.Length)];
                    }
                    else
                    {
                        pass += consonants.Substring(rnd.Next(0, consonants.Length), 1);
                    }
                }
                isvowel = !isvowel;
            }
            return pass;
        }
    }
}
CraigTP
That's pretty darn cool! What would it take to generalize it to weighted random regular expressions?
Ian