Functions/Test-PasswordComplexity.ps1

function Test-PasswordComplexity {
    <#
.SYNOPSIS
    Tests a password for length and password complexity
.DESCRIPTION
    Tests a password for length and password complexity. Complexity is at least 1 upper case character, 1 lower case character,
    1 numeral, 1 special character.
.PARAMETER SecureString
    The password passed as a secure string. In parameter sets 'SecureString'.
.PARAMETER Credential
    The password passed as part of a credential. In parameter sets 'Credential'.
.PARAMETER Password
    The password passed as plain text. In parameter sets 'Password'.
.Parameter MinimumLength
    Integer minimum number of characters in password. Valid range 1-255. Defaults to 8. Aliased to 'MinLength'.
    In parameter sets 'SecureString', 'Credential', 'Password'
.PARAMETER IncludeInput
    Switch whether to include input in the output. Passwords are masked with a '*'. In parameter sets 'SecureString', 'Credential', 'Password'
.EXAMPLE
    Test-PasswordComplexity -Password 'Password1'
 
    Would return $false as there is no special character
.EXAMPLE
    Test-PasswordComplexity -Password 'Password1' -IncludeInput
 
    Would return the following as there is no special character
    Password MinLength Length MatchComplexity
    -------- --------- ------ ---------------
    ********* 8 9 False
.EXAMPLE
    Test-PasswordComplexity -Password 'Ab(0' -IncludeInput
 
    Although it matches all the character types the password is too short
    Password MinLength Length MatchComplexity
    -------- --------- ------ ---------------
    **** 8 4 False
#>


    #region Parameter
    [CmdletBinding(DefaultParameterSetName = 'SecureString')]
    [OutputType('bool')]
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseOutputTypeCorrectly', '')]
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingPlainTextForPassword', '')]
    param (
        [Parameter(ParameterSetName = 'SecureString')]
        [securestring] $SecureString,

        [Parameter(ParameterSetName = 'Credential')]
        [pscredential] $Credential,

        [Parameter(ParameterSetName = 'Password', ValueFromPipeline)]
        [string[]] $Password,

        [Parameter(ParameterSetName = 'SecureString')]
        [Parameter(ParameterSetName = 'Credential')]
        [Parameter(ParameterSetName = 'Password')]
        [ValidateRange(0, 255)]
        [Alias('MinLength')]
        [int] $MinimumLength = 8,

        [Parameter(ParameterSetName = 'SecureString')]
        [Parameter(ParameterSetName = 'Credential')]
        [Parameter(ParameterSetName = 'Password')]
        [switch] $IncludeInput
    )
    #endregion

    begin {
        Write-Verbose -Message "Starting [$($MyInvocation.Mycommand)]"
        $Special = Get-PrintableAscii | Where-Object { $_.class -eq 's' } | Select-Object -Property Char, EscapeChar

        foreach ($s in $special) {
            if ($s.char -eq '(Space)') {
                $s.char = ' '
            }
            $s.EscapeChar = [regex]::Escape($s.char)
        }
        $SpecialRegex = '[' + ($special.EscapeChar -join '|') + ']'
        $LowerRegex = '[a-z]'
        $UpperRegex = '[A-Z]'
        $NumberRegex = '[0-9]'
    }

    process {
        switch ($PsCmdlet.ParameterSetName) {
            'Password' {
                foreach ($curPassword in $Password) {
                    if (
                        ($curPassword -match $SpecialRegex) -and
                        ($curPassword -cmatch $LowerRegex) -and
                        ($curPassword -cmatch $UpperRegex) -and
                        ($curPassword -match $NumberRegex) -and
                        ($curPassword.Length -ge $MinimumLength)
                    ) {
                        $ReturnVal = $true
                    } else {
                        $ReturnVal = $false
                    }
                    if ($IncludeInput) {
                        New-Object -TypeName psobject -Property ([ordered] @{
                                Password        = $curPassword -replace '.', '*'
                                MinLength       = $MinimumLength
                                Length          = $curPassword.Length
                                MatchComplexity = $ReturnVal
                            })
                    } else {
                        $ReturnVal
                    }
                }
            }
            'Credential' {
                $curPassword = Convert-SecureStringToString -SecureString $Credential.Password
                if (
                    ($curPassword -match $SpecialRegex) -and
                    ($curPassword -cmatch $LowerRegex) -and
                    ($curPassword -cmatch $UpperRegex) -and
                    ($curPassword -match $NumberRegex) -and
                    ($curPassword.Length -ge $MinimumLength)
                ) {
                    $ReturnVal = $true
                } else {
                    $ReturnVal = $false
                }
                if ($IncludeInput) {
                    New-Object -TypeName psobject -Property ([ordered] @{
                            Password        = $curPassword -replace '.', '*'
                            MinLength       = $MinimumLength
                            Length          = $curPassword.Length
                            MatchComplexity = $ReturnVal
                        })
                } else {
                    $ReturnVal
                }

            }
            'SecureString' {
                $curPassword = Convert-SecureStringToString -SecureString $SecureString
                if (
                    ($curPassword -match $SpecialRegex) -and
                    ($curPassword -cmatch $LowerRegex) -and
                    ($curPassword -cmatch $UpperRegex) -and
                    ($curPassword -match $NumberRegex) -and
                    ($curPassword.Length -ge $MinimumLength)
                ) {
                    $ReturnVal = $true
                } else {
                    $ReturnVal = $false
                }
                if ($IncludeInput) {
                    New-Object -TypeName psobject -Property ([ordered] @{
                            Password        = $curPassword -replace '.', '*'
                            MinLength       = $MinimumLength
                            Length          = $curPassword.Length
                            MatchComplexity = $ReturnVal
                        })
                } else {
                    $ReturnVal
                }
            }
        }

    }

    end {
        Write-Verbose -Message "Ending [$($MyInvocation.Mycommand)]"
    }
}