Freigeben über


Hashmaker, Hashmaker, Make Me A Hash

While contemplating methods to determine whether a file had changed or been updated, I thought that an MD5 check would be a pretty simple way to figure out if something was different.

But what if I wanted to check bunches of stuff on the fly? Or download a file from a website and store it in memory and check it against an existing file? So many things rushed in, and I knew I had to take a break and figure this one out.

So, I thought: well, I could use Get-FileHash.  That's all well and good, and it does indeed generate an MD5 hash of a file.  However, Get-FileHash has a significant drawback for my purposes (hint: it's in the name).

That's right--it can only compute the hash of a file.  It can't do something like compute the hash of a string stored in memory.

Don't worry, Wanda--I've got a plan.

Save this as a .ps1, and dot-source it (. .\scriptname.ps1), and then you'll be right as rain:

 Function Get-Hash([String[]] $StringValue,[ValidateSet('SHA','SHA1','MD5','SHA256','SHA384','SHA512')]$Algorithm = "MD5") 
{
$HashedValue = New-Object System.Text.StringBuilder 
[System.Security.Cryptography.HashAlgorithm]::Create($Algorithm).ComputeHash([System.Text.Encoding]::UTF8.GetBytes($StringValue))|%{ 
[Void]$HashedValue.Append($_.ToString("x2")) 
} 
$HashedValue.ToString() 
}

Then, when you need to compute a hash of content stored in memory, simple run Get-Hash against it:

 PS C:\temp> $String = "Hello, World!"
PS C:\temp> $String | Out-File hello.txt
PS C:\temp> $SecondString = Get-Content hello.txt
PS C:\temp> $Download = (New-Object System.Net.WebClient).DownloadString("https://www.undocumented-features.com/wp-content/uploads/2019/03/Hello.txt").Trim()
PS C:\temp> Get-Hash $String
65a8e27d8879283831b664bd8b7f0ad4
PS C:\temp> Get-Hash $SecondString
65a8e27d8879283831b664bd8b7f0ad4
PS C:\temp> Get-Hash $Download
65a8e27d8879283831b664bd8b7f0ad4
PS C:\temp>

Voila! You can use the Algorithm parameter to compute hashes using different hash algorithms as well.  MD5 is the default that I set--though you're welcome to change it for your own purpsoes.

Now that we've found the hash--where's the beef?