X Xerobit

SHA-256 Hash — How It Works and How to Use It in Code

SHA-256 produces a 256-bit (64 hex character) hash. It's used for data integrity verification, digital signatures, and file checksums. Here's how SHA-256 works and how to...

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

SHA-256 (Secure Hash Algorithm 256-bit) is a cryptographic hash function that produces a fixed 256-bit (32-byte, 64 hex character) output for any input. It’s the most widely used hash for data integrity and digital signatures.

Use the Hash Generator to compute SHA-256 and other hashes online.

SHA-256 properties

SHA-256("hello") = "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"
SHA-256("helo")  = "1cd9f9cc91c1b0fa7b18e72b6cefce10d48c4fe9c60869cc0f9e1cd7bf75fc33"

Key properties:

  • Fixed output size: always 256 bits (64 hex chars), regardless of input size
  • Deterministic: same input always produces the same hash
  • Avalanche effect: a one-character change produces a completely different hash
  • One-way: cannot reverse a hash to get the original input (in practice)
  • Collision resistant: practically impossible to find two inputs with the same hash

JavaScript (Web Crypto API)

The Web Crypto API is available in all modern browsers and Node.js 18+:

// Browser and Node.js 18+:
async function sha256(message) {
  const encoder = new TextEncoder();
  const data = encoder.encode(message);
  const hashBuffer = await crypto.subtle.digest('SHA-256', data);
  const hashArray = Array.from(new Uint8Array(hashBuffer));
  return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
}

await sha256('hello');
// '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824'

For files:

async function hashFile(file) {
  const buffer = await file.arrayBuffer();
  const hashBuffer = await crypto.subtle.digest('SHA-256', buffer);
  const hashArray = Array.from(new Uint8Array(hashBuffer));
  return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
}

// Usage:
const input = document.querySelector('input[type=file]');
input.addEventListener('change', async () => {
  const hash = await hashFile(input.files[0]);
  console.log('SHA-256:', hash);
});

Node.js (crypto module)

import { createHash } from 'crypto';

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

// String:
sha256('hello');
// '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824'

// Buffer:
sha256(Buffer.from('hello'));

// File:
import { readFileSync } from 'fs';
sha256(readFileSync('./document.pdf'));

// Stream:
import { createHash } from 'crypto';
import { createReadStream } from 'fs';

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

Python

import hashlib

# String:
hashlib.sha256(b'hello').hexdigest()
# '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824'

# With encoding:
hashlib.sha256('hello'.encode('utf-8')).hexdigest()

# File:
def sha256_file(path: str) -> str:
    h = hashlib.sha256()
    with open(path, 'rb') as f:
        while chunk := f.read(65536):  # 64KB chunks
            h.update(chunk)
    return h.hexdigest()

# Bytes:
data = b'\x00\x01\x02\x03'
hashlib.sha256(data).hexdigest()

Common use cases

Data integrity verification

// On upload: store the hash
const file = request.file;
const hash = createHash('sha256').update(file.buffer).digest('hex');

await db.save({ filename: file.originalname, hash, size: file.size });

// On download: verify integrity
const downloadedContent = readFileSync(downloadedPath);
const downloadedHash = createHash('sha256').update(downloadedContent).digest('hex');

if (downloadedHash !== storedHash) {
  throw new Error('File integrity check failed');
}

Content-addressable storage

// Use hash as filename — identical files share storage:
async function storeFile(content) {
  const hash = await sha256(content);
  const path = `./storage/${hash}`;
  
  if (!existsSync(path)) {
    writeFileSync(path, content);
  }
  
  return hash;  // reference by hash
}

API request signing

// Sign API request body:
function signRequest(body, secret) {
  return createHmac('sha256', secret)
    .update(JSON.stringify(body))
    .digest('hex');
}

// Verify on server:
function verifyRequest(body, signature, secret) {
  const expected = signRequest(body, secret);
  return crypto.timingSafeEqual(
    Buffer.from(signature, 'hex'),
    Buffer.from(expected, 'hex')
  );
}

SHA-256 vs other algorithms

AlgorithmOutputSpeedSecurity
MD5128 bits / 32 hexFastestBroken (don’t use for security)
SHA-1160 bits / 40 hexFastDeprecated (weak)
SHA-256256 bits / 64 hexMediumStrong
SHA-512512 bits / 128 hexSlowerStronger
SHA-3-256256 bits / 64 hexSimilarDifferent algorithm

SHA-256 is the best choice for most applications. Use SHA-512 where you need extra margin. Never use MD5 or SHA-1 for security purposes.


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 Encoding & Crypto pillar.