Last updated:
Hashes in PowerShell
Why the hashes belong in the signed report is explained on Integrity.
One file
Get-FileHash -Algorithm SHA256 -LiteralPath .\file.pst
All files in a folder
Written to CHECKSUMS_SHA256.txt one level up:
Get-ChildItem -Recurse -File |
Get-FileHash -Algorithm SHA256 |
ForEach-Object { '{0} *{1}' -f $_.Hash, (Resolve-Path -LiteralPath $_.Path -Relative) } |
Set-Content -Encoding utf8 ..\CHECKSUMS_SHA256.txt
Checking
Run it in the data folder:
$errors = 0
Get-Content ..\CHECKSUMS_SHA256.txt -Encoding utf8 | Where-Object { $_ } | ForEach-Object {
$expected, $path = $_ -split ' \*', 2
if (-not (Test-Path -LiteralPath $path)) { $errors++; "MISSING: $path"; return }
if ((Get-FileHash -Algorithm SHA256 -LiteralPath $path).Hash -ne $expected) { $errors++; "MISMATCH: $path" }
}
if ($errors -eq 0) { 'All files match.' } else { "$errors deviation(s) found." }
This reports changed and missing files, but not a file that has been added.
Pitfalls
Add -Encoding utf8 to Set-Content. Windows PowerShell 5.1 otherwise writes in the system’s code page. A file name with an accent or a Cyrillic letter then ends up garbled in the list. In a folder of email attachments that happens easily.
Use -LiteralPath, not -Path. With -Path, PowerShell reads square brackets in a file name as wildcards, does not find the file and reports nothing. File names from mailboxes often contain square brackets.
Do not write the list into the folder you are hashing. Otherwise it includes itself half written. Write one level up and move it afterwards.