How can I only allow these characters in the Powershell password generater?

Viewed 42

This function works nicely however, when it adds apecial characters I only want to allow these special characters
*^!+~

Function GenerateStrongPassword ([Parameter(Mandatory=$true)][int]$PasswordLenght)
{
Add-Type -AssemblyName System.Web
$PassComplexCheck = $false
do {
$newPassword=[System.Web.Security.Membership]::GeneratePassword($PasswordLenght,1)
If ( ($newPassword -cmatch "[A-Z\p{Lu}\s]") `
-and ($newPassword -cmatch "[a-z\p{Ll}\s]") `
-and ($newPassword -match "[\d]") `
-and ($newPassword -match "[^\w]")
)
{
$PassComplexCheck=$True
}
} While ($PassComplexCheck -eq $false)
return $newPassword
}

GenerateStrongPassword (16)

These are the special characters I want to allow

*^!+~
2 Answers

If you just need alphanumeric, e.g. A-Z_a-z + your specific NonAlphaNumeric chars, e.g. *^!+~

you can simply do:

(([char[]](0..255) -like '[A-Z]') + '*^!+~'.ToCharArray() | 
Get-Random -Count $PasswordLength) -join ""

Or you can use the [System.Web.Security.Membership]::GeneratePassword with 0 NonAlphaNumeric, e.g. ::GeneratePassword($PasswordLength,0) and add it manually:

For Example:

Function GenerateStrongPassword ([Parameter(Mandatory=$true)][int]$PasswordLength)
{
$Chars = [System.Web.Security.Membership]::GeneratePassword($PasswordLength,0) + '*^!+~'
$Password = ($Chars.ToCharArray() | Get-Random -Count $PasswordLength) -join ""
return $Password
}

It sounds like all you need to do is to replace
$newPassword -match "[^\w]"
with
$newPassword -match '[*^!+~]'

Also, your other regexes and if statement can be streamlined / optimized away to yield the following assignment:

$PassComplexCheck = 
  $newPassword -cmatch '[\p{Lu}\s]' -and
  $newPassword -cmatch '[\p{Ll}]' -and
  $newPassword -match '\d' -and
  $newPassword -match '[*^!+~]'

That is:

  • You can forgo an if statement by simply assigning the Boolean result of your expression directly to your $PassComplexCheck variable.

  • In [A-Z\p{Lu}\s], A-Z is redundant, because \p{Lu}, which represents all uppercase characters (not just English ones), implicitly comprises A through Z as well; the same applies analogously to [a-z\p{Ll}\s]

  • Since \s is being matched by the initial regex, alongside uppercase letters, it needn't be matched again when looking for lowercase letters.

  • [\d] needlessly wraps \d - matching a single digit - in [...] - the latter is only needed for ranges or sets of characters.

Related