What SHA-256 is and where it is used
SHA-256 is a member of the SHA-2 family published by NIST in 2001 (FIPS 180-4). It processes input in 512-bit blocks through 64 rounds and produces a 256-bit digest — 64 hexadecimal characters, or 44 characters when Base64-encoded. After more than two decades of analysis there is no practical collision or preimage attack, which is why it is the default digest almost everywhere: TLS certificates, code signing, Bitcoin mining and block hashes, Docker image digests, Subresource Integrity attributes, JWT signatures via HMAC, and package checksums for Linux distributions.
Its cousins differ mainly in output size and internal word width. SHA-224 and SHA-256 use 32-bit words; SHA-384 and SHA-512 use 64-bit words and are often slightly faster on 64-bit CPUs despite the longer output. SHA-512/256 truncates SHA-512 output to 256 bits for exactly that reason. Unless a specification requires otherwise, SHA-256 is the safe default.
SHA-256 with salt for passwords — the honest version
Salting SHA-256 fixes one problem and leaves a bigger one. The fix: identical passwords no longer share a digest, so rainbow tables and precomputed dumps become useless and an attacker must attack each record individually. The problem that remains: SHA-256 is engineered for throughput. Purpose-built rigs test tens of billions of candidates per second, so a salted SHA-256 of an eight-character human-chosen password still falls in hours.
The standard remedy is iteration: PBKDF2-SHA256 applies the hash hundreds of thousands of times so each guess costs real time, while keeping SHA-256 as the underlying primitive — useful in FIPS-constrained environments. Otherwise use a memory-hard function such as Argon2id or scrypt, or bcrypt. The password hash generator shows PBKDF2-SHA256 and bcrypt side by side on the same input.
HMAC-SHA256 vs plain SHA-256
When you need to prove a message came from someone holding a shared secret — a webhook from Stripe or GitHub, an AWS Signature V4 request, a signed JWT — you need a keyed construction, not a bare digest. HMAC hashes the key and message through two nested passes with distinct padding, which makes it immune to the length-extension weakness that affects naive sha256(secret + message) schemes. Always compare the received tag to your computed tag with a constant-time function so response timing cannot leak the correct value byte by byte.
// Node.js — verify an incoming webhook signature
const expected = crypto.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
const ok = crypto.timingSafeEqual(Buffer.from(expected),
Buffer.from(receivedSignature));
Computing SHA-256 elsewhere
# terminal
echo -n "hello" | sha256sum # Linux
shasum -a 256 file.iso # macOS
Get-FileHash file.iso -Algorithm SHA256 # PowerShell
# Node.js
crypto.createHash('sha256').update('hello').digest('hex');
# Python
hashlib.sha256(b'hello').hexdigest()
# Browser (Web Crypto, async)
const buf = await crypto.subtle.digest('SHA-256', new TextEncoder().encode('hello'));
A quick reference value to sanity-check any implementation: the SHA-256 of the empty string is e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.
SHA-2 family at a glance
| Variant | Output bits | Hex length | Notes |
|---|---|---|---|
| SHA-224 | 224 | 56 | Truncated SHA-256, rarely needed |
| SHA-256 | 256 | 64 | The default choice |
| SHA-384 | 384 | 96 | Common in TLS cipher suites |
| SHA-512 | 512 | 128 | Often faster on 64-bit CPUs |
| SHA3-256 | 256 | 64 | Keccak sponge, structural backup |