Skip to content

Instantly share code, notes, and snippets.

@joshooaj
Last active July 1, 2024 20:03
Show Gist options
  • Save joshooaj/182df7c3fe3f385b563ba1bd6c3e6ec4 to your computer and use it in GitHub Desktop.
Save joshooaj/182df7c3fe3f385b563ba1bd6c3e6ec4 to your computer and use it in GitHub Desktop.
Generate pseudo-random passwords
function New-Password {
<#
.SYNOPSIS
Generates a pseudo-random password.
.DESCRIPTION
This function generates a password with support for upper, and lower-case
characters, numbers, and symbols.
.PARAMETER Length
The desired password length. The default value is 16 characters.
.PARAMETER IncludeSpecial
Adds one or more special characters to the password.
.PARAMETER MinNumbers
The number of numerals to include in the password.
.PARAMETER MinSpecial
The number of special characters to include in the password.
.PARAMETER ModHex
Specifies that the special ModHex character set should be used. It is
recommended to use a much longer password when using this limited character
set.
.PARAMETER AsPlainText
Specifies that the password should be returned in plain text instead of a
[securestring] object.
.EXAMPLE
New-Password
Generates a 16-character password with upper-case, and lower-case
characters, and one numeral.
.EXAMPLE
New-Password -AsPlainText
Generates a 16-character password with upper-case, and lower-case
characters, and one numeral, and returns it as a string instead of a
[securestring] object.
.EXAMPLE
New-Password -Length 64 -ModHex
Generates a 64-character password using the ModHex character set.
.EXAMPLE
New-Password -IncludeSpecial
Generates a 16-character password with upper-case, and lower-case
characters, one numeral, and one special character.
.EXAMPLE
New-Password -IncludeSpecial -MinNumbers 2 -MinSpecial 2
Generates a 16-character password with upper-case, and lower-case
characters, two numerals, and two special characters.
.EXAMPLE
New-Password -Length 32 -IncludeSpecial -MinNumbers 6 -MinSpecial 4
Generates a 32-character password with upper-case, and lower-case
characters, six numerals, and four special characters.
.NOTES
The ModHex character set is used by Yubikey in some cases as these
characters are reliably found in the same place on most keyboards in most
locales. Read more here: https://docs.yubico.com/yesdk/users-manual/application-otp/modhex.html
Character sets
- Upper: ABCDEFGHIJKLMNOPQRSTUVWXYZ
- Lower: abcdefghijklmnopqrstuvwxyz
- Numbers: 0123456789
- Special: !@#$%^&*
- ModHex: bcdefghijklnrtuv
#>
[CmdletBinding(DefaultParameterSetName = 'Standard')]
[OutputType([securestring])]
param (
[Parameter(ParameterSetName = 'Standard')]
[Parameter(ParameterSetName = 'ModHex')]
[ValidateRange(1, [int]::MaxValue)]
[int]
$Length = 16,
[Parameter(ParameterSetName = 'Standard')]
[switch]
$IncludeSpecial,
[Parameter(ParameterSetName = 'Standard')]
[ValidateRange(1, [int]::MaxValue)]
[int]
$MinNumbers = 1,
[Parameter(ParameterSetName = 'Standard')]
[ValidateRange(1, [int]::MaxValue)]
[int]
$MinSpecial = 1,
[Parameter(Mandatory, ParameterSetName = 'ModHex')]
[switch]
$ModHex,
[Parameter(ParameterSetName = 'Standard')]
[Parameter(ParameterSetName = 'ModHex')]
[switch]
$AsPlainText
)
begin {
$upper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.ToCharArray()
$lower = 'abcdefghijklmnopqrstuvwxyz'.ToCharArray()
$numbers = '0123456789'.ToCharArray()
$special = '!@#$%^&*'.ToCharArray()
$modhexChars = 'bcdefghijklnrtuv'.ToCharArray()
}
process {
$chars = [collections.generic.list[char]]::new()
if ($IncludeSpecial) {
1..$MinSpecial | ForEach-Object {
$chars.Add(($special | Get-Random))
}
}
switch ($PSCmdlet.ParameterSetName) {
'Standard' {
1..$MinNumbers | ForEach-Object {
$chars.Add(($numbers | Get-Random))
}
1..($Length - $chars.Count) | ForEach-Object {
if ($_ % 2) {
$chars.Add(($upper | Get-Random))
} else {
$chars.Add(($lower | Get-Random))
}
}
}
'ModHex' {
for ($i = 0; $i -lt $Length; $i++) {
$chars.Add(($modhexChars | Get-Random))
}
}
Default {
throw "ParameterSet '$_' not implemented."
}
}
$ss = [securestring]::new()
$chars | Get-Random -Count $chars.Count | ForEach-Object {
$ss.AppendChar($_)
}
if ($AsPlainText) {
[pscredential]::new('a', $ss).GetNetworkCredential().Password
$ss.Dispose()
} else {
$ss
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment