Src/Public/New-Passphrase.ps1
<#
.NOTES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Module: PSPassPhrase Function: New-Passphrase Author: Martin Cooper (@mc1903) Date: 03-05-2025 GitHub Repo: https://github.com/mc1903/PSpassPhrase Version: 2.0.1 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .SYNOPSIS Generates one or more passphrases composed of random words, numbers, and optional special characters. .DESCRIPTION The New-Passphrase function generates passphrases by selecting a specified number of random words from a word list. These words can be separated by spaces, hyphens, or underscores. The passphrase may optionally include a random number and a special character at the end. The function allows customisation of the word length, capitalisation, and special characters used. .PARAMETER passPhraseCount Specifies the number of passphrases to generate. Default is 1. .PARAMETER wordsPerPassPhrase Specifies the number of words to use in each passphrase. Default is 3. .PARAMETER minWordLength Specifies the minimum length of words to be included in the passphrase. Default is 5. .PARAMETER maxWordLength Specifies the maximum length of words to be included in the passphrase. Default is 8. .PARAMETER firstCapitalOnly If specified, only the first letter of the passphrase will be capitalised. Otherwise, the first letter of each word in the passphrase will be capitalised. .PARAMETER delimiterChar Specifies the character to use as the delimiter between each word in the passphrase. Valid values are: 'none', 'space', 'hyphen', or 'underscore'. - 'none' separates words with a space (e.g. "AlphaBetaGamma"). - 'space' separates words with a space (e.g. "Alpha Beta Gamma"). - 'hyphen' separates words with a hyphen (e.g. "Alpha-Beta-Gamma"). - 'underscore' separates words with an underscore (e.g. "Alpha_Beta_Gamma"). The delimiter character will also be inserted before the random number at the end. The default is 'none'. .PARAMETER noSpaceBetween **Deprecated**: This switch made the passphrase words run together with nothing in between. It is retained for backward compatibility. Please use the `-delimiterChar ""` or omit the parameter for default behaviour. .PARAMETER randomNumberLength Specifies the length of the random number to append to each passphrase. Default is 3. .PARAMETER noLastSpecialChar If specified, no special character will be appended to the end of the passphrase. .PARAMETER specialCharacterList Specifies the list of special characters to choose from when appending a special character to the passphrase. Default is a list containing "!", "$", "*", and "&". .PARAMETER wordListPath Specifies the path to the word list file to use for generating passphrases. If not specified, a default list will be used. .EXAMPLE # Generate a single passphrase with the default settings New-Passphrase .EXAMPLE # Generate 3 passphrases, each composed of 4 words, with a minimum word length of 6 and maximum word length of 10 New-Passphrase -passPhraseCount 3 -wordsPerPassPhrase 4 -minWordLength 6 -maxWordLength 10 .EXAMPLE # Generate a passphrase with words separated by hyphens, a 5-digit random number, and no special character at the end New-Passphrase -delimiterChar hyphen -randomNumberLength 5 -noLastSpecialChar #> Function New-Passphrase { [CmdletBinding()] Param ( [int]$passPhraseCount = 1, [int]$wordsPerPassPhrase = 3, [int]$minWordLength = 5, [int]$maxWordLength = 8, [ValidateSet('none','space','hyphen','underscore')] [string]$delimiterChar = 'none', [switch]$firstCapitalOnly, [int]$randomNumberLength = 3, [switch]$noLastSpecialChar, [string[]]$specialCharacterList = @("!", "$", "*", "&"), [string]$wordListPath, [switch]$noSpaceBetween # Deprecated, remains for compatibility. Prefer -delimiterChar. ) # Deprecated Parameters Warning if ($PSBoundParameters.ContainsKey('noSpaceBetween')) { Write-Warning -Message "The 'noSpaceBetween' parameter is deprecated and will be removed in future releases. Please use the 'delimiterChar' parameter instead." } if ($minWordLength -gt $maxWordLength) { throw "The minimum word length ($minWordLength) cannot be greater than the maximum word length ($maxWordLength)" } if (-not $wordListPath) { try { $modulePath = Get-ModulePath $wordListPath = Join-Path -Path $modulePath -ChildPath 'src\private\DefaultWordList.txt' } catch { throw "The default word list could not be found. Please specify the word list location using the -wordListPath parameter." } } if (-not (Test-Path -Path $wordListPath)) { throw "Word list file not found at path: $wordListPath" } Write-Verbose "Loading word list from $($wordListPath)" $wordList = Get-Content -Path $wordListPath Write-Verbose "The word list contains $($wordList.count) entries" Write-Verbose "Filtering word list and selecting only the words between $($minWordLength) and $($maxWordLength) characters" $pattern = '^[a-zA-Z]+$' $filteredWordList = $wordList | Where-Object { $_ -match $pattern -and $_.Length -ge $minWordLength -and $_.Length -le $maxWordLength } # Translate delimiter string to actual character switch ($delimiterChar) { 'space' { $delimiter = " " } 'hyphen' { $delimiter = "-" } 'underscore' { $delimiter = "_" } 'none' { $delimiter = "" } default { $delimiter = "" } } $passPhrases = @() for ($i = 0; $i -lt $passPhraseCount; $i++) { Write-Verbose "Generating passPhrase $($i+1) of $($passPhraseCount)" $passPhraseWords = @() for ($j = 0; $j -lt $wordsPerPassPhrase; $j++) { $random = Get-Random -InputObject $filteredWordList $passPhraseWords += $random } # Compose the passphrase with word formatting if ($firstCapitalOnly) { $concatWords = ($passPhraseWords | ForEach-Object { $_.ToLower() }) -join $delimiter $passPhrase = $concatWords.Substring(0,1).ToUpper() + $concatWords.Substring(1) } else { $concatWords = ($passPhraseWords | ForEach-Object { $_.Substring(0,1).ToUpper() + $_.Substring(1).ToLower() }) -join $delimiter $passPhrase = $concatWords } # Add the delimiter before the random number at the end $passPhrase += $delimiter + (-join ((0..9) | Get-Random -Count $randomNumberLength)) if (!$noLastSpecialChar) { $randomSpecialChar = Get-Random -InputObject $specialCharacterList $passPhrase += $randomSpecialChar } $passPhrases += @{ Index = ($i + 1) PassPhrase = $passPhrase } } Write-Output "Index PassPhrase" Write-Output "----- ----------" foreach ($entry in $passPhrases) { $formatString = "{0,-5} {1}" Write-Output ($formatString -f $entry.Index, $entry.PassPhrase) } } |