SHA-256 Hashing Explained: How It Works and Why It Matters

By Taylor Feb 22, 2026 16 min read

Every time you log into a website, download software, make a cryptocurrency transaction, or verify a file's integrity, you are relying on cryptographic hashing. SHA-256 (Secure Hash Algorithm 256-bit) is the most widely used hash function in the world, securing everything from Bitcoin's blockchain to the SSL certificates that protect your web browsing.

This guide explains what hashing is from the ground up, how SHA-256 works at a conceptual level, how it compares to older algorithms like MD5 and SHA-1, and practical code examples in every major programming language. Whether you are implementing password storage, verifying file downloads, or just curious about how blockchain works, this guide has you covered.

Table of Contents
  1. What Is Hashing?
  2. Properties of Cryptographic Hashes
  3. How SHA-256 Works
  4. SHA-256 vs. MD5 vs. SHA-1
  5. Use Cases
  6. Code Examples in Every Language
  7. Password Hashing (Do It Right)
  8. Common Misconceptions
  9. The Future: SHA-3 and Beyond

1. What Is Hashing?

A hash function takes an input of any size (a password, a file, an entire database) and produces a fixed-size output called a hash, digest, or fingerprint. SHA-256 always produces a 256-bit (32-byte) output, regardless of whether the input is a single character or a 10-gigabyte video file.

Input: "hello"
SHA-256: 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824

Input: "hello!"
SHA-256: ce06092fb948d9ffac7d1a376e404b26b7575bcc11ee05a4615fef4fec3a308b

Input: "hello" (same as first)
SHA-256: 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824

Notice three crucial things from this example:

2. Properties of Cryptographic Hashes

Not all hash functions are cryptographic. A cryptographic hash function like SHA-256 must satisfy five properties that regular hash functions (like those used in hash tables) do not need to meet:

Pre-image Resistance (One-Way)

Given a hash output, it must be computationally infeasible to find any input that produces that hash. You cannot "reverse" the hash to get the original data. This is what makes hashing fundamentally different from encryption: encryption is designed to be reversed (decrypted), while hashing is designed to be irreversible.

Second Pre-image Resistance

Given an input and its hash, it must be infeasible to find a different input that produces the same hash. This property is crucial for file integrity: if you verify that a file's hash matches the expected value, you can be confident no one has tampered with the file.

Collision Resistance

It must be infeasible to find any two different inputs that produce the same hash. Since SHA-256 has a 256-bit output, there are 2^256 possible hashes. Finding a collision by brute force would require approximately 2^128 operations (due to the birthday paradox), which is far beyond current computational capabilities.

Uniform Distribution

Hash outputs should be uniformly distributed across the output space. No hash value should be more likely than any other, and the outputs should appear random (even though they are deterministic).

Efficiency

Computing the hash should be fast for any given input. SHA-256 can hash gigabytes of data per second on modern hardware. This is important because hash functions are called billions of times per day across the internet.

3. How SHA-256 Works

SHA-256 belongs to the SHA-2 family, designed by the NSA and published by NIST in 2001. While the full algorithm involves 64 rounds of mathematical operations on 32-bit words, here is a conceptual overview of the process:

  1. Padding: The input message is padded to a length that is a multiple of 512 bits. The padding includes the original message length, which prevents length extension attacks.
  2. Parsing: The padded message is divided into 512-bit blocks.
  3. Initialization: Eight 32-bit hash values (H0 through H7) are initialized to specific constants derived from the fractional parts of the square roots of the first eight primes.
  4. Compression: Each 512-bit block is processed through 64 rounds of operations involving bitwise logic (AND, OR, XOR, NOT), addition modulo 2^32, and right rotations. Each round uses a unique constant derived from the cube roots of the first 64 primes.
  5. Output: After all blocks are processed, the eight hash values are concatenated to produce the final 256-bit digest.
/* The 8 initial hash values (first 32 bits of the fractional
   parts of the square roots of the first 8 primes) */
H0 = 0x6a09e667    /* sqrt(2)  */
H1 = 0xbb67ae85    /* sqrt(3)  */
H2 = 0x3c6ef372    /* sqrt(5)  */
H3 = 0xa54ff53a    /* sqrt(7)  */
H4 = 0x510e527f    /* sqrt(11) */
H5 = 0x9b05688c    /* sqrt(13) */
H6 = 0x1f83d9ab    /* sqrt(17) */
H7 = 0x5be0cd19    /* sqrt(19) */

