X Xerobit

File Integrity Verification with Checksums — SHA-256 and MD5

Verify file integrity using SHA-256 and MD5 checksums. Learn how to generate and verify checksums on Linux, macOS, and Windows, use checksums in CI/CD pipelines, and detect...

Mian Ali Khalid · · 4 min read
Use the tool
Hash Generator
Generate MD5, SHA-1, SHA-256, and SHA-512 hashes client-side.
Open Hash Generator →

Checksums let you verify a file hasn’t been corrupted or tampered with. Download a file, generate its SHA-256 hash, compare against the published checksum — if they match, the file is intact.

Use the Hash Generator to compute checksums for files or text.

Generate checksums on Linux / macOS

# SHA-256:
sha256sum filename.zip
# Or on macOS:
shasum -a 256 filename.zip

# MD5:
md5sum filename.zip
# macOS:
md5 filename.zip

# Multiple files at once:
sha256sum *.deb

# Create a checksum file:
sha256sum *.tar.gz > SHA256SUMS.txt

# Verify against checksum file:
sha256sum --check SHA256SUMS.txt
# filename.tar.gz: OK

Generate checksums on Windows

# SHA-256 (PowerShell):
Get-FileHash filename.zip -Algorithm SHA256

# MD5:
Get-FileHash filename.zip -Algorithm MD5

# Compare to expected:
$expected = "abc123..."
$actual = (Get-FileHash filename.zip -Algorithm SHA256).Hash
$expected.ToUpper() -eq $actual  # True or False

# Command Prompt (certutil):
certutil -hashfile filename.zip SHA256
certutil -hashfile filename.zip MD5

Verify checksums in Python

import hashlib
from pathlib import Path

def sha256_file(filepath: str) -> str:
    """Compute SHA-256 hash of a file."""
    h = hashlib.sha256()
    with open(filepath, 'rb') as f:
        # Read in chunks for large files:
        for chunk in iter(lambda: f.read(65536), b''):
            h.update(chunk)
    return h.hexdigest()

def verify_checksum(filepath: str, expected_sha256: str) -> bool:
    actual = sha256_file(filepath)
    return actual.lower() == expected_sha256.lower()

# Usage:
expected = "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"
is_valid = verify_checksum('download.tar.gz', expected)
print(f"File {'valid' if is_valid else 'CORRUPTED/TAMPERED'}")

Node.js: hash a file

import { createHash } from 'crypto';
import { createReadStream } from 'fs';

async function sha256File(filepath) {
  return new Promise((resolve, reject) => {
    const hash = createHash('sha256');
    const stream = createReadStream(filepath);
    stream.on('data', chunk => hash.update(chunk));
    stream.on('end', () => resolve(hash.digest('hex')));
    stream.on('error', reject);
  });
}

// Verify download:
const hash = await sha256File('downloaded.tar.gz');
const expected = '2cf24dba...';

if (hash !== expected) {
  throw new Error(`Checksum mismatch! Expected ${expected}, got ${hash}`);
}
console.log('File integrity verified.');

CI/CD: verify artifacts

# GitHub Actions — verify downloaded tool:
- name: Download and verify tool
  run: |
    curl -LO https://example.com/tool-v1.2.3.tar.gz
    echo "expected_sha256  tool-v1.2.3.tar.gz" | sha256sum --check
  
# Docker: verify base image via digest:
FROM ubuntu@sha256:a93c8a4b5...  # Pinned digest, not tag

# npm: package-lock.json stores hashes:
# "integrity": "sha512-abc123..."

Distributing checksums with your software

# Create signed checksum file:
sha256sum release.tar.gz release.zip > SHA256SUMS.txt

# Sign with GPG:
gpg --detach-sign --armor SHA256SUMS.txt
# Creates SHA256SUMS.txt.asc

# Users verify:
gpg --verify SHA256SUMS.txt.asc SHA256SUMS.txt
sha256sum --check SHA256SUMS.txt

Content-addressable storage

Checksums enable deduplication and caching by content identity:

// Store files by their hash (like Git objects):
import { writeFile, readFile, mkdir } from 'fs/promises';
import { createHash } from 'crypto';
import path from 'path';

async function storeByHash(content, storageDir) {
  const hash = createHash('sha256').update(content).digest('hex');
  const dir = path.join(storageDir, hash.slice(0, 2)); // sharding
  const filepath = path.join(dir, hash);
  
  await mkdir(dir, { recursive: true });
  await writeFile(filepath, content);
  return hash;
}

async function retrieveByHash(hash, storageDir) {
  const filepath = path.join(storageDir, hash.slice(0, 2), hash);
  return readFile(filepath);
}

When MD5 vs SHA-256

  • MD5: Use only when security is irrelevant (deduplication keys, cache tags, non-security checksums). Fast, 128-bit output.
  • SHA-256: Use for security-relevant integrity verification (download verification, artifact signing, content hashing in storage). 256-bit output, collision-resistant.

Never use MD5 for security — it’s cryptographically broken.


Related posts

Related tool

Hash Generator

Generate MD5, SHA-1, SHA-256, and SHA-512 hashes client-side.

Written by Mian Ali Khalid. Part of the Dev Productivity pillar.