Every script download on this blog shows a SHA256 hash next to it. The hash is computed when the site is built, from the exact file that is served. Checking it takes ten seconds. Do it.

The short version

Run Get-FileHash .\Script-Name.ps1 and compare the Hash value with the one shown on the post. SHA256 is the default algorithm, so -Algorithm SHA256 is optional.

Details

  • Get-FileHash returns an object with Algorithm, Hash and Path. The hash is upper-case hex; the blog may show it in lower case. That does not matter: PowerShell’s -eq compares strings case-insensitively, so (Get-FileHash .\Script-Name.ps1).Hash -eq '<hash from the post>' returns True for a match.
  • A matching hash proves the file was not changed in transit or on your disk after download. It does not prove who wrote it — the hash comes from the same website as the file. That is what code signing is for, and these scripts are not signed yet.
  • Only after you have read the script and the hash matches: if your execution policy is RemoteSigned, remove the “downloaded from the internet” mark with Unblock-File .\Script-Name.ps1. It deletes the file’s Zone.Identifier alternate data stream — the same thing as the Unblock checkbox in the file’s Properties dialog.
  • Do not “fix” a blocked script by setting the execution policy to Unrestricted or Bypass machine-wide. If you need it for a single session, -Scope Process limits the change to the current PowerShell process.
  • Avoid MD5 and SHA1 for this. Microsoft’s own documentation says they should only be used for simple change validation.

References