src/public/New-Passphrase.ps1
|
#Requires -Module PwnedPassCheck #TODO: Additional format options (word##word, wordword##!) #TODO: Add maximum and minimum word lengths to filter the word list <# .SYNOPSIS Generates one or more passphrases based on the specified parameters. .DESCRIPTION The New-Passphrase function generates memorable passphrases by randomly selecting words from a word list and combining them with separators and optional numbers. It supports customizable word count, separator characters, case formatting, and optional pwned password checking. .PARAMETER WordCount Specifies the number of words to include in the passphrase. Default is 3. Alias: Words .PARAMETER Separator Specifies the character used to separate words in the passphrase. Valid values: "-", "_", "None", ".", ",", "+", "=". Default is "-". .PARAMETER Case Specifies the case formatting for words in the passphrase. Valid values: "Lowercase", "Uppercase", "Titlecase", "RandomCase", "RandomLetter". Default is "Titlecase". - Lowercase: All words in lowercase - Uppercase: All words in UPPERCASE - Titlecase: First letter uppercase, rest lowercase - RandomCase: Each word is randomly uppercase or lowercase - RandomLetter: Each letter in each word is randomly upper or lowercase .PARAMETER ExcludeNumbers Excludes numbers from the end of the passphrase. By default, a random number (0-99) is appended. .PARAMETER PwnCheck Checks if the generated passphrase has been pwned using the PwnedPassCheck module. If pwned, generates a new passphrase. .PARAMETER NumberOfPassphrases Specifies the number of passphrases to generate. Default is 1. Alias: Count .PARAMETER OutputPath Specifies the file path to save the generated passphrases. If specified, passphrases are appended to the file, or a new file is created if it doesn't exist. .PARAMETER CopyToClipboard Copies the generated passphrases to the clipboard. .PARAMETER NoProgress Suppresses the progress bar display during passphrase generation. .EXAMPLE New-Passphrase Generates a single passphrase with 3 titlecase words separated by hyphens and a random number at the end. .EXAMPLE New-Passphrase -WordCount 4 -Separator "_" -Case Uppercase -ExcludeNumbers Generates a passphrase with 4 uppercase words separated by underscores without numbers. .EXAMPLE New-Passphrase -NumberOfPassphrases 5 -PwnCheck -OutputPath "C:\Passphrases.txt" Generates 5 passphrases, checks if they've been pwned, and saves them to the specified file. .EXAMPLE New-Passphrase -Case RandomLetter -Separator "None" -CopyToClipboard Generates a passphrase where each letter has random capitalization without separators and copies it to the clipboard. .NOTES Requires the PwnedPassCheck module for the PwnCheck functionality. Word list is retrieved from https://raw.githubusercontent.com/srsbod/PassPhraseWordList/refs/heads/main/en.txt #> function New-Passphrase { [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "", Justification = "Not actually changing anything on the system.")] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingWriteHost", "", Justification = "Write-Host is fine here.")] [CmdletBinding(DefaultParameterSetName = "Simple")] param ( [Parameter(Mandatory = $false)] [Alias("Words")] [int]$WordCount = 3, [Parameter(Mandatory = $false)] [ValidateSet("-", "_", "None", ".", ",", "+", "=")] [string]$Separator = "-", [Parameter(Mandatory = $false)] [ValidateSet("Lowercase", "Uppercase", "Titlecase", "RandomCase", "RandomLetter")] [string]$Case = "RandomCase", [Parameter(Mandatory = $false)] [switch]$ExcludeNumbers, [Parameter(Mandatory = $false)] [Switch]$PwnCheck, [Parameter(Mandatory = $false)] [Alias("Count")] [int]$NumberOfPassphrases = 1, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$OutputPath, [Parameter(Mandatory = $false)] [Switch]$CopyToClipboard, [Parameter(mandatory = $false)] [switch]$NoProgress ) begin { $Passphrases = @() $GeneratedPassphrases = 0 $WordListURL = "https://raw.githubusercontent.com/srsbod/PassPhraseWordList/refs/heads/main/en.txt" try { $WordList = (Invoke-RestMethod -Uri $WordListURL) -split "`n" | Where-Object { $_.Trim() -ne "" } } catch { Write-Error "Failed to retrieve word list from $WordListURL" exit 1 } } process { while ($GeneratedPassphrases -lt $NumberOfPassphrases) { if (-not $NoProgress) { $ProgressPercentage = [math]::Round(($GeneratedPassphrases / $NumberOfPassphrases) * 100) Write-Progress -Activity "Generating Passphrases" -Status "$ProgressPercentage% Complete:" -PercentComplete $ProgressPercentage } $Words = @() for ($i = 0; $i -lt $WordCount; $i++) { $RandomWord = Get-Random -InputObject $WordList switch ($Case) { "Lowercase" { $RandomWord = $RandomWord.ToLower() } "Uppercase" { $RandomWord = $RandomWord.ToUpper() } "Titlecase" { $RandomWord = ($RandomWord.Substring(0, 1).ToUpper() + $RandomWord.Substring(1).ToLower()) } "RandomCase" { if ((Get-Random -Minimum 0 -Maximum 2) -eq 1) { $RandomWord = $RandomWord.ToUpper() } else { $RandomWord = $RandomWord.ToLower() } } "RandomLetter" { $RandomLetters = @() foreach ($char in $RandomWord.ToCharArray()) { if ((Get-Random -Minimum 0 -Maximum 2) -eq 1) { $RandomLetters += $char.ToString().ToUpper() } else { $RandomLetters += $char.ToString().ToLower() } } $RandomWord = $RandomLetters -join "" } } $Words += $RandomWord } $ActualSeparator = $Separator if ($Separator -eq "None") { $ActualSeparator = "" } $Passphrase = $Words -join $ActualSeparator if (-not $ExcludeNumbers) { $RandomNumber = Get-Random -Minimum 0 -Maximum 99 $Passphrase += $RandomNumber } if ($PwnCheck) { $Pwned = Get-PwnedPassword $Passphrase | Select-Object -ExpandProperty SeenCount if ($Pwned -gt 0) { Write-Host "Passphrase $Passphrase is pwned, generating a new one instead - Pwned count: $Pwned" -ForegroundColor Yellow continue } } $Passphrases += $Passphrase $GeneratedPassphrases++ } if ($OutputPath) { try { $Passphrases | Out-File $OutputPath -Append -Force -ErrorAction Stop Write-Output "$NumberOfPassphrases passphrase(s) generated - File Location: $OutputPath" } catch { # Store passphrases in caller's scope if file write fails Set-Variable -Name 'GeneratedPassphrases' -Value $Passphrases -Scope 1 Write-Error "An error occurred while writing the passphrase file: $_" Write-Output "The generated passphrase(s) have been saved to the variable '`$GeneratedPassphrases'. Use '`$GeneratedPassphrases | Set-Clipboard' to copy them to clipboard" } } else { # Only output passphrases to console if not writing to file Write-Output $Passphrases } if ($CopyToClipboard) { $Passphrases | Set-Clipboard } } end { } } |