Functions/Credential/New-Password.ps1
<#
.SYNOPSIS Generate a new secure password. .DESCRIPTION This command will generate a secure random password, by default with 30 characters. The source characters to generated the password are carefully crafted to avoid ambiguous characters and keyboard layout issues between Swiss German and US. Default is an equal balance between lowercase, uppercase and numbers. - l (ell) - 1 (one) - I (capital i) - O (capital o) - 0 (zero) - zZyY (en/us keyboard layout issues) .EXAMPLE PS C:\> New-Password Generate a new password and copy it to the clipboard. .EXAMPLE PS C:\> New-Password -OutputType 'SecureString' Generate a new password and return it as secure string. .LINK https://github.com/claudiospizzi/SecurityFever #> function New-Password { [CmdletBinding()] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] param ( # The length of the password. [Parameter(Mandatory = $false, Position = 0)] [System.Int32] $Length = 30, # Characters to use for the password generation. See description for # more details. [Parameter(Mandatory = $false)] [System.String] $Include = 'abcdefghijkmnopqrstuvwxABCDEFGHJKLMNPQRSTUVWX234567892345678923456789', # How to return the generated password. [Parameter(Mandatory = $false)] [Alias('As')] [ValidateSet('SecureString', 'String', 'Clipboard')] [System.String] $OutputType = 'SecureString' ) try { $password = [System.Security.SecureString]::new() # For PowerShell 6 and later, use the modern random number generator. # For PowerShell 5 and before, use the legacy cryptographic functions. do { $isComplexLower = $false $isComplexUpper = $false $isComplexNumber = $false for ($i = 0; $i -lt $Length; $i++) { # Directly generated a random number between 0 and the length of # the include character array. If we have a modern PowerShell # and .NET version, use the cryptographically secure seed for # the Random class. if ($PSVersionTable.PSVersion.Major -gt 5) { $randomNumber = [System.Security.Cryptography.RandomNumberGenerator]::GetInt32(0, $Include.Length) } else { # Generate a cryptographically secure seed for the Random # class and then use the seed to generated a random number # between 0 and the length of the include character array. [System.Byte[]] $randomSeedBytes = [System.Byte[]]::new(4) $rngProvider = [System.Security.Cryptography.RNGCryptoServiceProvider]::new() $rngProvider.GetBytes($randomSeedBytes) $randomSeedNumber = [System.BitConverter]::ToInt32($randomSeedBytes, 0) $randomNumber = [System.Random]::new($randomSeedNumber).Next(0, $Include.Length) } $randomChar = $Include[$randomNumber] $password.AppendChar($randomChar) switch -regex ($randomChar) { '[a-z]' { $isComplexLower = $true } '[A-Z]' { $isComplexUpper = $true } '[0-9]' { $isComplexNumber = $true } } } } while (-not ($isComplexLower -and $isComplexUpper -and $isComplexNumber)) switch ($OutputType) { 'SecureString' { Write-Output $password } 'String' { Unprotect-SecureString -SecureString $password | Write-Output } 'Clipboard' { Unprotect-SecureString -SecureString $password | Set-Clipboard } } } catch { $PSCmdlet.ThrowTerminatingError($_) } } |