AspAlliance.com LogoASPAlliance: Articles, reviews, and samples for .NET Developers
URL:
http://aspalliance.com/articleViewer.aspx?aId=703&pId=-1
A Simple Passphrase Generator
page
by Richard Dudley
Feedback
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 41494/ 52

Background

Download Code

I first developed this component for a private web application. Users do not self register, but are approved for access by their service contacts. We then set up the user’s account, assigning a randomly generated passphrase as part of the account setup. When the user logs in for the first time, they are required to change their passphrase to one of their own choosing that meets certain complexity requirements. If a user forgets his or her passphrase, we create a new one using this control, and the user can then log in, but is forced again to change the passphrase. Passphrases are salted and hashed before storing them in the database, and comparisons at login are made against the hash, rather than the passphrase. Although this component was originally designed for a web-based application, it could easily be modified for use as a password generator run on desktop or mobile platforms, or for any other use subject only to your imagination.

Why Passphrases

Perhaps first we should ask "What is a passphrase?" The Wikipedia may say it best:

A passphrase is a collection of 'words' used for access control, typically used to gain access to a computer system. (1)

Passphrases were first proposed in 1981 by Sigmund Porter (6). Passphrases are distinguished from passwords by their virtue of being comprised of several words separated by spaces (2). Passphrases can satisfy even stringent security requirements, while being easier for the users to remember (3). It’s this combination of complexity and ease of remembrance that make passphrases a good part of a password policy.

Our decision to use passphrases included another reason. By using passphrases when a user’s account is set up, we hoped to set an example to our users to use passphrases as well. We hoped that users would follow our example and choose passphrases they could remember easily, and that would be more than their dog’s name concatenated with a number 1. As a precedent, I cited that AOL has for years used multiple word passphrases as the login associated with all those floppies and CDs they send out. PGP and its variants also require using secure passphrases as your private key.

Recommended Passphrase “Best Practices”

With the intrinsic strength of some of the modern encryption, authentication, and message digest algorithms such as RSA, MD5, SHS and IDEA the user password or phrase is becoming more and more the focus of vulnerability. (8)

String passphrases are only one part of a comprehensive security policy. For additional security, you should include other best practices in your application’s login components. Microsoft (4) makes a number of recommendations for Windows networks which are also applicable for ASP.NET applications. These recommendations include:

  • Enforcing strong passwords
  • Ensure regular password changes
  • Maintain a history to prevent immediate reuse
  • Lock out accounts after a certain number of failed attempts

In a very good series of articles, Jesper Johansson (5) reiterates many of these recommendations, but disagrees about using account lockout policies. Several myths surrounding Windows passwords are addressed by Mark Burnett (7), and although focused on Windows passwords, some of the information is also applicable to ASP.NET applications. Designing a component that includes these recommendations is beyond the scope of this article, but you should familiarize yourself with these recommendations and incorporate the pertinent ones into your application.

Generating Passphrases

FAQ: How do I choose a good password or phrase?

ANS: Shocking nonsense makes the most sense. (9)

There are a number of methods for generating passwords and passphrases. In this article, we’ll modify a method known as Diceware (10). This method consists of a numbered word list and five dice. Each word is assigned a 5-digit number, with only numbers 1-6 at each position, and covering every combination of numbers. The five dice are rolled, and the numbers are read from each face to form a 5-digit number. This number is cross-referenced with a word in the word list, which is then the first word in the passphrase. This process is repeated until the requisite length or number of words has been reached. Diceware has been around for a while, and the International PGP Homepage (12) recommends Diceware as one method to generate your private key.

Instead of rolling dice, we’ll use pseudo-random number generators to simulate dice rolls. To make cross referencing easier, we’ll use a wordlist converted to XML format (which is available in the source code download). This wordlist has also been edited slightly to remove some words not suitable for corporate use (this does not assure that you will not generate offensive combinations, and you may need to further edit the word list to suit your own needs). The original wordlist is also included in the download. We’ll use a few simple methods of seeding the random number generators, which will work in many lower-security cases. If you need more complex random number generation, one source to review is RFC 4086: Randomness Requirements for Security. (11)

Coding the Application

The first step for me was to convert the original tab-delimited wordlist (diceware_wordlist_asc.txt) into an XML-formatted one. This will allow us to use XML query commands, rather than parsing a wordlist line by line. The original wordlist (included unmodified in the source code download) contains the author’s PGP signature, which should be removed prior to XML processing. To prevent downloading of the wordlist, we'll give it a .config extension (wordlist.config), which is mapped to HttpForbiddenHandler. You could also use database storage of the wordlist if you wanted. I have included the class I used to convert the wordlist (wordlist.vb), and the page used to control the conversion (ConvertWordlist.aspx).

Now that we have a word list in an easily queryable format, we’ll use another class to generate our passphrases. We’ll call the class Passphrase, and include a constructor and a GeneratePassphrase method. In our example, we’ll generate a passphrase consisting of two words and a two-digit number. We’ll need five randomly chosen numbers between 1 and 6 for each word, and a randomly chosen two-digit number. To generate the five randomly chosen numbers, we’ll use five different pseudo-random number generators (PRNGs), with five different initialization vectors (IVs, which are numbers used by the PRNGs when they are created to try and ensure a greater degree of uniqueness). The first two IVs will be based on the number of ticks on the processor’s clock; the first IV will be the last 8 digits of this value, and the second IV will be the last 5 digits of this value. The other IVs will be the day of year, day of week, and the two multiplied. The IVs will be created when the class constructor is called, and are suitable for a system that is only used to generate a couple of passphrases on any given day. If you will be generating a large number of passphrases, you may need more variation in your IVs, and reference (11) RFC 4086 (RFC4086) is a recommended source for suggestions. The initialization vectors are shown in Listing 1.

Listing 1: Initialization Vectors

Dim _IV1 As Integer = CInt(Right(CStr(DateTime.Now.Ticks), 8))
Dim _IV2 As Integer = CInt(Right(CStr(DateTime.Now.Ticks), 5))
Dim _IV3 As Integer = DatePart(DateInterval.DayOfYear, Today())
Dim _IV4 As Integer = DatePart(DateInterval.Weekday, Today())
Dim _IV5 As Integer = _IV3 * _IV4
 

The second step in generating our passphrase is to generate five random numbers between 1 and 6, and concatenate them into a single value. We’ll use the .NET Framework’s Random class for this, as shown in Listing 2. We’ll also generate our two-digit number at this time, using one of the random numbers as well. This will also be performed when the constructor is called.

Listing 2: Simulating Rolls of Five Dice

Dim _Rand1 As New Random(_IV1)
Dim _Rand2 As New Random(_IV2)
Dim _Rand3 As New Random(_IV3)
Dim _Rand4 As New Random(_IV4)
Dim _Rand5 As New Random(_IV5) 


_RV1 = CStr(_Rand1.Next(1, 6)) & CStr(_Rand2.Next(1, 6)) _ 
     & CStr(_Rand3.Next(1, 6)) & CStr(_Rand4.Next(1, 6)) & CStr(_Rand4.Next(1, 6))


 _RV2 = CStr(_Rand5.Next(1, 6)) & CStr(_Rand4.Next(1, 6)) _
     & CStr(_Rand3.Next(1, 6)) & CStr(_Rand2.Next(1, 6)) & CStr(_Rand1.Next(1, 6))


_RV3 = CInt(_Rand2.NextDouble * 100)

The final step is cross-referencing our dice rolls with our wordlist, and concatenating the two words and two-digit number together. The .NET Framework makes operations such as this very easy, which is one reason why we converted the word list to XML in the first place. We simply need to load the wordlist into an XmlDataDocument object, and then execute an XPath query to retrieve the nodes that correspond to our simulated dice rolls. Finally, we concatenate the inner text of the ‘word’ elements (which is the last child of each node retrieved) with our two-digit number, and return our passphrase.

Listing 3: Querying the XML

Dim _WordList As New XmlDataDocument
_WordList.Load(argFileName)


 _Query1 = "descendant::listWord[code='" & _RV1 & "']"
_Query2 = "descendant::listWord[code='" & _RV2 & "']"


Dim _node1 As XmlNode = _WordList.SelectSingleNode(_Query1)
Dim _node2 As XmlNode = _WordList.SelectSingleNode(_Query2)


 _Word1 = _node1.LastChild.InnerText
_Word2 = _node2.LastChild.InnerText


_Phrase = _Word1 & " " & _Word2 & " " & CStr(_RV3)

The complete code is included in the sample project.

Installing the Sample Application

Create a new IIS virtual directory called ‘passphrase’. Download the sample application, unzip it, and place the files in your new passphrase virtual directory. Open the sample application in Visual Studio.

Summary

In this article, we’ve built a small application that can create a passphrase using simulated dice rolls and an extensive wordlist. Passphrase length and complexity are only parts of a comprehensive security policy, and this application should not be mistaken as the only security procedure you need to include. This application could also find use as a passphrase generator for personal use when registering with websites.

References

Product Spotlight
Product Spotlight 

©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-04-18 5:46:58 AM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search