.NetGurus

Diğer Yazılar

Google a Ekle

Add to Google



Generating Random Text/String (Member Code, Passwoed etc...)

Bu makalenin Türkçe versiyonunu görmek için Tıklayınız 

Today, we will learn how to generate random text -in order to be used as password, security code, activation code, member code or CAPTCHA code etc- and the key points that we should pay attention. I advise you to read the "Random In .Net" before this article but it is in Turkish yet :(

Random Text Generation job is generally accomplished by appending randomly selected characters from a character set. You can determine your own rules on how to generate text according to the different security needs. For example; you may say the text should have at least 2 alpha-numeric characters or..

In this article let' s try to generate random member code. The reason why to generate member code instead of password or other things is the uniqueness-singularity need of the membership code. Because you cannot give the same member code to 2 or more users. Therefore we should generate almost unique codes. Beside this uniqueness need-rule we have one another rule which is the member codes should be unpredictable.

The processes needed to generate unique member codes are,

  • 1. Determining the universal character set: In this first step, we should determine the characters that may be in the result member code. Because the size of the character set will change the probability of the code's being unique. We should also determine the length of the code in this step. According to my own idea and experiences the universal set of the codes that may be generated should be at least 100 times greater than the target member number. For example; if you target that you will have 10000 members and you have a character set that has 30 characters (ABCDEFGHKLMNPQRSTVUWXYZ2345789) then the code must be at least 5 characters (10000 * 100 < 30 to the power 'length'). In this way we have extra room after 10000 members. Bu the most important point is to generate code that is not given before will be more simple.
  • 2. Generating the code: Generating the code that has a pre-determined lenght. This is the most important part and this asrticle focuses on this step. Dont forget that we must generate the code in such a way so that the codes will not repeat.
  • 3. Uniqueness Check: In this step will check to ensure that the code was not given before. If the code is given before we should generate a new one and check that again and repeat these steps until the code is unique. This check is generally done by querying against the database. You can do this through an infinite loop, i mean generating and checking process. But to reach the quality in our code we should better limit the loop (100 may be enough) and after all if we dont have a unique code, throw an exception. By this way we can be aware of something going wrong.

  • Now, Generating The Random Text
    As I mentioned before, Random Text Generation is generally accomplished by appending randomly selected characters from a character set. And selecting a random character from a set is done by using a random number(integer). For example, to select a character from a set of 20 characters, we should get a random integer from 1 to 20 and get the character that is in the rank of our number in the character set. The most critical thing is I think, to get the random number.

    To generate random text we should generate random numbers, repeatedly. And this makes it harder... Lets see why though an example.

     

    Örnek

    In this sample we will try to get random numbers in 7 different ways from a set of 20 characters which are ABCEFKNMPRSTUYZ13579 . The code will be 3 characters in lenght and  We will generate 8000(20*20*20) codes. So we can see the success in uniqueness, difference.

    Difference ratio: Number of different code / Number of generated codes.

    Uniqueness ratio: Number of unique code / Number of generated codes.

    Assume that, we have generated 10 numbers which are; AB3, 27K, 8UK, M8E, AB3, K6D, M8E, P3L, M8E, 63A
    here we have 7 different code which are: AB3, 27K, 8UK, M8E, K6D, P3L, 63A so the difference ratio is 7/10 = 0.7
    an have 5 unique code which are: 27K, 8UK, K6D, P3L, 63A so the uniqueness ratio is 5/10 = 0.5

    After all, now lets look at the methods.

     

    Metod 1 Elapsed
    Time
    Difference
    Ratio
    Uniqueness
    Ratio

    Dim sb As New StringBuilder

    Dim CharArray As Char() = Chars.ToCharArray

    Dim startTime As DateTime = Now

    For j As Integer = 1 To IterationNumber

           sb.Length = 0

           For i As Integer = 1 To CodeLength

                  Dim Rndm As New Random

                  Dim CharIndex As Integer = CInt(Int((CharArray.GetUpperBound(0) * Rndm.NextDouble()) + 1))

                  sb.Append(CharArray(CharIndex))

           Next

           AddToResults(sb.ToString())

    Next

    187ms 0,00225 0,000875
    Metod 2 Elapsed
    Time
    Difference
    Ratio
    Uniqueness
    Ratio

    Dim sb As New StringBuilder

    Dim CharArray As Char() = Chars.ToCharArray

    Dim startTime As DateTime = Now

    For j As Integer = 1 To IterationNumber

           sb.Length = 0

           Dim Rndm As New Random

           For i As Integer = 1 To CodeLength

                  Dim CharIndex As Integer = CInt(Int((CharArray.GetUpperBound(0) * Rndm.NextDouble()) + 1))

                  sb.Append(CharArray(CharIndex))

           Next

           AddToResults(sb.ToString())

    Next

    93ms 0,000375 0
    Metod 3 Elapsed
    Time
    Difference
    Ratio
    Uniqueness
    Ratio

    Dim sb As New StringBuilder

    Dim CharArray As Char() = Chars.ToCharArray

    Dim startTime As DateTime = Now

    Dim Rndm As New Random

    For j As Integer = 1 To IterationNumber

           sb.Length = 0

           For i As Integer = 1 To CodeLength 

                 Dim CharIndex As Integer = CInt(Int((CharArray.GetUpperBound(0) * Rndm.NextDouble) + 1))

                 sb.Append(CharArray(CharIndex))

           Next

           AddToResults(sb.ToString())

    Next

    15ms 0,593125 0,319
    Metod 4 Elapsed
    Time
    Difference
    Ratio
    Uniqueness
    Ratio

    Dim sb As New StringBuilder

    Dim CharArray As Char() = Chars.ToCharArray

    Dim startTime As DateTime = Now

    For j As Integer = 1 To IterationNumber

          sb.Length = 0

          For i As Integer = 1 To CodeLength

                Randomize()

                Dim CharIndex As Integer = CInt(Int((CharArray.GetUpperBound(0) * Rnd()) + 1))

                sb.Append(CharArray(CharIndex))

          Next

          AddToResults(sb.ToString())

    Next

    78ms 0,136625 0,003
    Metod 5 Elapsed
    Time
    Difference
    Ratio
    Uniqueness
    Ratio

    Dim sb As New StringBuilder

    Dim CharArray As Char() = Chars.ToCharArray

    Dim startTime As DateTime = Now

    For j As Integer = 1 To IterationNumber

            sb.Length = 0

            Randomize()

            For i As Integer = 1 To CodeLength

                   Dim CharIndex As Integer = CInt(Int((CharArray.GetUpperBound(0) * Rnd()) + 1))

                   sb.Append(CharArray(CharIndex))

            Next

            AddToResults(sb.ToString())

    Next

    31ms 0,092125 0
    Metod 6 Elapsed
    Time
    Difference
    Ratio
    Uniqueness
    Ratio

    Dim sb As New StringBuilder

    Dim CharArray As Char() = Chars.ToCharArray

    Dim startTime As DateTime = Now

    Randomize()

    For j As Integer = 1 To IterationNumber

            sb.Length = 0

            For i As Integer = 1 To CodeLength

                    Dim CharIndex As Integer = CInt(Int((CharArray.GetUpperBound(0) * Rnd()) + 1))

                    sb.Append(CharArray(CharIndex))

            Next

            AddToResults(sb.ToString())

    Next

    15ms 0,589 0,30925
    Metod 7 Elapsed
    Time
    Difference
    Ratio
    Uniqueness
    Ratio

    Dim sb As New StringBuilder

    Dim CharArray As Char() = Chars.ToCharArray

    Dim startTime As DateTime = Now

    For j As Integer = 1 To IterationNumber

           sb.Length = 0

           For i As Integer = 1 To CodeLength

                  Dim buffer(0) As Byte

                  Dim rngSp As New System.Security.Cryptography.RNGCryptoServiceProvider

                  rngSp.GetBytes(buffer)

                  Randomize(Convert.ToInt32(buffer(0)))

                  Dim CharIndex As Integer = CInt(Int((CharArray.GetUpperBound(0) * Rnd()) + 1))

                  sb.Append(CharArray(CharIndex))

           Next

           AddToResults(sb.ToString())

    Next

    140ms 0,591625 0,315625


     

    Evaluation Of the Methods

    In method 1, the Random object is generated before each character and without giving a seed value. Because we did not give a seed value, the random object uses the system time as the seed. And because there is so little time between the iteration of the loop the random numbers are generated using same or similar seeds. And this causes getting same integer which causes most of the characters to be same. For this reason, the difference and uniqueness ratio is low.

    In method 2, the Random object is generated before each code again without giving a seed value. This time the characters are different because the random object begins with a number derived from the seed and then follows a series of random numbers. But although the characters in a code differ the codes are similar or same. And this causes the difference and uniqueness ratio to be low.

    In method 3, a random object is created at the beginning and then the same object used for each number without assigning a seed again. This causes to get random numbers for all codes. So the difference and uniqueness ratio is high. But if you notice the ratios are not still close to 1.

    In method 4,  we have used VbMath object instead of Random object. Like in method 1, the seed is assigned a system time derived value before each character by calling Randomize method(without prameter). Randomize method (without the parameter) generates the seed value using both the current seed and the system time. So the generated numbers differ more than they did in method 1. But still the ratios are very low.

    In method 5, the seed is assined before each code not character. This causes to get same codes having different characters. Again the ratios are too low as they were in method 2.

    In method 6, Randomize is called once at the very begining of the code block. Then the Rnd function follows a series of random numbers. By this way we get well arranged random number as we did in mehod 3. But the ratios are again far form 1.

    The method 7 is different than the others. At the first glance this method looks like method 4. But in this method the Randomize method is called with a parameter that is get from the RNGCryptıServiceProvider object's GetBytes method. The system time(clock) is not used through the generation of the seed used in the Rnd function. As you see the ratios upon the generated codes are as high as best of the preciding ones. And if you notice, the RNGCryptıServiceProvider is created before each character and despite this the numbers are not similar. This means that the RNGCryptıServiceProvider is independent from system time(clock). So the generated codes using this object is more unpredictable than the others.

    As you see; as the number of calling the Randomize (in methods 4,5,6,7) and the number of creation of the Random object increases the time elapsed to generate codes also increases. In method 7, the usage of the RNGCryptıServiceProvider object has increased the time far more.

    I know there are better methods than the methods described here. But even the best methods used in this sample cannot exceed the 0.32 value of Uniqueness ratio and 0.6 value of Difference ratio. And I think this supports my idea of setting the wideness of the universal set to 100 times greater than the targer set :)

    Last
    In this article and sample you have seen different ways of using random objects and methods. To say the truth some of them(method 1,2,4,5) may not be called as methods because they were wrong. But these methods help us to understand "do not makes" of random jobs. And after all now you get the point and I think you can drive your own way in this subject.

    The methods described in this article is in the attached project file.

    RandomCodeGenerator_en.zip (79,56 kb)


    Posted by yavuz on 14 Haziran 2008 Cumartesi 00:36
    Permalink | Yorumlar (0) | Post RSSRSS comment feed

    Yorumlar

    Yorum ekle


    (Gravatar simgesini gösterecek)

      Country flag

    biuquote
    • Yorum
    • Canlı önizleme
    Loading