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: 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