When you think ASP, think...
Recent Articles
All Articles
ASP.NET Articles
ASPFAQs.com
Message Board
Related Web Technologies
User Tips!
Coding Tips
Search

Sections:
Book Reviews
Sample Chapters
Commonly Asked Message Board Questions
JavaScript Tutorials
MSDN Communities Hub
Official Docs
Security
Stump the SQL Guru!
Web Hosts
XML
Information:
Advertise
Feedback
Author an Article
Jobs

ASP ASP.NET ASP FAQs Message Board Feedback ASP Jobs
 
Print this Page!
Published: Wednesday, October 12, 2005

Generating Random Passwords with ASP.NET

By Scott Mitchell


Introduction


In one of the consulting projects I'm working on a website that has user accounts (like most every non-trivial Web application). User accounts for this site can be created in one of two ways: by the user himself, in which case that user provides their email address and password; or by the user's boss, in which case the boss simply provides his employee's email address. The system then creates a random password for the employee and emails this information to said employee. Upon first logging in to the site, the employee must change the random password.

One of the challenges of this task involved writing the code that would generate a random password. When I needed to accomplish this, I headed over to 4Guys and searched for the phrase "random password". Sadly, the only articles on creating a random password here on 4Guys are from the antequated days of classic ASP, meaning I ended up writing my own ASP.NET random password generator. (This need is moot with ASP.NET 2.0's new Membership API; in fact, with 2.0 you can simply call Membership.GeneratePassword(length, numberOfNonAlphaNumericCharacters).)

The purpose of this article is to provide a random password generator for ASP.NET. There are a number techniques for creating a random password, and these techniques are explored, along with source code. Read on to learn more!

- continued -

Quick and Dirty Random Password Generation Using GUIDs


The simplest random password generation scheme with ASP.NET is to return a portion of a GUID. A GUID is a Globally Unique ID, a 128-bit number that can be quickly generated with one method call, producing a hexidecimal string that can be used as a random password. To create a new GUID, use the System.Guid structure's NewGuid() method. Then, the .ToString() method can be used to create a string version of this. Here's some example code:

' VB.NET
Dim guidResult as String = System.Guid.NewGuid().ToString()

// C#
string guidResult = System.Guid.NewGuid().ToString();

Each time this code is run a new, globally unique number will be generated. Here's the output of this code when run five times (you can refresh the page and you'll see five new results):


2c7bd746-13d1-4d71-8fce-43a7b68e0753
0b3693cf-4b68-404f-89c4-ad38e61e8569
d714582a-308f-48a2-b5e5-a29416e8c577
883e9609-d5e9-4d65-aed4-926ef368a7e4
7742db71-f525-4154-8a9b-cf86fad6da8d

Typically I strip out the hyphens (-) and then return the first n characters of the GUID. To generalize this technique, let's create a method called GetRandomPasswordUsingGUID(length) that accepts as input the length of the random password and returns the first length characters of a GUID (with the hyphens removed).

' VB.NET
Public Function GetRandomPasswordUsingGUID(ByVal length as Integer) as String  
  'Get the GUID
  Dim guidResult as String = System.Guid.NewGuid().ToString()
  
  'Remove the hyphens
  guidResult = guidResult.Replace("-", String.Empty)
  
  'Make sure length is valid
  If length <= 0 OrElse length > guidResult.Length Then
    Throw New ArgumentException("Length must be between 1 and " & guidResult.Length)
  End If
  
  'Return the first length bytes
  Return guidResult.Substring(0, length)
End Function


// C#
public string GetRandomPasswordUsingGUID(int length)
{
  // Get the GUID
  string guidResult = System.Guid.NewGuid().ToString();
  
  // Remove the hyphens
  guidResult = guidResult.Replace("-", string.Empty);
  
  // Make sure length is valid
  if (length <= 0 || length > guidResult.Length)
    throw new ArgumentException("Length must be between 1 and " + guidResult.Length);
  
  // Return the first length bytes
  return guidResult.Substring(0, length);
}

