Janik von Rotz


2 min read

XKCD PowerShell password generator

Through 20 ears of effort, we’ve successfully trained everyone to use passwords that are hard for humans to remember, but easy for computers to guess.

If you are a Hacker News binge reader such as me, you might have read this article: The Guy Who Invented Those Annoying Password Rules Now Regrets Wasting Your Time.

This article reminded my of how stupid current password guidelines are and that we need to change that. A few months ago I wrote a random password generator function and decided that it needs an update to make the generated passwords more memorable.

Inspiration for the new random password was the following XKCD comic:

Untitled

So instead of using any kind of character for the password, simply put four random words together. To create this kind of password we need a word list with common nouns. I’ve created a german and english word list for you to download:

wordlist.de.txt wordlist.en.txt

Get-XKCDPassword.ps1

And here is the PowerShell function:

function Get-XKCDPassword {

    Param(
        [int]$words = 4,

        [string]$delimiter = "-",

        [ValidateSet("en","de")] 
        [string]$lang = "en",

        [switch]$FirstLetterUpperCase  
    )
    
    $password = ""
    $wordlist = @{
        de = "/wp-content/uploads/2017/08/wordlist.de_.txt"
        en = "/wp-content/uploads/2017/08/wordlist.en_.txt"
    }
    
    switch($words) {
        {$_ -ge 6 } { throw "Word parameter cannot be greater or equal 6." }
        5 { $range = (3,4) }
        4 { $range = (4,5) }
        3 { $range = (5,6) }
        2 { $range = (7,8) }
        {$_ -le 1 } { throw "Word parameter cannot be less or equal 1." }
    }

    $list = (((Invoke-WebRequest $wordlist[$lang]).Content -split "`n" | ForEach-Object{ 
        New-Object PSObject -Property @{
            Value = $_.ToLower()
            Length=$_.length
        }
    }) | Where-Object { ($_.Length -eq ($range[0] + 1)) -or ($_.Length -eq ($range[1] + 1)) })

    1..$words | ForEach-Object {
        $part =  (Get-Random $list).Value.Trim()

        if($FirstLetterUpperCase ) {
             $password += ((Get-Culture).TextInfo).ToTitleCase($part)
        } else {
            $password += $part
        }

        if($_ -lt $words){ 
            $password += $delimiter 
        }
    }

    return $password
}

Get-XKCDPassword -words 4 -delimiter "-" -lang "de" -FirstLetterUpperCase 

Here are some results:

bite-bomb-pupil-basis
crime-wedge-alley-roll
side-filly-bloom-fairy
read-tribe-mouth-jail
knot-make-child-moth

And a few more in german:

Seite-Sorge-Saft-Nadel
Fluss-Glas-Alter-Rand
Nord-Maul-Wert-Nabel
Sand-Schal-Anruf-Rand
Sahne-Post-Name-Park

Categories: scripting
Tags: password , powershell
Improve this page
Show statistic for this page