Public/New-NSPRandomPassword.ps1
|
function New-NSPRandomPassword { <# .SYNOPSIS Cryptographically-random password generator that works on Windows PowerShell 5.1 AND PowerShell 7+. .DESCRIPTION Adopted verbatim (behaviour-preserving) from the NSP-FGTIPSecTools CLI Builder / IPSec Master Orchestrator, where it replaced [System.Web.Security.Membership]::GeneratePassword - that type lives only in 5.1's System.Web.dll and throws "Unable to find type" under 7+. System.Security.Cryptography.RandomNumberGenerator exists on both. Character set excludes quotes, backtick, and space so the output is safe to drop into FortiGate CLI arguments, PowerShell string literals, and generated scripts. Look-alike characters (0/O, 1/l/I) are also excluded. .PARAMETER Length Total length. Default 16. .PARAMETER MinSpecial Minimum count of special characters (!@#$%^&*-_=+), placed then shuffled. Default 4. .EXAMPLE New-NSPRandomPassword .EXAMPLE New-NSPRandomPassword -Length 24 -MinSpecial 6 #> [CmdletBinding()] [OutputType([string])] param( [ValidateRange(4, 256)][int]$Length = 16, [ValidateRange(0, 64)][int]$MinSpecial = 4 ) if ($MinSpecial -gt $Length) { throw "New-NSPRandomPassword: -MinSpecial ($MinSpecial) cannot exceed -Length ($Length)." } $alphanumeric = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789' $special = '!@#$%^&*-_=+' # excludes quotes/backtick/space - those break downstream CLI args $rng = [System.Security.Cryptography.RandomNumberGenerator]::Create() try { $bytes = [byte[]]::new(4) $chars = [System.Collections.Generic.List[char]]::new() for ($i = 0; $i -lt $MinSpecial; $i++) { $rng.GetBytes($bytes) $chars.Add($special[[BitConverter]::ToUInt32($bytes, 0) % $special.Length]) } for ($i = $MinSpecial; $i -lt $Length; $i++) { $rng.GetBytes($bytes) $chars.Add($alphanumeric[[BitConverter]::ToUInt32($bytes, 0) % $alphanumeric.Length]) } # Fisher-Yates shuffle so the special chars aren't always clustered at the front for ($i = $chars.Count - 1; $i -gt 0; $i--) { $rng.GetBytes($bytes) $j = [BitConverter]::ToUInt32($bytes, 0) % ($i + 1) $tmp = $chars[$i]; $chars[$i] = $chars[$j]; $chars[$j] = $tmp } -join $chars } finally { $rng.Dispose() } } |