How To Build a Powershell Random Password Generator

PowerShell can automate the creation of secure passwords, ensuring they adhere to your organization’s length and complexity criteria.

Brien Posey

January 22, 2024

8 Min Read
digital keys
Alamy

Best practices have long demanded using passwords that are long, complex, and random, while ensuring that each password is unique for every resource. Recently, I was introduced to the idea of using PowerShell to automatically generate passwords. The notion behind this is that a PowerShell password generator could potentially streamline pipeline operations. For example, if you were using PowerShell to create new user accounts, you could employ the password generator to automatically assign a unique password to each account.

I must admit that, initially, I had dismissed the idea despite recognizing the technique’s usefulness. I thought of a password generator as little more than a random number generator. However, upon further contemplation, I began to realize that any decent PowerShell password generator would require a considerable amount of logic. After all, generating a password is one thing, but ensuring that the password adheres to your organization’s length and complexity requirements is an entirely different challenge.

In this article, I will walk you through the process of using PowerShell to generate a password. In Part 1, the goal will be to simply produce a password. In Part 2, we will examine password validation.

Part 1

Part 2


Part 1

 

Define the Character Set and Password Length

When using PowerShell to create a password, the first step is to tell PowerShell which characters it is allowed to use. A good password should contain a mix of upper and lowercase letters, numbers, and symbols.

While theoretically, you could simply grant PowerShell access to an entire character set, certain characters might pose issues. Considering this, I decided to establish an array named $FullSet. The array is designed to store every character that would be valid for inclusion in a password, although it’s worth noting that there might be more valid symbols than those included in my array.

Here is what the array declaration looks like:

$FullSet=@('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','1','2','3','4','5','6','7','8','9','0','!','@','$','?','<','>','*','&')


The script also needs to specify the password length. I created a variable named $Length that stores a numerical value indicating how long the password should be. For this article, I have set the length to 12 characters, but you can adjust it to your preferences.

Retrieve the Password Characters

Once the character set and password length are defined, the next step is to retrieve the characters that will make up the password. In this case, this means randomly selecting 12 items (since the password is 12 characters long) from the $FullSet array. The nice thing about this approach is that it should ensure that none of the characters in the password is repeated.

The command used to retrieve the password characters is:

$PasswordArray = $FullSet | Get-Random -Count $Length


The command establishes a variable named $PasswordArray, which stores the individual characters of the password. I am using the Get-Random cmdlet to retrieve random characters from $FullSet. The -Count parameter tells PowerShell how many random characters to retrieve. In this instance, the -Count is set to $Length, or the length of the password.

Combine the Characters Into a String

After the command runs, the $PasswordArray variable will contain the characters that make up the password, but these characters aren’t in a usable form. To use them as a password, we need to combine the characters into a string. I achieved this through a simple For loop.

Here is what the loop looks like:

For ($Index=0; $Index -lt $Length; $Index++)
{
    $Password=$Password+$PasswordArray[$Index]
}


This loop is based on a variable called $Index, initially set to 0. The loop examines the $Index position within the $PasswordArray variable and appends the corresponding character to a variable named $Password. The loop continues until $Index is less than the password length ($Length). Although the password length is currently set to 12, the loop only progresses through an index value of 11, because the password’s first character is stored in index position 0. Upon completion of the loop, the $Password variable will contain all the password characters in sequence, as a string.

Full Source Code for Basic Password Generation

To conclude the script, I decided to display the password on the screen by using the Write-Host cmdlet. Additionally, I copied the password to the Windows clipboard for easy pasting into an application. The cmdlet used for copying the password to the clipboard is Set-Clipboard. 

Here is the full source code for the simplified password generator:

# Password Generator

$Length=12

# Define Character Sets

$FullSet=@('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','1','2','3','4','5','6','7','8','9','0','!','@','$','?','<','>','*','&')

# Initialize password variable

$Password=""

$PasswordArray = $FullSet | Get-Random -Count $Length
For ($Index=0; $Index -lt $Length; $Index++)
{
    $Password=$Password+$PasswordArray[$Index]
}

# Display Password

Write-Host "The new password is: " $Password
Set-Clipboard -Value $Password


While this password generator does work, it leaves a lot to chance. It does nothing to guarantee the inclusion of upper and lowercase letters, numbers, and symbols in the generated password. There’s a possibility that one or two of these character types might be omitted. As such, I will now demonstrate how you can modify the script to guarantee that the generated password aligns with your organization’s criteria.

Part 2


In Part 1, you may recall that we created an array named $FullSet containing every character usable in a password. We then used a randomizer to select characters from that array. Because the selection process is random, the chosen characters might not include numbers or symbols. To address this, we need a way of examining the selected characters to ensure they meet complexity requirements. Additionally, we need a method for generating new passwords if a password is found to be inadequate.

Distinguishing Between Character Types

