I would like to calculate an MD5 checksum of some content. How do I do this in PowerShell?
This becomes a one-liner if you download File Checksum Integrity Verifier (FCIV) from Microsoft.
I downloaded FCIV from here: Availability and description of the File Checksum Integrity Verifier utility
Run the following command. I had ten files to check.
Get-ChildItem WTAM*.tar | % {.\fciv $_.Name}
There are a lot of examples online using ComputeHash(). My testing showed this was very slow when running over a network connection. The snippet below runs much faster for me, however your mileage may vary:
$md5 = [System.Security.Cryptography.MD5]::Create("MD5")
$fd = [System.IO.File]::OpenRead($file)
$buf = New-Object byte[] (1024*1024*8) # 8 MB buffer
while (($read_len = $fd.Read($buf,0,$buf.length)) -eq $buf.length){
$total += $buf.length
$md5.TransformBlock($buf,$offset,$buf.length,$buf,$offset)
Write-Progress -Activity "Hashing File" `
-Status $file -percentComplete ($total/$fd.length * 100)
}
# Finalize the last read
$md5.TransformFinalBlock($buf, 0, $read_len)
$hash = $md5.Hash
# Convert hash bytes to a hexadecimal formatted string
$hash | foreach { $hash_txt += $_.ToString("x2") }
Write-Host $hash_txt
Here's a function I use that handles relative and absolute paths:
function md5hash($path)
{
$fullPath = Resolve-Path $path
$md5 = new-object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
$file = [System.IO.File]::Open($fullPath,[System.IO.Filemode]::Open, [System.IO.FileAccess]::Read)
try {
[System.BitConverter]::ToString($md5.ComputeHash($file))
} finally {
$file.Dispose()
}
}
Thanks to @davor above for the suggestion to use Open() instead of ReadAllBytes() and to @jpmc26 for the suggestion to use a finally block.
If you are using the PowerShell Community Extensions there is a Get-Hash commandlet that will do this easily:
C:\PS> "hello world" | Get-Hash -Algorithm MD5
Algorithm: MD5
Path :
HashString : E42B054623B3799CB71F0883900F2764
As stated in the accepted answer, Get-FileHash is easy to use with files, but it is also possible to use it with strings:
$s = "asdf"
Get-FileHash -InputStream ([System.IO.MemoryStream]::New([System.Text.Encoding]::ASCII.GetBytes($s)))