Monday, March 21, 2011

MD5 Hash For PowerShell

For a project, I had a requirement to move selected files between two servers and provide proof that the copied matched exactly the original file. A common method to provide this proof is through a MD5 hash for each of the files to create a fingerprint. A MD5 hash provides the ability to compare two files without having to go to the trouble and slowness of comparing the files byte by byte using the algorithm created by Ron Rivest in 1991 to create a 128-bit hash. You can save the hash and use it for future reference to see if the file has changed.

In the code sample below, I use the System.Security.Cryptography.MD5CryptoServiceProvider class to create the hash in bytes then convert it to a string using the System.Bitconverter class and removing all dashes to create a 32 character representation of that hash. If you require even more bits to be present in your hash, the System.Security.Cryptography namespace provides up to 512 bits. To achieve this level of security, use System.Security.Cryptography.SHA512Managed class instead of System.Security.Cryptography.MD5CryptoServiceProvider in the function.

To test out this code, change out the file names below. Copy a file to a new location, run the function and see the results. Then open the copied file, make a minor edit and test again. It's interesting to see the changes in the returned hash.
Function Get-MD5Hash($fileName) {
 if([System.IO.File]::Exists($fileName)) {
  $fileStream = New-Object System.IO.FileStream($fileName,[System.IO.FileMode]::Open,[System.IO.FileAccess]::Read,[System.IO.FileShare]::ReadWrite)
  $MD5Hash = New-Object System.Security.Cryptography.MD5CryptoServiceProvider
  [byte[]]$fileByteChecksum = $MD5Hash.ComputeHash($fileStream)
  $fileChecksum = ([System.Bitconverter]::ToString($fileByteChecksum)).Replace("-","")
  $fileStream.Close()
 } else {
  $fileChecksum = "ERROR: $fileName Not Found"
 }
 return $fileChecksum
}

$fileName = "\\east-coast-fs.ad.mycompany.local\documents\Important Excel Spreadsheet.xlsx"
$fileChecksumOne = Get-MD5Hash $fileName
if($fileChecksumOne -match "^ERROR:") {
 Write-Host $fileChecksumOne -foregroundColor Red
 exit
}

$fileName = "\\west-coast-fs.ad.mycompany.local\documents\Important Excel Spreadsheet.xlsx"
$fileChecksumTwo = Get-MD5Hash $fileName
if($fileChecksumTwo -match "^ERROR:") {
 Write-Host $fileChecksumTwo -foregroundColor Red
 exit
}

if($fileChecksumOne -eq $fileChecksumTwo) {
 Write-Host "Files match!"
 Write-Host $fileChecksumOne -foregroundColor Green
 Write-Host $fileChecksumTwo -foregroundColor Green
} else {
 Write-Host "Files do not match!"
 Write-Host $fileChecksumOne -foregroundColor Red
 Write-Host $fileChecksumTwo -foregroundColor Green
}

No comments:

Post a Comment