SHA-256 From Scratch

hard · cryptography, hashing, bitwise

SHA-256 From Scratch

Implement SHA-256 without using any crypto libraries.

You must handle:

  • Merkle-Damgard padding
  • Message schedule
  • Compression rounds
  • Final digest formatting

Function signature

func SHA256(msg []byte) [32]byte

SHA-256 summary

  • Block size: 512 bits (64 bytes)
  • Output size: 256 bits (32 bytes)
  • Word size: 32 bits

Padding

Given a message of length L bytes:

  1. Append 0x80.
  2. Append 0x00 bytes until length is 56 mod 64.
  3. Append the original length in bits as a 64-bit big-endian integer.

Message schedule

For each 64-byte block, parse 16 big-endian words W[0..15]. Then for i=16..63:

W[i] = s1(W[i-2]) + W[i-7] + s0(W[i-15]) + W[i-16]

where:

s0(x) = ROTR7(x)  ^ ROTR18(x) ^ (x >> 3)
s1(x) = ROTR17(x) ^ ROTR19(x) ^ (x >> 10)

Compression (64 rounds)

Initialize a..h from the IV. For i=0..63:

T1 = h + S1(e) + Ch(e,f,g) + K[i] + W[i]
T2 = S0(a) + Maj(a,b,c)

h = g
f = e
 e = d + T1
 d = c
 c = b
 b = a
 a = T1 + T2

where:

Ch(x,y,z)  = (x & y) ^ (^x & z)
Maj(x,y,z) = (x & y) ^ (x & z) ^ (y & z)
S0(x) = ROTR2(x) ^ ROTR13(x) ^ ROTR22(x)
S1(x) = ROTR6(x) ^ ROTR11(x) ^ ROTR25(x)

Finally, add a..h back into the hash state.

Notes

  • Use big-endian for word parsing and output.
  • All arithmetic is 32-bit with wraparound.
  • This is a learning exercise. Do not ship your own SHA-256 implementation.
Run tests to see results
No issues detected