Skip to content

Instantly share code, notes, and snippets.

@thomasba
Created September 3, 2019 06:23
Show Gist options
  • Save thomasba/946c7c7ee91d4c056881943390e33723 to your computer and use it in GitHub Desktop.
Save thomasba/946c7c7ee91d4c056881943390e33723 to your computer and use it in GitHub Desktop.
PowerShell function to create md5crypt string.
function Get-Md5Crypt {
<#
.DESCRIPTION
Generate a md5crypt string ($1$salt$hash)
.PARAMETER String
The string to hash
.PARAMETER Salt
The salt to use (can be a crypt string)
.PARAMETER SaltSize
In case no salt is provided generate one with length SaltSize (default: 10)
.NOTES
Thanks to Aaron Toponce explanation: https://pthree.org/2015/08/07/md5crypt-explained/
#>
param (
[Parameter(Position=0,ValueFromPipeline)]
[string]
$String,
[string]
$Salt,
[ValidateRange(3,100)]
[int]
$SaltSize = 10
)
if($String.Length -eq 0) {
$pass = [System.Net.NetworkCredential]::new("", (Read-Host -AsSecureString -Prompt "Enter Password")).Password
$repeat = [System.Net.NetworkCredential]::new("", (Read-Host -AsSecureString -Prompt "Repeat Password")).Password
if(-not $pass.Equals($repeat)) {
throw "Passwords didn't match!"
}
$String = $pass
}
if($Salt.Length -eq 0) {
$Salt = (-join ((48..57) +(65..90) + (97..122) | Get-Random -Count $SaltSize | ForEach-Object {[char]$_}))
}elseif($Salt.StartsWith('$1$')) {
$Salt = ($Salt -split '\$')[2]
}
$md5 = new-object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
$utf8 = new-object -TypeName System.Text.UTF8Encoding
$pw = [byte[]]$utf8.GetBytes($String)
$magic = [byte[]]$utf8.GetBytes('$1$')
$bsalt = $utf8.GetBytes($Salt)
$itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
$tmp = [System.Collections.ArrayList]@()
$tmp.AddRange($pw)
$tmp.AddRange($bsalt)
$tmp.AddRange($pw)
$db = $md5.ComputeHash([byte[]]$tmp)
$da_bytes = [System.Collections.ArrayList]@()
$da_bytes.AddRange($pw)
$da_bytes.AddRange($magic)
$da_bytes.AddRange($bsalt)
$i = $pw.Length
while($i -gt 0) {
if($i -gt 16) {
$da_bytes.AddRange($db)
}else{
$da_bytes.AddRange($db[0..$($i-1)])
}
$i -= 16
}
$i = $pw.Length
while($i -gt 0) {
if($i -band 1) {
$da_bytes.Add([byte]0) | Out-Null
}else{
$da_bytes.Add($pw[0]) | Out-Null
}
$i = $i -shr 1
}
$dc = [byte[]]$md5.ComputeHash([byte[]]$da_bytes)
for($i = 0; $i -lt 1000; $i++) {
$tmp = [System.Collections.ArrayList]@()
if($i -band 1) {
$tmp.AddRange($pw)
}else{
$tmp.AddRange($dc)
}
if($i%3) { $tmp.AddRange($bsalt) }
if($i%7) { $tmp.AddRange($pw) }
if($i -band 1) {
$tmp.AddRange($dc)
}else{
$tmp.AddRange($pw)
}
$dc = [byte[]]$md5.ComputeHash([byte[]]$tmp)
}
$final = ''
@(@(0,6,12),@(1,7,13),@(2,8,14),@(3,9,15),@(4,10,5)) | ForEach-Object {
$x, $y, $z = $_
$v = ([int]$dc[$x] -shl 16) -bor ([int]$dc[$y] -shl 8) -bor [int]$dc[$z]
1..4 | ForEach-Object {
$final += $itoa64[ $v -band 0x3f ]
$v = $v -shr 6
}
}
$v = [int]$dc[11]
1..2 | ForEach-Object {
$final += $itoa64[$v -band 0x3f]
$v = $v -shr 6
}
'{0}{1}${2}' -f $utf8.GetString($magic),$salt,$final
}
@meersau
Copy link

meersau commented Apr 17, 2024

Great!

To work with an UNIX appliance salt is max 8

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment