Following the wiki code: we have a message block of $512$ bits (or $64$ bytes) that you're dealing with. We see those as $16$ words of $32$ bits each.
These are W[0],..., W[15]
, in order.
Then e.g. W[16] = W[0] ^ f_1(W[1]) ^ W[9] ^ f_2(W[14])
where f_1(w)
transforms the word w
into ror(w,7)^ror(w,18)^(w>>3)
where ror
is implemented as in the link in my comment above, and f_2(w) = ror(w,17)^ror(w,19)^(w>>10)
Then W[17]
is the same with all indices moved up 1, etc. So : W[17] = W[1] ^ f_1(W[2]) ^ W[10] ^ f_2(W[15])
and next W[18] = W[2] ^ f_1(W[3]) ^ W[11] ^ f_2(W[16])
, etc.
So W[16],....., W[63]
are all computed based on the previously computed W[i]
in a way that mixes up the bits, and we get a 4-fold expansion of the message block words that are used as starting values.
Conceptually, what's happening in this hash function (and others like this) is that we're using a block cipher $E(m,k)$ (often called the "transform" function in code implementations) with block size (for $m$) of 256 bits (8 words) and keysize (for $k$) of 512 bits. To handle a message with blocks $m_0,m_1, m_2, \ldots, m_N$
(where the last block(s) have padding and a total length) is to define $h_0$ to be a fixed block, and then computing $h_1 = E(h_0,m_0) + h_0$ (message block addition happens per word, modulo $2^{32}$), $h_2 = E(h_1, m_1) + h_1$, etc. up to $h_{N+1} = E(h_N, m_N) + h_N$ and then $h_{N+1}$ is the final hash. Adding the input to the cipher output makes the result irreversible (which is what we want with hash functions).
The $E$ function uses a message block as key, and the computation of the $W$ words is its key schedule: it creates round keys for the block cipher (which has 64 rounds for SHA-256 and uses one $W$ word per round, this is the last big loop in the Wikipedia pseudo code).
I think the pseudo code can quite well be translated into pure Python, using a good ror
function, of course.
It would help if you can tell where your code no longer gives the right result as compared to the spread sheet links. And it's more of a stackoverflow question if it's about code itself, IMHO.
hashlib.sha256
, so if you just need to use sha256 on something then you're going about it the long/wrong way. $\endgroup$