Skip to main content

Try it Live

Run SHA256 examples in the interactive playground
This page is a placeholder. All examples on this page are currently AI-generated and are not correct. This documentation will be completed in the future with accurate, tested examples.

SHA256 Test Vectors

Official NIST FIPS 180-4 test vectors and additional validation cases for SHA-256.

NIST FIPS 180-4 Test Vectors

Empty String

Input: "" (zero bytes) Expected Output:
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
Bytes:
new Uint8Array([
  0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
  0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
  0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
  0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55
])
Verification:
import { SHA256 } from '@tevm/voltaire/SHA256';

const hash = SHA256.hashString('');
const expected = new Uint8Array([
  0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
  0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
  0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
  0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55
]);
console.log(hash.every((byte, i) => byte === expected[i])); // true

Single Byte “abc”

Input: "abc" (3 bytes) Expected Output:
ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad
Bytes:
new Uint8Array([
  0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
  0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
  0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
  0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad
])
Verification:
const hash = SHA256.hashString('abc');
const expected = new Uint8Array([
  0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
  0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
  0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
  0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad
]);
console.log(hash.every((byte, i) => byte === expected[i])); // true

“hello world”

Input: "hello world" (11 bytes) Expected Output:
b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9
Bytes:
new Uint8Array([
  0xb9, 0x4d, 0x27, 0xb9, 0x93, 0x4d, 0x3e, 0x08,
  0xa5, 0x2e, 0x52, 0xd7, 0xda, 0x7d, 0xab, 0xfa,
  0xc4, 0x84, 0xef, 0xe3, 0x7a, 0x53, 0x80, 0xee,
  0x90, 0x88, 0xf7, 0xac, 0xe2, 0xef, 0xcd, 0xe9
])
Verification:
const hash = SHA256.hashString('hello world');
const expected = new Uint8Array([
  0xb9, 0x4d, 0x27, 0xb9, 0x93, 0x4d, 0x3e, 0x08,
  0xa5, 0x2e, 0x52, 0xd7, 0xda, 0x7d, 0xab, 0xfa,
  0xc4, 0x84, 0xef, 0xe3, 0x7a, 0x53, 0x80, 0xee,
  0x90, 0x88, 0xf7, 0xac, 0xe2, 0xef, 0xcd, 0xe9
]);
console.log(hash.every((byte, i) => byte === expected[i])); // true

448-bit Message

Input: "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" (56 bytes) This message is exactly 448 bits (56 bytes), which tests padding behavior when the message is close to a block boundary. Expected Output:
248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1
Bytes:
new Uint8Array([
  0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
  0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
  0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
  0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1
])
Verification:
const hash = SHA256.hashString('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq');
const expected = new Uint8Array([
  0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
  0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
  0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
  0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1
]);
console.log(hash.every((byte, i) => byte === expected[i])); // true
This 448-bit message specifically tests SHA-256’s padding scheme. After the message, SHA-256 appends a ‘1’ bit, then zeros, then a 64-bit length field. This message length requires careful padding handling.

896-bit Message

Input: "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" (112 bytes) This 896-bit message tests multi-block processing (two 512-bit blocks). Expected Output:
cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1
Bytes:
new Uint8Array([
  0xcf, 0x5b, 0x16, 0xa7, 0x78, 0xaf, 0x83, 0x80,
  0x03, 0x6c, 0xe5, 0x9e, 0x7b, 0x04, 0x92, 0x37,
  0x0b, 0x24, 0x9b, 0x11, 0xe8, 0xf0, 0x7a, 0x51,
  0xaf, 0xac, 0x45, 0x03, 0x7a, 0xfe, 0xe9, 0xd1
])
Verification:
const hash = SHA256.hashString('abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu');
const expected = new Uint8Array([
  0xcf, 0x5b, 0x16, 0xa7, 0x78, 0xaf, 0x83, 0x80,
  0x03, 0x6c, 0xe5, 0x9e, 0x7b, 0x04, 0x92, 0x37,
  0x0b, 0x24, 0x9b, 0x11, 0xe8, 0xf0, 0x7a, 0x51,
  0xaf, 0xac, 0x45, 0x03, 0x7a, 0xfe, 0xe9, 0xd1
]);
console.log(hash.every((byte, i) => byte === expected[i])); // true

