Get-FileHash in PowerShell: verify a file's SHA256 hash

Get-FileHash in PowerShell: verify a file's SHA256 hash

You downloaded the Firefox installer straight from the official site. Your antivirus didn't complain. But how do you know that, somewhere between Mozilla's server and your hard drive, nobody swapped that file for a modified version? The answer fits in two lines of PowerShell and a 64-character hexadecimal number.

What is Get-FileHash?

Get-FileHash is a native PowerShell cmdlet (available since version 4.0) that calculates the hash value of any file. A hash is a mathematical "fingerprint" of the content: changing a single byte produces a completely different hash. If the hash you calculate matches the one the vendor published, the file is identical to the one that left their server.

It's part of the Microsoft.PowerShell.Utility module, already loaded by default — it doesn't require additional installation or administrator privileges for most cases.

Basic syntax

# Calculate the SHA256 hash of a file (default algorithm)
Get-FileHash -Path "C:\Downloads\firefox-installer.exe"

# Expected output:
# Algorithm  Hash                                                             Path
# ---------  ----                                                             ----
# SHA256     9F86D081884C7D659A2FEAA0C55AD015A3BF4F1B2B0B822CD15D6C15B0F00A08 C:\...

The -Algorithm parameter sets the algorithm. PowerShell 7 supports SHA1, SHA256, SHA384, SHA512 and MD5. The default is SHA256 — use it unless the vendor publishes the hash in another format. MD5 and SHA1 are considered insecure for cryptographic verification, but they still show up in older Linux distributions and niche packages.

How do I compare the calculated hash with the official one?

Copy the hash the vendor published and compare it directly in PowerShell with the -eq operator. A True result confirms the file hasn't been altered; False means something is wrong.

# Official hash published by the vendor (illustrative example)
$officialHash = "B4D8A4F3E92A1C0D6B7E5F2A3C8D1E9F0A2B4C6D8E0F2A4B6C8D0E2F4A6B8C0D2"

# Calculate the hash of the downloaded file
$fileHash = (Get-FileHash -Path "C:\Downloads\app-installer.exe").Hash

# Compare (case-insensitive — upper/lowercase letters don't matter in hex)
$fileHash -eq $officialHash

If the result is False, don't run the file. Discard it, clear your browser cache and download it again — preferably from a different network, to rule out a local man-in-the-middle.

Checking multiple files in a folder

In deployment or audit contexts, hashing an entire directory is more efficient with Get-ChildItem in a pipeline:

# Calculate SHA256 for every file in a folder
Get-ChildItem -Path "C:\Scripts\" -File | Get-FileHash | Format-Table Algorithm, Hash, Path -AutoSize

To export the result as CSV — useful for recording a directory's state on a given date:

Get-ChildItem -Path "C:\Scripts\" -File |
    Get-FileHash |
    Export-Csv -Path "C:\Audit\hashes-$(Get-Date -Format 'yyyyMMdd').csv" -NoTypeInformation

Keep that CSV file and compare it against a future run to detect any change in the scripts — a basic file integrity monitoring technique.

Checking whether two files are identical

Before replacing a configuration file in production, it's worth confirming the staging file is exactly the same:

$hash1 = (Get-FileHash "C:\Prod\config.json").Hash
$hash2 = (Get-FileHash "C:\Staging\config.json").Hash

if ($hash1 -eq $hash2) {
    Write-Host "Files are identical." -ForegroundColor Green
} else {
    Write-Host "Files differ!" -ForegroundColor Red
}

That eliminates the risk of "they looked similar but weren't identical" — a single-character difference in a config JSON can take down a service.

When should you use MD5 vs. SHA256?

Use SHA256 (or higher) for security verification. MD5 has had known collisions since 2004 — it's technically possible to craft two files with different content and the same MD5 hash. For confirming that an installer hasn't been tampered with, that's unacceptable.

Reserve MD5 for cases where speed matters more than cryptographic guarantees: comparing backup copies on internal storage, deduplicating log files in an enterprise tool that only accepts MD5. In any context where integrity is a security question, SHA256 is the reasonable minimum.

Why isn't SHA1 good enough for security?

In 2017, Google and CWI demonstrated the first practical SHA1 collision (the SHAttered project), producing two different PDFs with the same hash. Since then, SHA1 has been considered unsuitable for integrity verification in a security context. Windows Update, Microsoft code signing and most modern distribution systems migrated to SHA256 years ago.

Real-world use cases

  • Windows ISOs: Microsoft publishes the SHA256 hash of every ISO on the download page. Calculate it before burning it to a USB drive — a corrupted or tampered ISO produces silent installation problems.
  • Open-source software packages: projects like Python, Node.js and Git publish SHA256 checksums alongside every release. Checking takes 10 seconds and eliminates the risk of downloading from a compromised mirror.
  • Forensic evidence: before working on a copy of a suspicious file, calculate and record its hash. That preserves the chain of custody — proof the file hasn't been modified since collection.
  • Deployment automation: in a CI/CD script, validate the artifact's hash before pushing it to the production server. One extra line that prevents deploying a corrupted package.

Limitations to keep in mind

Get-FileHash verifies integrity, not authenticity. A file can have the correct hash and still be malware — if the vendor's site was compromised and the official hash was swapped along with the file, the cmdlet will still say "True". That's why hash verification complements, but doesn't replace, an antivirus scan. For an extra layer, combine it with the VirusTotal verification guide before running any unknown installer.

To monitor file changes over time in production, dedicated FIM (File Integrity Monitoring) solutions like Windows' file audit module (covered in the post on auditing logs with PowerShell) offer real-time alerts that go beyond the snapshot a scheduled script can capture.

Conclusion

Get-FileHash is one of the simplest and most underused tools in PowerShell. Calculating an installer's SHA256 hash before running it takes less than 10 seconds and eliminates an entire category of risk — files corrupted in transit, downloads from a compromised mirror, local tampering. Add it to your sysadmin checklist alongside Invoke-WebRequest to close the download-verify-execute loop in a coherent pipeline.

If you use Get-FileHash for deployment automation or forensics, the CSV examples above probably already cover what you need. But if you want to expand into continuous monitoring, the natural next step is setting up scheduled tasks with Get-NetTCPConnection or audit scripts that fire an email alert when the hash changes.

Comments