# # Copyright (c) 2017 Richard L. Mueller # # ---------------------------------------------------------------------- # You have a royalty-free right to use, modify, reproduce, and # distribute this script file in any way you find useful, provided that # you agree that the copyright owner above has no warranty, obligations, # or liability for such use. Function Spell-Phonetic { <# .SYNOPSIS Function to return the phonetic spelling of one or more strings. .DESCRIPTION Uses the NATO spelling alphabet, also known as the ICAO phonetic alphabet. This alphabet has been expanded to include upper and lower case letters, as well the non-alphanumeric characters on most computer keyboards. .NOTES Author: Richard L. Mueller Version: 1.0 Date: February 15, 2017 Requires: PowerShell V2 .PARAMETER Strings One or more strings to be spelled phonetically. .PARAMETER Label Label indicating the function of each string, such as "Password" or "Product Key". .PARAMETER Complex A switch indicating the string(s) should be analyzed to see if they meet the password complexity requirements. .EXAMPLE # Example prompting for a string. In this case no characters need to be escaped. $Password = Read-Host "Enter a password" Spell-Phonetic $Password -c -l "Password" .EXAMPLE # Example passing an array of strings to the function. $Keys = @("fD0lL","12pass4","xXcpass","X&3c") Spell-Phonetic $Keys .EXAMPLE # Example using required escaping of $, `, and " characters in quoted strings. $Password = "vA3`$*8``>m`"l'o" Spell-Phonetic $Password -complex -label "Password" -Verbose .EXAMPLE # Example piping the output of a hypothetical script to Spell-Phonetic. . .\Spell-Phonetic.ps1 .\New-Password.ps1 | Spell-Phonetic -l "Password" -c > .\Password.txt .INPUTS One or more strings. .OUTPUTS String, one for each input string, that can be redirected to a text file. #> [CmdletBinding()] Param( [Parameter(Mandatory=$True,ValueFromPipeline=$True)] [String[]]$Strings, [String]$Label = "String", [Switch]$Complex ) # Hash tables of keyboard characters with their phonetic spelling. # These cannot be combined into one because hash tables are case insensitive. # 26 lower case letters. $LCChars = @{"a"="Lower case a as in alfa";"b"="Lower case b as in bravo"; ` "c"="Lower case c as in charlie";"d"="Lower case d as in delta"; ` "e"="Lower case e as in echo";"f"="Lower case f as in foxtrot"; ` "g"="Lower case g as in golf";"h"="Lower case h as in hotel"; ` "i"="Lower case i as in india";"j"="Lower case j as in juliett"; ` "k"="Lower case k as in kilo";"l"="Lower case l as in lima"; ` "m"="Lower case m as in mike";"n"="Lower case n as in november"; ` "o"="Lower case o as in oscar";"p"="Lower case p as in papa"; ` "q"="Lower case q as in quebec";"r"="Lower case r as in romeo"; ` "s"="Lower case s as in sierra";"t"="Lower case t as in tango"; ` "u"="Lower case u as in uniform";"v"="Lower case v as in victor"; ` "w"="Lower case w as in whiskey";"x"="Lower case x as in xray"; ` "y"="Lower case y as in yankee";"z"="Lower case z as in zulu"} # 26 upper case letters. $UCChars = @{"A"="Upper case A as in Alfa";"B"="Upper case A as in Bravo"; ` "C"="Upper case C as in Charlie";"D"="Upper case D as in Delta"; ` "E"="Upper case E as in Echo";"F"="Upper case F as in Foxtrot"; ` "G"="Upper case G as in Golf";"H"="Upper case H as in Hotel"; ` "I"="Upper case I as in India";"J"="Upper case J as in Juliett"; ` "K"="Upper case K as in Kilo";"L"="Upper case L as in Lima"; ` "M"="Upper case M as in Mike";"N"="Upper case N as in November"; ` "O"="Upper case O as in Oscar";"P"="Upper case P as in Papa"; ` "Q"="Upper case Q as in Quebec";"R"="Upper case R as in Romeo"; ` "S"="Upper case S as in Sierra";"T"="Upper case T as in Tango"; ` "U"="Upper case U as in Uniform";"V"="Upper case V as in Victor"; ` "W"="Upper case W as in Whiskey";"X"="Upper case X as in Xray"; ` "Y"="Upper case Y as in Yankee";"Z"="Upper case Z as in Zulu"} # 10 digits. $DigitChars = @{"0"="Number Zero";"1"="Number One";"2"="Number Two"; ` "3"="Number Three";"4"="Number Four";"5"="Number Five";"6"="Number Six"; ` "7"="Number Seven";"8"="Number Eight";"9"="Number Nine"} # 33 symbols. $SymbChars = @{"``"="Backquote";"~"="Tilda";"!"="Exclamation Mark"; ` "@"="At Sign";"#"="Pound Sign";"`$"="Dollar Sign";"%"="Percent"; ` "^"="Carat";"&"="Ampersand";"*"="Asterisk";"("="Open Parentheses"; ` ")"="Close Parentheses";"-"="Dash";"_"="Underscore";"="="Equal Sign"; ` "+"="Plus";"{"="Open Curly Brace";"}"="Close Curly Brace";"["="Open Bracket"; ` "]"="Close Bracket";"\"="Back Slash";"|"="Pipe Symbol";";"="Semicolon"; ` ":"="Colon";"'"="Apostrophe";"`""="Quote";","="Comma";"."="Period"; ` "/"="Forward Slash";"<"="Open Angle Bracket"; ` ">"="Close Angle Bracket";"?"="Question Mark";" "="Space"} $First = $True # Consider each string. ForEach ($String In $Strings) { If ($Complex) {$OK = $False} Else {$OK = $True} # If not the first page of output, print a form feed character. # The form feed character is recognized by Microsoft Word, if the output # is opened in Unicode. $Output is the multi-line output for each input string # (unless rejected for complexity). If ($First) {$Output = "------------------"} Else {$Output = "`f`r`n------------------"} # Display the string delimited by >>> and <<<. $Output = "$Output`r`n${Label}: >>> $String <<<" # Spell the string phonetically. # Count the number of each type of character. $LC = 0 $UC = 0 $Digits = 0 $Symbols = 0 $Output = "$Output`r`nSpelled out phonetically:" # Consider each character of the string. For ($k = 0; $k -lt $String.Length; $k = $k + 1) { # Retrieve the character. $Char = $String.SubString($k, 1) # Determine the decimal ASCII value. Trap cases where the value is out of # range for bytes. These are non-keyboard characters. # In these cases assign 0 to $Asc so the character is treated as a symbol. Try {$Asc = [byte][char]$Char} Catch {$Asc = 0} # Determine if lower case, upper case, numeric, or other (symbol). If (($Asc -ge 97) -And ($Asc -le 122)) { # Character is a lower case letter. $C = $LCChars[$Char] $LC = $LC + 1 } ElseIf (($Asc -ge 65)-And ($Asc -le 90)) { # Character is an upper case letter. $C = $UCChars[$Char] $UC =$UC + 1 } ElseIf (($Asc -ge 48) -And ($Asc -le 57)) { # Character is a digit. $C = $DigitChars[$Char] $Digits = $Digits + 1 } Else { # All other characters are assumed to be symbols. $C = $SymbChars[$Char] $Symbols = $Symbols + 1 } # If the character is not in any of the arrays, # the phonetic spelling is "". If (-Not $C) {$C = ""} $Output = "$Output`r`n$Char ($C)" } # End of For loop to consider each character of the string. If ($Complex) { # Determine if the string meets the complexity requirements, where at least 3 # of the following 4 categories of characters are included in the string: # Lower case letters, upper case letters, digits, and symbols. $Cmpl = 0 If ($LC -gt 0) {$Cmpl = $Cmpl + 1} If ($UC -gt 0) {$Cmpl = $Cmpl + 1} If ($Digits -gt 0) {$Cmpl = $Cmpl + 1} If ($Symbols -gt 0) {$Cmpl = $Cmpl + 1} If ($Cmpl -ge 3) {$OK = $True} } If ($OK) { # Output for this string, so it can be redirected to a text file. $Output = "$Output`r`n------------------" $Output # If -Verbose selected, the following is not redirected to a text file. # Display the number of characters in each of the 4 categories. Write-Verbose "${Label}: >>> $String <<<" Write-Verbose "Number of each type of character" Write-Verbose "Lower case letters: $LC" Write-Verbose "Upper case letters: $UC" Write-Verbose "Digits: $Digits" Write-Verbose "Symbols: $Symbols" $First = $False } Else { # String rejected due to complexity requirements. # This warning is not redirected to a text file. # Highlight the rejected string in different colors. Write-Host "$Label " -ForegroundColor Red -BackgroundColor Black -NoNewLine Write-Host "$String" -ForegroundColor Black -BackgroundColor White -NoNewLine Write-Host " rejected due to complexity requirements" ` -ForegroundColor Red -BackgroundColor Black Write-Verbose "Number of each type of character" Write-Verbose "Lower case letters: $LC" Write-Verbose "Upper case letters: $UC" Write-Verbose "Digits: $Digits" Write-Verbose "Symbols: $Symbols" } } # End of ForEach loop for strings. } # End of Function Spell-Phonetic.