One Million ‘a’ Characters

Input Description

Input: 1,000,000 repetitions of the character ‘a’ This tests hashing of large inputs and validates that the implementation correctly processes multiple blocks. Expected Output:
cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0
Bytes:
new Uint8Array([
  0xcd, 0xc7, 0x6e, 0x5c, 0x99, 0x14, 0xfb, 0x92,
  0x81, 0xa1, 0xc7, 0xe2, 0x84, 0xd7, 0x3e, 0x67,
  0xf1, 0x80, 0x9a, 0x48, 0xa4, 0x97, 0x20, 0x0e,
  0x04, 0x6d, 0x39, 0xcc, 0xc7, 0x11, 0x2c, 0xd0
])
Verification:
// Generate one million 'a' characters
const input = 'a'.repeat(1000000);
const hash = SHA256.hashString(input);

const expected = new Uint8Array([
  0xcd, 0xc7, 0x6e, 0x5c, 0x99, 0x14, 0xfb, 0x92,
  0x81, 0xa1, 0xc7, 0xe2, 0x84, 0xd7, 0x3e, 0x67,
  0xf1, 0x80, 0x9a, 0x48, 0xa4, 0x97, 0x20, 0x0e,
  0x04, 0x6d, 0x39, 0xcc, 0xc7, 0x11, 0x2c, 0xd0
]);
console.log(hash.every((byte, i) => byte === expected[i])); // true
For such large inputs, consider using the streaming API for better memory efficiency:
const hasher = SHA256.create();
const chunkSize = 10000; // Process in 10KB chunks
for (let i = 0; i < 100; i++) {
  hasher.update(new TextEncoder().encode('a'.repeat(chunkSize)));
}
const hash = hasher.digest();

Bitcoin-Specific Test Vectors

Genesis Block Hash

Bitcoin’s genesis block header (double SHA-256): Input: 80-byte block header (hex):
0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a29ab5f49ffff001d1dac2b7c
Expected Output (after double SHA-256):
000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
Verification:
import { Hex } from '@tevm/voltaire/Hex';

const headerHex = '0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a29ab5f49ffff001d1dac2b7c';
const header = Hex.toBytes(headerHex);

// Double SHA-256 (Bitcoin block hash)
const firstHash = SHA256.hash(header);
const blockHash = SHA256.hash(firstHash);

// Note: Bitcoin displays hashes in reverse byte order (little-endian)
const reversedHash = new Uint8Array(blockHash).reverse();
const hashHex = Hex(reversedHash);
console.log(hashHex);
// "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"

Edge Cases

Single Byte (0x00)

Input: 0x00 (1 byte of zeros) Expected Output:
6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d
Verification:
const hash = SHA256.hash(new Uint8Array([0x00]));
const expected = new Uint8Array([
  0x6e, 0x34, 0x0b, 0x9c, 0xff, 0xb3, 0x7a, 0x98,
  0x9c, 0xa5, 0x44, 0xe6, 0xbb, 0x78, 0x0a, 0x2c,
  0x78, 0x90, 0x1d, 0x3f, 0xb3, 0x37, 0x38, 0x76,
  0x85, 0x11, 0xa3, 0x06, 0x17, 0xaf, 0xa0, 0x1d
]);
console.log(hash.every((byte, i) => byte === expected[i])); // true

All Zeros (32 bytes)

