Monday, September 8, 2008

A Simple Passphrase Generator

Passphrases have been receiving more and more attention as part of a strong security policy. When building secure web-based applications, assigning random passphrases to new user accounts can be a bit of a challenge. In this article, we'll build a simple passphrase generator that can be used as part of a web application to set or reset user passphrases.
by Richard Dudley

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.


ASP.Net Feeds