Skip to content
crypto2026-06-185 min read

"Isn't hashing just a type of encryption?" This question comes up constantly, and confusing the two causes real-world security incidents. Use encryption where you meant hashing, and a leaked key exposes every password in your database. Use hashing where you meant encryption, and the original data is gone forever.

This guide covers the actual mathematical difference between the two, where each belongs, and the password storage mistakes that keep showing up in breach reports. You can generate your own digests with our SHA-256 hash generator to test the one-way property directly.

The One-Sentence Distinction

Hashing is one-way. Encryption is two-way.

  • Hash: produces a fixed-length fingerprint of any input. You cannot recover the input from the fingerprint.
  • Encryption: converts plaintext to ciphertext using a key. With the right key, you get the plaintext back.

Everything else follows from that.

Hashing: The One-Way Function

A hash function takes arbitrary input and produces a fixed-length digest. The defining properties:

  • Deterministic: same input always yields the same output
  • One-way: infeasible to reverse the function and recover the input
  • Collision-resistant: infeasible to find two distinct inputs with the same output

Common hash functions in production:

# SHA-256 (32 bytes, 64 hex characters)
echo -n "hello" | shasum -a 256
# 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824

# MD5 (16 bytes, 32 hex characters, broken for security)
echo -n "hello" | md5
# 5d41402abc4b2a76b9719d911017c592

Where hashing fits:

  • File integrity checks: compare checksums before and after transfer
  • Content-addressable storage: Git uses object hashes as identifiers
  • Cache keys and deduplication: identical content produces identical keys
  • Password storage: with a critical caveat, explained below

Encryption: The Two-Way Function

Encryption needs a key. The same key (or a paired one) reverses the transformation.

Two flavors:

Symmetric encryption: same key for encrypt and decrypt. Fast, ideal for bulk data.

# AES-GCM, the de facto standard for symmetric encryption
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os

key = AESGCM.generate_key(bit_length=256)
nonce = os.urandom(12)
aesgcm = AESGCM(key)

ciphertext = aesgcm.encrypt(nonce, b"secret message", None)
plaintext = aesgcm.decrypt(nonce, ciphertext, None)
# plaintext == b"secret message"

Asymmetric encryption: key pair, public encrypts, private decrypts. Slower, but solves key distribution.

# RSA: encrypt with public key, decrypt with private key
openssl rsautl -encrypt -pubin -inkey public.pem -in message.txt -out encrypted.bin
openssl rsautl -decrypt -inkey private.pem -in encrypted.bin -out message.txt

Where encryption fits:

  • Transport security: TLS uses hybrid encryption to protect HTTPS
  • Data at rest: full-disk encryption, encrypted database columns
  • Digital envelopes: encrypt data with a symmetric key, encrypt that key with an asymmetric one
  • Anywhere the original data must be recoverable

Password Storage: The Persistent Trap

Passwords are where hashing and encryption get conflated most often. The rules are unambiguous.

Never encrypt passwords. Never use a raw hash for passwords.

Encrypted passwords can be reversed. When (not if) the encryption key is compromised, typically stored on the same host as the database, every password becomes plaintext instantly.

Raw SHA-256 or MD5 hashes are equally unacceptable. They're too fast. A modern GPU tries tens of billions of hashes per second, and dictionary attacks crack weak passwords in hours.

The right tool is a password hashing function:

import bcrypt

# Hash with automatic salt (work factor 12 is reasonable in 2026)
hashed = bcrypt.hashpw(b"mypassword", bcrypt.gensalt(rounds=12))
# b'$2b$12$...'

# Verify later
bcrypt.checkpw(b"mypassword", hashed)  # True
bcrypt.checkpw(b"wrongpassword", hashed)  # False

Password hashing functions (bcrypt, scrypt, argon2id) share one critical property: they are deliberately slow. A work factor parameter makes each hash take a controlled amount of time, usually hundreds of milliseconds. Brute force becomes computationally infeasible. Argon2id, winner of the 2015 Password Hashing Competition, is the current recommended standard.

When to Use Which

The decision reduces to one question: do you need to recover the original data?

  • Yes → encrypt
  • No → hash

Expanded into a decision table:

| Use case | Hash | Encrypt | |----------|------|---------| | User passwords | ✓ (bcrypt or argon2) | ✗ | | API request signing | ✓ (HMAC) | ✗ | | File integrity verification | ✓ | ✗ | | Cache keys / dedup | ✓ | ✗ | | Database column (queryable) | ✗ | ✓ | | Communication content (TLS, messages) | ✗ | ✓ | | Encrypted backups | ✗ | ✓ | | Digital signatures | ✓ (hash then sign) | ✓ (asymmetric) |

The last row shows both at work: hash the document to compress it, then sign the hash with an asymmetric key. Signing the full document with asymmetric crypto would be prohibitively slow.

Performance Notes

Hashing is typically fast, and both hashing and encryption benefit from hardware acceleration on modern CPUs:

| Operation | Throughput on modern hardware | |-----------|-------------------------------| | SHA-256 (with SHA-NI) | ~1.2 GB/s | | AES-256-GCM (with AES-NI) | ~5 GB/s | | bcrypt (rounds=12) | ~100 hashes/second |

Note that bcrypt throughput is measured in hashes per second, not gigabytes per second. The slowness is intentional and is exactly what you want for password hashing.

Do It All In Your Browser

Whether you're hashing an API key, encrypting a config snippet, or generating a password hash, you should not be sending sensitive data to an unfamiliar server.

The SHA-256 Hash Generator, MD5 Hash Generator, bcrypt Hash, AES Encrypt/Decrypt, and RSA Encrypt/Decrypt tools all run entirely in your browser using the Web Crypto API. Your plaintext, keys, passwords, and hash outputs never leave your machine. No logs, no retention, no third-party exposure. That matters most when you're working with API credentials, customer data, or proprietary source.

The short version: encrypt when you need to recover the plaintext, hash when you don't, use bcrypt or argon2 for passwords, and never confuse those three.


Advertisement