# SHA-256 Algorithm
First of all, I'd like to share this nice book: https://webspace.science.uu.nl/~tel00101/liter/Books/CrypCont.pdf
## A - Preprocess steps
1 - Padding the message
2 - Parsing the message into message blocks
3 - Setting the initial hash value
### Step 1: Padding the message
- This padding is to ensure that the padded msg is a multiple of 512.
- Append the bit '1' to the end of the message followed by k zero bits
- And then, append 64-bits block to represent the message size
Suppose M contains l bits and k is the smallest positive integer to the equation
$l + 1 + k ≡ 448 mod 512$
example: abc = 8*3=24 bits, so l = 24
We need to find how many zero's
```
a = 01100001
b = 01100010
c = 01100011
```
Following this `l + 1 + k = 448mod512`
We have `512 - 448 = 64`
Then we append 64-bits block to express the number l, that in this example is l=24= 00...011000
So, we have:
**abc 1 00..00 00...011000**
k = 448 zero bits 00..00
where the last 5 bits in the sequence is 24 that represents l
Now, the lenght of the padded message has to be a multiple of 512 bits
### Step 2: Parsing the message into message blocks
The message and its padding must be parsed into N 512-bit blocks. Since the 512 bits of the input block may be expressed as 16 32-bit words, the first 32 bits of message block i are denoted M0_i, the next 32 bits are M1_i ... M15_i.
In other words, each 512 bit block is broken into 16 sub blocks of 32 bit each.
In the example abc, N = 1 and then we have only one 512-bit block.
```1c=
M0 = a b c 1 0000000
M1 = 0000000000..00
.
.
.
M15 = 000.. 011000 (where the final here is l that is 24)
```
### Step 3: Setting the initial hash value
Before hash computation starts, the initial hash value must be set.
The initial hash value consists of 8 32-bit words:
```gcode
H0 = 6a09e667
H1 = bb67ae85
H2 = 3c6ef372
H3 = a54ff53a
H4 = 512e527f
H5 = 9b05688c
H6 = 1f83d9ab
H7 = 5be0cd19
```
These words are results of the first 32-bits of the fractional parts of the square roots of the first eight prime numbers.
## B- Hash Computation
Uses functions and constants.
#### B.1 - Constants:
Its a sequence of the 64 constant 32-bit words. These words represent the first 32-bits of the fractional parts of the cube roots of the first 64 prime numbers.
Each message block, M0 ... M15 is processed in order using the following steps:
In the example abc, N = 1.
#### B.2 - Algorithm to compute 64 32-bits words W:
```c=
for i = 1 to N
Prepare the message schedule (Wt). Let's construct the 64 blocks Wi from M(t)
While 0 <= t <= 63
if t <= 15 Wt = Mt
else
Wt = D1(Wt-2) + Wt-7 + D0(Wt-15) + Wt-16
setWorkingVariables(i)
compression()
computeNewValueOfH(i)
// How compute D0 and D1:
D0 (x) = RotationR7(x) XOR RotationR18(x) XOR ShiftR3(x)
D1 (x) = RotationR17(x) XOR RotationR19(x) XOR ShiftR10(x)
```
#### Remember: x = 32 bit-word
Rotation examples to apply on D0 and D1:
```1c
X = 11000111000111000110010011000001
```
#### Understanding how D0 works:
```1c
D0 (x) = RotationR7(x) XOR RotationR18(x) XOR ShiftR3(x)
```
```1c!
RotationR7(x)
take the 7h bit and shift to the right in a circular way (similar behavior of circular list)
```
The result for X is:
```1c
RotationR7(x) = 10000011100011100011100011001001
```
Similarly, we apply to the remaining rotation operations.
```1c!
ShiftR3(x) is quite simple, just shift without applying circular concept.
ShiftR3(x) = 00011000111000111000110010011000
```
#### XOR Operations
After applying shift and rotation operations, we now, apply XOR operations.
```1c
x = 11000111000111000110010011000001
D0 (x) = RotationR7(x) XOR RotationR18(x) XOR ShiftR3(x)
D0 (x) = 10000011100011100011100011001001
XOR
00011001001100000111000111000111
XOR
00011000111000111000110010011000
D0 (x) = 10000010010111011100010110010110
```
We do the same thing for **D1**. And then we compute W16, W17, W18, ... W63.
#### Variable Initialization
Here, we use those hash values set in **Step 3** during the preprocessing phase to set eight working variables. The function `setWorkingVariables(i)` is called in the algorithm presented in the `pseudocode (line 8)`.
```c=
setWorkingVariables(i)
a = H0^(i-1)
b = H1^(i-1)
c = H2^(i-1)
d = H3^(i-1)
e = H4^(i-1)
f = H5^(i-1)
g = H6^(i-1)
h = H7^(i-1)
```
In our example, we know that $N=1$. So, `setWorkingVariables(i)` function runs just once and we have the following values:
```gcode
a = H0 = 6a09e667
b = H1 = bb67ae85
c = H2 = 3c6ef372
d = H3 = a54ff53a
e = H4 = 512e527f
f = H5 = 9b05688c
g = H6 = 1f83d9ab
h = H7 = 5be0cd19
```
#### Compression
The `compression()` function bellow is called in the `pseudocode (line 9)`.
```c=
compression()
for i=0 to 63
S1 = (e rightrotate 6) xor (e rightrotate 11) xor (e rightrotate 25)
ch = (e and f) xor ((not e) and g)
T1 = h + S1 + ch + k[i] + w[i]
S0 = (a rightrotate 2) xor (a rightrotate 13) xor (a rightrotate 22)
maj = (a and b) xor (a and c) xor (b and c)
T2 := S0 + maj
h = g
g = f
f = e
e = d + T1
d = c
c = b
b = a
a = T1 + T2
```
#### Compute the new value of H_j
```c=
computeNewValueOfH(i)
//In our example, i=N=1, so this code is runned once
h0 = h0 + a
h1 = h1 + b
h2 = h2 + c
h3 = h3 + d
h4 = h4 + e
h5 = h5 + f
h6 = h6 + g
h7 = h7 + h
```
Link shared by Shebin to run some tests: https://sha256algorithm.com/
Link shared by Kris with a step-by-step: https://blog.boot.dev/cryptography/how-sha-2-works-step-by-step-sha-256/