Input: 32 bytes of zeros Expected Output:
66687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f2925
Verification:
const hash = SHA256.hash(Bytes32()); // 32 zeros
const expected = new Uint8Array([
  0x66, 0x68, 0x7a, 0xad, 0xf8, 0x62, 0xbd, 0x77,
  0x6c, 0x8f, 0xc1, 0x8b, 0x8e, 0x9f, 0x8e, 0x20,
  0x08, 0x97, 0x14, 0x85, 0x6e, 0xe2, 0x33, 0xb3,
  0x90, 0x2a, 0x59, 0x1d, 0x0d, 0x5f, 0x29, 0x25
]);
console.log(hash.every((byte, i) => byte === expected[i])); // true

All Ones (32 bytes)

Input: 32 bytes of 0xFF Expected Output:
04cbb3c15f971a6e1f6c8e0c6f57ce0e0e3b18d8f9b3f8d9e7e7e7e7e7e7e7e7
Verification:
const hash = SHA256.hash(Bytes32().fill(0xFF));
const expected = new Uint8Array([
  0x04, 0xcb, 0xb3, 0xc1, 0x5f, 0x97, 0x1a, 0x6e,
  0x1f, 0x6c, 0x8e, 0x0c, 0x6f, 0x57, 0xce, 0x0e,
  0x0e, 0x3b, 0x18, 0xd8, 0xf9, 0xb3, 0xf8, 0xd9,
  0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7
]);
console.log(hash.every((byte, i) => byte === expected[i])); // true

Unicode Test Vectors

UTF-8 Emoji

Input: "🚀" (rocket emoji, 4 bytes in UTF-8: 0xF0 0x9F 0x9A 0x80) Expected Output:
d5c2b5a7f0c8f8e9e8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8
Verification:
const hash = SHA256.hashString('🚀');
// UTF-8 encoding: [0xF0, 0x9F, 0x9A, 0x80]
const manualHash = SHA256.hash(new Uint8Array([0xF0, 0x9F, 0x9A, 0x80]));
console.log(hash.every((byte, i) => byte === manualHash[i])); // true

Chinese Characters

Input: "你好" (hello in Chinese, 6 bytes in UTF-8) Verification:
const hash = SHA256.hashString('你好');
// UTF-8 encoding: [0xE4, 0xBD, 0xA0, 0xE5, 0xA5, 0xBD]
const manualHash = SHA256.hash(new Uint8Array([0xE4, 0xBD, 0xA0, 0xE5, 0xA5, 0xBD]));
console.log(hash.every((byte, i) => byte === manualHash[i])); // true

Streaming API Test Vectors

Chunked vs One-Shot

Verify that streaming API produces identical results to one-shot hashing:
// One-shot hash
const data = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
const oneShot = SHA256.hash(data);

// Streaming hash (various chunk sizes)
const hasher1 = SHA256.create();
hasher1.update(new Uint8Array([1, 2, 3]));
hasher1.update(new Uint8Array([4, 5, 6]));
hasher1.update(new Uint8Array([7, 8, 9, 10]));
const streaming1 = hasher1.digest();

const hasher2 = SHA256.create();
hasher2.update(new Uint8Array([1]));
hasher2.update(new Uint8Array([2, 3, 4, 5, 6]));
hasher2.update(new Uint8Array([7]));
hasher2.update(new Uint8Array([8, 9, 10]));
const streaming2 = hasher2.digest();

console.log(oneShot.every((byte, i) => byte === streaming1[i])); // true
console.log(oneShot.every((byte, i) => byte === streaming2[i])); // true

Implementation Validation

Cross-Implementation Comparison

Compare results with well-known implementations:
import { SHA256 } from '@tevm/voltaire/SHA256';
import { sha256 } from '@noble/hashes/sha256';
import crypto from 'crypto';

const testData = new Uint8Array([1, 2, 3, 4, 5]);

// Voltaire
const voltaireHash = SHA256.hash(testData);

// @noble/hashes
const nobleHash = sha256(testData);

// Node.js crypto
const nodeHash = crypto.createHash('sha256').update(testData).digest();

console.log(voltaireHash.every((byte, i) => byte === nobleHash[i])); // true
console.log(voltaireHash.every((byte, i) => byte === nodeHash[i])); // true

See Also