Even though we have an array containing all the possible characters for a password, we must have a way to distinguish between uppercase letters, lowercase letters, numbers, and symbols. While various methods exist, I addressed this by establishing four additional arrays, each dedicated to a specific character type.

Here are the declarations for those arrays:

$UpperCase=@('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z') 
$LowerCase=@('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z') 
$Numbers=@('1','2','3','4','5','6','7','8','9','0') 
$Symbols=@('!','@','$','?','<','>','*','&')


Subsequently, I created four variables, each representing a character type, and set each variable to 0. Here are the commands I used:

$HasUpperCase=0 
$HasLowerCase=0 
$HasNumbers=0 
$HasSymbols=0

Producing Complex Passwords

With these variables in mind, imagine that the password generator produces a password with its first character being a lowercase ‘a’. The script can isolate this character and compare it against the $UpperCase array to see if the character matches any of the array’s contents. Since the array contains uppercase characters and the password’s character is lowercase, no match is found. As such, no change is made to the variables.

The script repeats the process, comparing the character to the $LowerCase array. This time, because the character is a lowercase letter, it matches an item in the $LowerCase array. Consequently, a match prompts a change in the value of the $HasLowerCase variable from 0 to 1.

This process repeats for each character that makes up the password. Each character undergoes comparison with all four arrays. Whenever a character matches an item within one of the arrays, the corresponding variable ($HasUpperCase, $HasLowerCase, $HasNumbers, or $HasSymbols) is set to 1.


At the end of the process, we can check if any of these variables remain equal to 0. If so, it indicates that one of the four character types was omitted from the password. Since the password fails to meet complexity requirements, it needs to be created anew.

Password Validation

The comparison of each character against the various arrays is handled with a For loop. Here is what the loop looks like:

For ($Index=0;$Index -lt $Length; $Index++) 
{ 
$Character=$Password.Substring($Index,1) 
If ($UpperCase -Ccontains $Character) {$HasUpperCase=1} 
If ($LowerCase -Ccontains $Character) {$HasLowerCase=1} 
If ($Numbers -Contains $Character) {$HasNumbers=1} 
If ($Symbols -Contains $Character) {$HasSymbols=1} 
} 
}

Most of the code shown here is pretty straightforward. The loop operates based on an index value that allows it to examine one positional character at a time. Given that we are working with a string, the substring method is used to inspect the character at the specified index position.

The four If statements perform the actual comparison. As previously noted, they are designed so that if the character set array contains an instance of the currently examined character, a variable is set to 1. An important detail is that in the first two If statements, the word “contains” is intentionally misspelled. The deliberate misspelling (ccontains instead of contains) ensures that the comparison is treated as case-sensitive, which is what we need to check for the existence of both upper and lowercase letters.


The entire password generation and evaluation process is encapsulated within a While loop. This loop continues to repeat as long as any of the evaluation variables ($HasUpperCase, $HasLowerCase, $HasNumbers, or $HasSymbols) have a value of 0. The loop only terminates, finalizing the password, when all four variables are determined to have a value of 1.

Full Source Code

Here is the full source code for the script:

# Password Generator

$Length=12

# Define Character Sets

$UpperCase=@('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z')
$LowerCase=@('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z')
$Numbers=@('1','2','3','4','5','6','7','8','9','0')
$Symbols=@('!','@','$','?','<','>','*','&')
$FullSet=@('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','1','2','3','4','5','6','7','8','9','0','!','@','$','?','<','>','*','&')

# Check to see if all character sets are used

$HasUpperCase=0
$HasLowerCase=0
$HasNumbers=0
$HasSymbols=0

While($HasUpperCase -eq 0 -or $HasLowerCase -eq 0 -or $HasNumbers -eq 0 -or $HasSymbols -eq 0)
{
    # Generate New Password

    # Initialize password variable

    $Password=""

    $PasswordArray = $FullSet | Get-Random -Count $Length
    For ($Index=0; $Index -lt $Length; $Index++)
    {
        $Password=$Password+$PasswordArray[$Index]
    }

    # Test the password that has been created

    For ($Index=0;$Index -lt $Length; $Index++)
    {
        $Character=$Password.Substring($Index,1)
        If ($UpperCase -Ccontains $Character) {$HasUpperCase=1}
        If ($LowerCase -Ccontains $Character) {$HasLowerCase=1}
        If ($Numbers -Contains $Character) {$HasNumbers=1}
        If ($Symbols -Contains $Character) {$HasSymbols=1}
    }
}

# Display Password

Write-Host "The new password is: " $Password
Set-Clipboard -Value $Password

About the Author(s)

Brien Posey

Brien Posey is a bestselling technology author, a speaker, and a 20X Microsoft MVP. In addition to his ongoing work in IT, Posey has spent the last several years training as a commercial astronaut candidate in preparation to fly on a mission to study polar mesospheric clouds from space.

http://brienposey.com/

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