The following shows this output of this method when called with length values of 5, 10, and 15, respectively. (Again, you can refresh the page and you'll see different random passwords, as each time System.Guid.NewGuid() is called, a new, unique identifier is created.)


Random password of length 5:611a7
Random password of length 10: 83cd32e32c
Random password of length 15: fe3fec55f71f41c

A More Robust Random Password Generator


This nice thing about the GUID approach for creating random passwords is that it is easy to implement and use. However, it leaves you with no control over the resulting output, and only generates passwords with alphanumeric characters (and only with letters ranging from a to f). What if you want to impose certain security guidelines, such as requiring a random password with a certain number of non-alphanumeric characters, or a random password that uses a wider range of random characters (such as drawing from the entire alphabet)? Or what if, for some reason, you didn't want numbers in the random password? Or you wanted to make the password case-sensitive (again, with the GUID approach you only have six letters and they are all lowercase).

A more robust solution would be to create a GeneratePassword(length, numberOfNonAlphanumericCharacters) password generator that mirrors the behavior of the ASP.NET 2.0 Membership API's method with the same name. This method - which is what you should use if you're using 2.0 - allows the page developer to specify the random password's length and the number of non-alphanumeric characters. Furthermore, it uses the RNGCryptoServiceProvider class, which is a cryptographically strong random number generator. (In English, that means that the algorithm does not suffer from having characteristics which make it possible to better guess upcoming random numbers based on past random numbers produced.)

If you are stuck in the ASP.NET 1.x world like yours truly, then you'll need to roll your own GeneratePassword() method. But wait, why duplicate the efforts of the ASP.NET team? Why not just use their code? With a little help from Reflector this is a cinch. Here is the code for the Membership.GeneratePassword(length, numberOfNonAlphanumericCharacters) method, along with a live demo.

' VB.NET
Function GeneratePassword(ByVal length As Integer, _
                 ByVal numberOfNonAlphanumericCharacters As Integer) As String
  'Make sure length and numberOfNonAlphanumericCharacters are valid....
  '... checks omitted for brevity ... see live demo for full code ...
  
  Do While True
    Dim i As Integer
    Dim nonANcount As Integer = 0
    Dim buffer1 As Byte() = New Byte(length  - 1) {}
    
    'chPassword contains the password's characters as it's built up
    Dim chPassword As Char() = New Char(length  - 1) {}
    
    'chPunctionations contains the list of legal non-alphanumeric characters
    Dim chPunctuations as Char() = "!@@$%^^*()_-+=[{]};:>|./?".ToCharArray()

    'Get a cryptographically strong series of bytes
    Dim rng as New System.Security.Cryptography.RNGCryptoServiceProvider
    rng.GetBytes(buffer1)
        
    For i = 0 To length - 1
      'Convert each byte into its representative character
      Dim rndChr As Integer = (buffer1(i) Mod 87)
      If (rndChr < 10) Then
        chPassword(i) = Convert.ToChar(Convert.ToUInt16(48 + rndChr))
      Else
        If (rndChr < 36) Then
          chPassword(i) = Convert.ToChar(Convert.ToUInt16((65 + rndChr) - 10))
        Else
          If (rndChr < 62) Then
            chPassword(i) = Convert.ToChar(Convert.ToUInt16((97 + rndChr) - 36))
          Else
            chPassword(i) = chPunctuations(rndChr - 62)
            nonANcount += 1
          End If
        End If
      End If
    Next
    
    If nonANcount < numberOfNonAlphanumericCharacters Then
      Dim rndNumber As New Random
      For i = 0 To (numberOfNonAlphanumericCharacters - nonANcount) - 1
        Dim passwordPos As Integer
        Do
          passwordPos = rndNumber.Next(0, length)
        Loop While Not Char.IsLetterOrDigit(chPassword(passwordPos))
        chPassword(passwordPos) = _
                chPunctuations(rndNumber.Next(0, chPunctuations.Length))
      Next
    End If
    
    Return New String(chPassword)
  Loop
End Function
[View the Live Demo!]

Note: I tweaked the GetPassword() method in that I removed some of the potentially dangerous non-alphanumeric characters (namely # and &). ASP.NET 2.0 does a check to ensure that the randomly generated password can't be used in a cross-site scripting attack, and the characters it checks for is <, #, and &. I just removed these to avoid needing to include the code for the XSS check...

Conclusion


In this article we examined two techniques for generating random passwords using ASP.NET. In the first technique we used a GUID, stripped out the hyphens, and then returned the first length characters of the GUID. This approach is a quick and easy way to generate a random password. However, it lacks in sophistication in that its potential pool of characters is rather limited (a-f and 0-9).

A more robust and elegant random password generator can be seen in ASP.NET 2.0's Membership.GeneratePassword() method. If you are using 2.0 most definitely take advantage of this method. If you are still using ASP.NET 1.x, however, you'll need to create your own password generator if you need an approach more robust than the GUID approach first examined. In this article we saw how to 'copy' 2.0's GeneratePassword() method using Reflector.

Happy Programming!

  • By Scott Mitchell



  • ASP.NET [1.x] [2.0] | ASPMessageboard.com | ASPFAQs.com | Advertise | Feedback | Author an Article