DicewarePassword.psm1
function Invoke-DiceRoll { <# .SYNOPSIS Simulates a dice roll and returns a number based on the result of rolling the desired number of dice. .DESCRIPTION Simulates a dice roll and returns a number based on the result of rolling the desired number of dice. The default dice count is 5, which was driven by the Diceware Passphrase minimum word length recommendation. See the help for the 'New-DicewarePassword' cmdlet/function for more information. .PARAMETER DiceCount The number of dice to roll .EXAMPLE Invoke-DiceRoll -DiceCount 8 51334144 .EXAMPLE Invoke-DiceRoll 31544 .INPUTS System.Int32 .OUTPUTS System.String .NOTES Author: Kevin Kirkpatrick Contact: https://github.com/vScripter Version: 1.0 Last Updated: 20151027 Last Updated By: K. Kirkpatrick Last Update Notes: - Created #> [CmdletBinding()] param ( [Parameter(Position = 0, Mandatory = $false)] [ValidateRange(1, 8)] [System.Int32]$DiceCount = 5 ) BEGIN { #Requires -Version 3 } # end BEGIN block PROCESS { $i = 0 Write-Verbose -Message "[Invoke-DiceRoll] Rolling dice; generating a {$DiceCount} digit random number." try { $numberResult = $null for (; $i -lt $DiceCount; $i++) { $number = $null $number = "$(Get-Random -Minimum 1 -Maximum 6)" $numberResult += $number } # end for loop $numberResult } catch { Write-Warning -Message "[Invoke-DiceRoll][ERROR]Error generating random number. $_ " } # end try/catch } # end PROCESS block END { Write-Verbose -Message "[Invoke-DiceRoll] Processing Complete" } # end END block } # end function Invoke-DiceRoll function New-DicewarePassword { <# .SYNOPSIS This function will generate/return a Diceware Password. .DESCRIPTION This function will generate/return a Diceware Password. Diceware involves, literally, rolling dice and matching the resulting numbers to a list containing 7,776 English words, each identified by a five-digit number. For more information on what the 'Diceware Passphrase' concept is, see the following link: http://world.std.com/~reinhold/diceware.html This function was inspired by the concepts and methods of creating Diceware Passphrases. That said, this function cannot guarantee 100% unique unique results for a few reasons: 1. I had to substite out the double-quote charater (") associated with number/entry 66634 with double-colons (::); I had issues returning a single, double-quote charater, based on how PowerShell handles quoations 2. Since a computer is handling the 'digital' dice rolls, one could argue that a bug in some system code, or at some other low level of computation, a computer (potentially) follows a discoverable algorithm...that's as far as I'll go, on that. Overall, this should still be a good tool to generate more complex, and easy to remember, passwords than you may have previously used. There are several 'Security Levels' that you can choose from, which equates to the total number of words utilized. In the Diceware FAQ, it states that "Six words may be breakable by an organization with a very large budget, such as a large country's security agency. Seven words and longer are unbreakable with any known technology, but may be within the range of large organizations by around 2030. Eight words should be completely secure through 2050." Some additional good resources/articles: http://arstechnica.com/business/2015/10/this-11-year-old-is-selling-cryptographically-secure-passwords-for-2-each/ http://arstechnica.com/information-technology/2014/03/diceware-passwords-now-need-six-random-words-to-thwart-hackers/ .PARAMETER FetchType Specify if you want to import the file from the web or from a local file path .PARAMETER URI URI of web-hosted file .PARAMETER Path Full path to file location .PARAMETER SecurityLevel Desired Security Level. Average = 5 words High = 6 words Extreme = 7 words UnHackable = 8 words .EXAMPLE New-DicewarePassword -Verbose This assumes a URI has been hard coded into the function and will attempt to pull the .CSV Diceware word list from a web-hosted file .EXAMPLE New-DicewarePassword -FetchType Web -URI 'https://server01/dicewarewordlist.csv' .EXAMPLE New-DicewarePassword -FetchType Local -Path C:\dicewarewordlist.csv .INPUTS System.String .OUTPUTS System.Management.Automation.PSCustomObject .NOTES Author: Kevin Kirkpatrick Contact: https://github.com/vScripter Version: 1.0 Last Updated: 20151027 Last Updated By: K. Kirkpatrick Last Update Notes: - Created #> [CmdletBinding(DefaultParameterSetName = 'Default')] param ( [Parameter(Position = 0, Mandatory = $false)] [ValidateSet('Local', 'Web')] [System.String]$FetchType = 'Web', [Parameter(Position = 1, ParameterSetName = 'Web')] [ValidateScript({ (Invoke-WebRequest -Uri $URI).StatusCode -eq 200 })] [System.String]$URI = 'https://dl.dropboxusercontent.com/u/22332521/DicewareWordList.csv', [Parameter(Position = 2, ParameterSetName = 'Local')] [ValidateScript({ Test-Path -LiteralPath $Path -PathType Leaf })] [System.String]$Path, [Parameter(Position = 3)] [ValidateSet('Average', 'High', 'Extreme', 'UnHackable')] [System.String]$SecurityLevel = 'Average' ) BEGIN { #Requires -Version 3 if ($URI) { Write-Verbose -Message "[New-DicewarePassword] Calling REST 'Get' method from URI {$URI}. I will then import and store the Diceware Word List" try { $wordList = $null $wordList = Invoke-RestMethod -Uri $URI -Method Get -ErrorAction Stop | ConvertFrom-Csv -ErrorAction Stop } catch { Write-Warning -Message "[New-DicewarePassword][ERROR] Importing and storing Diceware Word List from URI {$URI}. $_ " } # end try/catch } elseif ($Path) { Write-Verbose -Message "[New-DicewarePassword] Importing and storing Diceware Word List from Path {$Path}" try { $wordList = $null $wordList = Import-Csv -LiteralPath $Path -ErrorAction Stop } catch { Write-Warning -Message "[New-DicewarePassword][ERROR] Importing and storing Diceware Word List from Path {$Path}. $_ " } # end try/catch } # end if/elseif Write-Verbose -Message "[New-DicewarePassword] Security level of {$SecurityLevel} has been selected. Translating dice roll count." try { [void][int]$diceRollCount $diceRollCount = switch ($SecurityLevel) { Average { 5 } High { 6 } Extreme { 7 } UnHackable { 8 } } # end switch Write-Verbose -Message "[New-DicewarePassword] Dice will be rolled {$diceRollCount} time/s" } catch { Write-Warning -Message "[New-DicewarePassword][ERROR] Unable to translate dice roll count. $_ " } # end try/catch } # end BEGIN block PROCESS { Write-Verbose -Message "[New-DicewarePassword] Generating a {$diceRollCount} word Diceware Password based on Security Preference {$($SecurityLevel)}." try { $i = 0 $result1 = $null $result2 = $null for (; $i -lt $diceRollCount; $i++) { $word = $null $diceRoll = $null $diceRoll = Invoke-DiceRoll -ErrorAction Stop $word = ($wordList | Where-Object { $_.Number -eq $diceRoll }).Word $result1 += " $word" $result2 += $word } # end for loop $objPassWord = @() $objPassWord = [PSCustomObject] @{ PassWord = $result2.Trim() SpacedPassWord = $result1.Trim() } $objPassWord } catch { Write-Warning -Message "[New-DicewarePassword][ERROR] Could not generate Diceware Password. $_ " } # end try/catch } # end PROCESS block END { Write-Verbose -Message "[New-DicewarePassword] Processing Complete" } # end END block } # end function New-DicewarePassword Export-ModuleMember -Function * |