Generating Random Passwords in PowerShell

This simple script helps you pump up password strength

Bill Stewart

August 21, 2012

7 Min Read
ITPro Today logo


In May of 2009, I wrote an HTML Application (HTA), RandPass.hta, that uses JScript code to conveniently generate random passwords (see " Random Passwords on Demand"). The HTA has four check boxes that youcan use to specify which character classes (uppercase, lowercase, numbers, and symbols) the HTA can include in the generated passwords.

The operative words are can include: The application doesn't force the inclusion of the selected character classes in the random passwords that itgenerates. The check boxes merely create a longer list of characters to choose from. For example, if you select the Uppercase and Lowercase check boxes,the HTA might randomly generate passwords that contain only uppercase or only lowercase characters. This behavior makes sense but feels a bitcounterintuitive (e.g., "I selected Uppercase, but this password doesn't contain any uppercase characters"). Despite this minor flaw, I use RandPass.hta ona regular basis and have received feedback from numerous people, thanking me for making it available.

Still, I wanted the ability to generate random strings just by using RandPass.hta, but from the Windows PowerShell command line. I also wanted to improveon the algorithm that RandPass.hta uses: Rather than specifying character classes that might appear in the password strings, I wanted to specifyclasses that will appear in the password strings. To accomplish this goal, I wrote Get-RandomString.ps1.

Making a Good Thing Better

The command-line syntax for RandomString.ps1 is as follows:

Get-RandomString.ps1 [[-Length] ] [-LowerCase] [-UpperCase] [-Numbers] [-Symbols] [[-Count] ] 


The ‑Length parameter specifies the length; for example,

-Length 32 


means that Get-RandomString.ps1 will generate random strings of 32 characters. If you don't specify this parameter, the default value is 8. You can omitthe parameter name (‑Length) if you place the parameter argument immediately after the script's name on the command line.

‑LowerCase, ‑UpperCase, ‑Numbers, and ‑Symbols are switch parameters. All four specify the character classes to include in the random strings. ‑LowerCaseis enabled by default, so if you want to create random strings that do not contain lowercase characters, you must specify

-LowerCase:$False 


All these character classes are based on ASCII characters and are not locale-specific.

The ‑Count parameter specifies how many random strings to output (1 is the default). For example,

-Count 10 


outputs 10 random strings.

For more information about the script's parameters as well as some sample commands, use

Get-Help Get-RandomString -Detailed 


or

Get-Help Get-RandomString -Full 


How Does It Work?

The script begins by declaring a param statement that specifies the script's parameters. All the parameters are declared with default values. Next, thescript determines the ‑Length parameter argument. If the argument is less than 4, the script throws an error. (Strings must be at least 4 charactersbecause that's the number of available character classes.) As a final sanity check, the script makes sure that at least one of the four character classes(i.e., ‑LowerCase, ‑UpperCase, ‑Numbers, or ‑Symbols) is included. If none of the four character classes are specified, the script throws an error.

Next, the script declares a set of bitmap mask values that represent the four character classes. (For more information about how bitmaps and masks work,see the sidebar "Bitmaps as Arrays.") The script then creates four arrays that contain the character values for each of the four character classes, basedon the ASCII values of the characters. For example, the $charsLower array contains ASCII lowercase characters (i.e., each element in the array is alowercase ASCII character); the $charsNumber array contains ASCII number characters. The characters that I chose for the $charsSymbol array don't includeany characters that might cause problems from the command line (e.g., single and double quotes, pipe and redirection symbols).

After this, the script creates an array, stored in the $charList variable, that contains all the characters from the character classes that are specifiedon the command line. For example, if ‑LowerCase and ‑Numbers exist on the command line, then the $charList variable will contain the characters from boththe $charsLower and the $charsNumber arrays. The script also defines the $charSets variable, which is a bitmap value that stores the character sets thathave been selected.

The script then defines the test-stringcontents function, which Listing 1 shows. This function uses two parameters: a string and an array of characters.The function returns $True if the string contains at least one character from the array; otherwise, the function returns $False. The script uses thisfunction later to determine whether a random string contains characters from a specified character class.

After defining the test-stringcontents function, the script loops the number of times that the ‑Count parameter requests. Next, the script initiates a doloop that generates a random string and checks if the string contains all of the requested character classes. In the do loop, the script creates the $flagsvariable (a second bitmap value) to keep track of matching character classes. Then, the script uses the Get-Random cmdlet to append a randomly selectedcharacter from the $charList array as many times as the ‑Length parameter requests, as Listing 2 shows.

After running the code in Listing 2, the random string contains characters that are randomly selected from the $charList array. However, this doesn't meanthat the string is guaranteed to contain characters from each selected character class. To make sure that the string contains at least one character fromeach class, the script uses the test-stringcontents function (see Listing 1). If the string contains at least one character from a class, it sets thecorresponding bit for that class in the $flags bitmap. If the $flags bitmap doesn't match the $charSets bitmap, then the randomly generated string does notcontain all the requested character classes, and the do loop repeats. Otherwise, the script outputs the string.

Random Password Generation Made Easy

The Get-RandomString.ps1 script uses PowerShell's Get-Random cmdlet and its powerful array- and string-handling functionality to return random strings. Youcan use the script to create random passwords, PIN codes, or whatever else you need.

 

 

Listing 1: The test-stringcontents Function

function test-stringcontents([String] $test, [Char[]] $chars) {  foreach ($char in $test.ToCharArray()) {    if ($chars -ccontains $char) { return $TRUE }  }  return $FALSE}


 

Listing 2: Code that Generates a Random String

$output = ""1..$Length | foreach-object {  $output += $charList[(get-random -maximum $charList.Length)]}

 

Sidebar: Bitmaps As Arrays

A bitmap is a number that the programmer interprets as an array of Boolean values (i.e., each bit in the number represents a Boolean). You can check and change the bits in a bitmap by using a mask value that represents one or more bit positions in the bitmap. The Get-RandomString.ps1 script uses two numbers as bitmaps. The first bitmap, $charSets, stores the character classes (i.e., lowercase, uppercase, numbers, or symbols) that the user specified on the command line. The second bitmap, $flags, contains the character classes that the randomly generated string actually contains. If the bitmaps don't match, the script generates another random string. You can use the formulas in Table A to check and change the bits in a bitmap.

 

Table A: Formulas for Checking Bits

Purpose

Formula

Check whether at least one bit in the mask is set

(bitmap -band mask) -ne 0

Check whether all of the bits in the mask are set

(bitmap -band mask) -eq bitmap

Check whether none of the bits in the mask are set

(bitmap -band mask) -eq 0

Set the bits specified in the mask

bitmap = bitmap -bor mask

Clear the bits specified in the mask

bitmap = bitmap -band (-bnot mask)

Toggle the bits specified in the mask:

bitmap = bitmap -bxor mask

Sign up for the ITPro Today newsletter
Stay on top of the IT universe with commentary, news analysis, how-to's, and tips delivered to your inbox daily.

You May Also Like