Generate a random strong password in PowerShell

I’ve created this PowerShell function that allows you generate any random strong password.

With this method, the caller is able to specify:

  1. The desired password length (minimum = 4)
  2. Whether or not to use lowercase characters
  3. Whether or not to use uppercase characters
  4. Whether or not to use numbers
  5. Whether or not to use special characters
  6. Whether or not to avoid using similar characters ( e.g. i, l, o, 1, 0, I)

The function ensures that each type of character (lowercase, uppercase, number and/or special) is included at least once in the password.

Examples of how to use this:

  • GeneratePassword
    Generates a password using the default settings (length of 8, using a combination of lowercase, uppercase and numbers, while avoiding similar characters), e.g. YeM2B98r
  • GeneratePassword 16
    Generates a longer password using the default settings (length of 16, using a combination of lowercase, uppercase and numbers, while avoiding similar characters), e.g. 89p4758unWt2HDnp
  • GeneratePassword 4 $false $false
    Generates a 4 digit numeric PIN code, e.g. 8298
  • GeneratePassword 8 $true $true $true $true
    Generates an extra strong password, (length of 8, using a combination of lowercase, uppercase, numbers and special characters, while avoiding similar characters), e.g. 9c+9P=#z
  • GeneratePassword 20 $true $true $true $true $false
    Generates an extra strong password, (length of 20, using a combination of lowercase, uppercase, numbers and special characters with possible similar characters), e.g. YCi+R8?vVl1H!B+5hZU8

You can grab the script here (double-click it to copy):

function GeneratePassword() {
    Param (
    [int]$length = 8,    
    [bool] $includeLowercaseLetters = $true,
    [bool] $includeUppercaseLetters = $true,
    [bool] $includeNumbers = $true,
    [bool] $includeSpecialChars = $false,
    [bool] $noSimilarCharacters = $true
    )

    <#
    (c) Morgan de Jonge CC BY SA
    Generates a random password. you're able to specify:
    - The desired password length (minimum = 4)
    - Whether or not to use lowercase characters
    - Whether or not to use uppercase characters
    - Whether or not to use numbers
    - Whether or not to use special characters
    - Whether or not to avoid using similar characters ( e.g. i, l, o, 1, 0, I)
    #>

    # Validate params
    if($length -lt 4) {
        $exception = New-Object Exception "The minimum password length is 4"
        Throw $exception
    }
    if ($includeLowercaseLetters -eq $false -and 
            $includeUppercaseLetters -eq $false -and
            $includeNumbers -eq $false -and
            $includeSpecialChars -eq $false) {
        $exception = New-Object Exception "At least one set of included characters must be specified"
        Throw $exception
    }

    #Available characters
    $CharsToSkip = [char]"i", [char]"l", [char]"o", [char]"1", [char]"0", [char]"I" 
    $AvailableCharsForPassword = $null;
    $uppercaseChars = $null 
    for($a = 65; $a -le 90; $a++) { if($noSimilarCharacters -eq $false -or [char][byte]$a -notin $CharsToSkip) {$uppercaseChars += ,[char][byte]$a }}
    $lowercaseChars = $null
    for($a = 97; $a -le 122; $a++) { if($noSimilarCharacters -eq $false -or [char][byte]$a -notin $CharsToSkip) {$lowercaseChars += ,[char][byte]$a }}
    $digitChars = $null
    for($a = 48; $a -le 57; $a++) { if($noSimilarCharacters -eq $false -or [char][byte]$a -notin $CharsToSkip) {$digitChars += ,[char][byte]$a }}
    $specialChars = $null
    $specialChars += [char]"=", [char]"+", [char]"_", [char]"?", [char]"!", [char]"-", [char]"#", [char]"$", [char]"*", [char]"&", [char]"@"

    $TemplateLetters = $null
    if($includeLowercaseLetters) { $TemplateLetters += "L" }
    if($includeUppercaseLetters) { $TemplateLetters += "U" }
    if($includeNumbers) { $TemplateLetters += "N" }
    if($includeSpecialChars) { $TemplateLetters += "S" }
    $PasswordTemplate = @()
    # Set password template, to ensure that required chars are included
    do {   
        $PasswordTemplate.Clear()
        for($loop = 1; $loop -le $length; $loop++) {
            $PasswordTemplate += $TemplateLetters.Substring((Get-Random -Maximum $TemplateLetters.Length),1)
        }
    }
    while ((
        (($includeLowercaseLetters -eq $false) -or ($PasswordTemplate -contains "L")) -and
        (($includeUppercaseLetters -eq $false) -or ($PasswordTemplate -contains "U")) -and
        (($includeNumbers -eq $false) -or ($PasswordTemplate -contains "N")) -and
        (($includeSpecialChars -eq $false) -or ($PasswordTemplate -contains "S"))) -eq $false
    )
    #$PasswordTemplate now contains an array with at least one of each included character type (uppercase, lowercase, number and/or special)

    foreach($char in $PasswordTemplate) {
        switch ($char) {
            L { $Password += $lowercaseChars | Get-Random }
            U { $Password += $uppercaseChars | Get-Random }
            N { $Password += $digitChars | Get-Random }
            S { $Password += $specialChars | Get-Random }
        }
    }

    return $Password
}

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.