The beauty of SHA-256's design is that every bit of the input affects every bit of the output through the 64 rounds of mixing. This is why changing a single character in the input completely transforms the hash.

4. SHA-256 vs. MD5 vs. SHA-1

PropertyMD5SHA-1SHA-256
Output size128 bits (32 hex)160 bits (40 hex)256 bits (64 hex)
Year published199219952001
Collision resistanceBroken (2004)Broken (2017)Secure
SpeedFastestFastModerate
Security statusInsecureInsecureSecure
Use in 2026Checksums onlyLegacy onlyRecommended

MD5 Is Broken

MD5 collisions can be generated in seconds on a laptop. In 2008, researchers demonstrated that they could create a rogue SSL certificate with the same MD5 hash as a legitimate one, enabling man-in-the-middle attacks. MD5 should never be used for security. Its only acceptable use is as a fast checksum for detecting accidental corruption (not malicious tampering).

SHA-1 Is Broken

In 2017, Google's SHAttered project demonstrated the first practical SHA-1 collision, producing two different PDF files with the same SHA-1 hash. The attack required approximately 2^63 computations (9 quintillion). All major browsers and certificate authorities stopped accepting SHA-1 certificates by 2017. Git still uses SHA-1 for commit hashes but is migrating to SHA-256.

SHA-256 Is Secure

No collision has been found for SHA-256, and none is expected with current or foreseeable technology. Breaking SHA-256's collision resistance would require approximately 2^128 operations, which would take longer than the age of the universe using all the computing power on Earth. Even quantum computers, using Grover's algorithm, would only reduce this to 2^128 operations, which remains infeasible.

Hash Any Text Instantly

Hash Forge computes SHA-256, SHA-512, MD5, and SHA-1 hashes in real time. Paste text and see the hash update as you type.

Open Hash Forge

5. Use Cases

Password Storage

Websites never (should never) store your actual password. Instead, they store the hash of your password. When you log in, the server hashes the password you entered and compares it to the stored hash. If they match, you are authenticated. If the database is breached, attackers get hashes, not passwords.

Important caveat: Plain SHA-256 is not suitable for password hashing. See the Password Hashing section below for why and what to use instead.

File Integrity Verification

When you download software, the website often provides a SHA-256 hash alongside the download. After downloading, you compute the hash of the downloaded file and compare it to the published hash. If they match, the file has not been corrupted or tampered with during download.

# Verify a downloaded file (Linux/macOS)
sha256sum downloaded-file.tar.gz
# Output: a1b2c3d4... downloaded-file.tar.gz

# Compare with the published hash
echo "a1b2c3d4...  downloaded-file.tar.gz" | sha256sum --check
# Output: downloaded-file.tar.gz: OK

# Windows PowerShell
Get-FileHash downloaded-file.tar.gz -Algorithm SHA256

Blockchain and Cryptocurrency

Bitcoin uses SHA-256 extensively. Each block in the blockchain contains the SHA-256 hash of the previous block, creating an immutable chain. Mining involves finding a nonce (number) such that the SHA-256 hash of the block header starts with a certain number of zeros. This proof-of-work mechanism requires enormous computational effort to create but is trivial to verify.

Block Header:
    Previous Block Hash: 0000000000000000000abc...
    Merkle Root: def123...
    Timestamp: 1769472000
    Nonce: 2083236893

SHA-256(SHA-256(header)):
    000000000000000000012a4f... (starts with required zeros)

Digital Signatures

When you sign a document or software release digitally, the signing algorithm first computes the SHA-256 hash of the content, then encrypts the hash with your private key. The recipient verifies by decrypting the signature with your public key and comparing the result to their own hash computation. This proves both authenticity (it came from you) and integrity (it was not modified).

Git Commit Identification

Git identifies commits, trees, and blobs using SHA-1 hashes (migrating to SHA-256 in newer versions). Every git commit hash you see (like a1b2c3d) is a truncated hash of the commit's contents, including the author, message, timestamp, and parent commit hash.

API Request Signing

Many APIs (AWS, Stripe, Webhooks) use HMAC-SHA256 to sign requests. The sender computes a hash of the request body combined with a secret key. The receiver recomputes the hash and verifies it matches, proving the request was not tampered with and came from an authorized sender.

6. Code Examples in Every Language

JavaScript (Browser)

async function sha256(message) {
    const msgBuffer = new TextEncoder().encode(message);
    const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);
    const hashArray = Array.from(new Uint8Array(hashBuffer));
    return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
}

// Usage
const hash = await sha256('hello');
console.log(hash);
// 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824

Node.js

const crypto = require('crypto');

function sha256(input) {
    return crypto.createHash('sha256').update(input).digest('hex');
}

console.log(sha256('hello'));
// 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824

// HMAC-SHA256 (for API signing)
function hmacSha256(message, secret) {
    return crypto.createHmac('sha256', secret).update(message).digest('hex');
}

console.log(hmacSha256('data', 'my-secret-key'));

Python

import hashlib

# String hashing
hash_hex = hashlib.sha256('hello'.encode('utf-8')).hexdigest()
print(hash_hex)
# 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824

# File hashing (memory-efficient for large files)
def hash_file(filepath):
    sha256 = hashlib.sha256()
    with open(filepath, 'rb') as f:
        for chunk in iter(lambda: f.read(8192), b''):
            sha256.update(chunk)
    return sha256.hexdigest()

# HMAC-SHA256
import hmac
signature = hmac.new(
    b'my-secret-key',
    b'data',
    hashlib.sha256
).hexdigest()

Go

package main

import (
    "crypto/sha256"
    "fmt"
)

func main() {
    data := []byte("hello")
    hash := sha256.Sum256(data)
    fmt.Printf("%x\n", hash)
    // 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
}

Java

import java.security.MessageDigest;
import java.nio.charset.StandardCharsets;

public class SHA256Example {
    public static String sha256(String input) throws Exception {
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] hash = digest.digest(input.getBytes(StandardCharsets.UTF_8));
        StringBuilder hex = new StringBuilder();
        for (byte b : hash) {
            hex.append(String.format("%02x", b));
        }
        return hex.toString();
    }

    public static void main(String[] args) throws Exception {
        System.out.println(sha256("hello"));
    }
}

Bash / Command Line

# Hash a string
echo -n "hello" | sha256sum
# 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824  -

# Hash a file
sha256sum myfile.txt

# macOS
echo -n "hello" | shasum -a 256

# Windows PowerShell
$bytes = [System.Text.Encoding]::UTF8.GetBytes("hello")
$hash = [System.Security.Cryptography.SHA256]::Create().ComputeHash($bytes)
[BitConverter]::ToString($hash) -replace '-', '' | ForEach-Object { $_.ToLower() }

7. Password Hashing (Do It Right)

This is the most important section of this article, because getting password hashing wrong has catastrophic consequences. Do not use plain SHA-256 for passwords. Here is why:

Instead, use a purpose-built password hashing function that is intentionally slow and includes automatic salting:

AlgorithmRecommendationSpeed
Argon2idBest choice (winner of PHC)Configurable (100ms+)
bcryptExcellent, widely supported~100ms per hash
scryptGood, memory-hardConfigurable
PBKDF2-SHA256Acceptable with high iterationsConfigurable
SHA-256 (plain)NEVER for passwordsBillions/sec (too fast)
MD5NEVERBroken + too fast
# Python: Correct password hashing with bcrypt
import bcrypt

# Hashing a password (registration)
password = b"user_password_here"
salt = bcrypt.gensalt(rounds=12)  # 2^12 iterations
hashed = bcrypt.hashpw(password, salt)
# $2b$12$LJ3m4ys3Lgm0EvPzNuRVc.YyB0DBQdm9sp9IqaY1prVaKB0MnNSm2

# Verifying a password (login)
if bcrypt.checkpw(password, hashed):
    print("Password matches!")

# Node.js: Using bcrypt
const bcrypt = require('bcrypt');
const hash = await bcrypt.hash('user_password', 12);
const match = await bcrypt.compare('user_password', hash);

8. Common Misconceptions

9. The Future: SHA-3 and Beyond

SHA-3 (Keccak) was standardized by NIST in 2015 as a backup in case SHA-2 is ever compromised. SHA-3 uses a completely different internal structure (sponge construction) from SHA-2 (Merkle-Damgard), so a vulnerability in one family would not affect the other.

In practice, SHA-256 remains the standard for most applications in 2026. SHA-3 adoption is growing in specialized areas (Ethereum uses Keccak-256, a SHA-3 variant), but SHA-256 is not going anywhere. The key points:

Compute Hashes Instantly

Hash Forge computes SHA-256, SHA-512, SHA-1, and MD5 hashes in real time. Paste any text and see all hash values instantly.

Open Hash Forge