-
-
Save pornin/46a1701d2c2e377cf4ffe9ecb6c94b32 to your computer and use it in GitHub Desktop.
Perfunctory implementation of the SHA-256 block processing function, for testing purposes only
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class SHA256: | |
K = [ | |
0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, | |
0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, | |
0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, | |
0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, | |
0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, | |
0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, | |
0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, | |
0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, | |
0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, | |
0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, | |
0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, | |
0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, | |
0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, | |
0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, | |
0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, | |
0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2 | |
] | |
IV_standard = bytes.fromhex('6a09e667bb67ae853c6ef372a54ff53a510e527f9b05688c1f83d9ab5be0cd19') | |
@classmethod | |
def ROTR(cls, n, x): | |
return (x >> n) | ((x << (32 - n)) & 0xFFFFFFFF) | |
@classmethod | |
def ROTL(cls, n, x): | |
return cls.ROTR(32 - n, x) | |
@classmethod | |
def Ch(cls, x, y, z): | |
return (x & y) ^ (~x & z) | |
@classmethod | |
def Maj(cls, x, y, z): | |
return (x & y) ^ (x & z) ^ (y & z) | |
@classmethod | |
def BigSigma_0(cls, x): | |
return cls.ROTR(2, x) ^ cls.ROTR(13, x) ^ cls.ROTR(22, x) | |
@classmethod | |
def BigSigma_1(cls, x): | |
return cls.ROTR(6, x) ^ cls.ROTR(11, x) ^ cls.ROTR(25, x) | |
@classmethod | |
def LittleSigma_0(cls, x): | |
return cls.ROTR(7, x) ^ cls.ROTR(18, x) ^ (x >> 3) | |
@classmethod | |
def LittleSigma_1(cls, x): | |
return cls.ROTR(17, x) ^ cls.ROTR(19, x) ^ (x >> 10) | |
@classmethod | |
def ProcessBlock(cls, initial_value, message_block): | |
initial_value = bytes(initial_value) | |
message_block = bytes(message_block) | |
assert len(initial_value) == 32 | |
assert len(message_block) == 64 | |
H = [] | |
for i in range(0, 8): | |
H.append(int.from_bytes(initial_value[4*i : 4*i+4], byteorder='big')) | |
W = [] | |
for i in range(0, 16): | |
W.append(int.from_bytes(message_block[4*i : 4*i+4], byteorder='big')) | |
for i in range(16, 64): | |
W.append((cls.LittleSigma_1(W[i - 2]) + W[i - 7] + cls.LittleSigma_0(W[i - 15]) + W[i - 16]) & 0xFFFFFFFF) | |
a = H[0] | |
b = H[1] | |
c = H[2] | |
d = H[3] | |
e = H[4] | |
f = H[5] | |
g = H[6] | |
h = H[7] | |
for i in range(0, 64): | |
T1 = (h + cls.BigSigma_1(e) + cls.Ch(e, f, g) + cls.K[i] + W[i]) & 0xFFFFFFFF | |
T2 = (cls.BigSigma_0(a) + cls.Maj(a, b, c)) & 0xFFFFFFFF | |
h = g | |
g = f | |
f = e | |
e = (d + T1) & 0xFFFFFFFF | |
d = c | |
c = b | |
b = a | |
a = (T1 + T2) & 0xFFFFFFFF | |
H[0] = (H[0] + a) & 0xFFFFFFFF | |
H[1] = (H[1] + b) & 0xFFFFFFFF | |
H[2] = (H[2] + c) & 0xFFFFFFFF | |
H[3] = (H[3] + d) & 0xFFFFFFFF | |
H[4] = (H[4] + e) & 0xFFFFFFFF | |
H[5] = (H[5] + f) & 0xFFFFFFFF | |
H[6] = (H[6] + g) & 0xFFFFFFFF | |
H[7] = (H[7] + h) & 0xFFFFFFFF | |
res = b'' | |
for i in range(0, 8): | |
res += H[i].to_bytes(4, byteorder='big') | |
return res | |
# ========================================================================= | |
# Example: using the standard IV value (from FIPS 180-4, section 5.3.3) | |
# and the given message block (random 55-byte string, with padding applied), | |
# the output should be: | |
# d283164a342a43160f18c4f384429d2ab25cdbb686853b7f620fe60a0476593a | |
IV = bytes.fromhex('6a09e667bb67ae853c6ef372a54ff53a510e527f9b05688c1f83d9ab5be0cd19') | |
Mb = bytes.fromhex('f579a8ca3762fb77c02342f872114eb54752842a280f63f1b644d30e4e0710b347171d9031f56caf2f33872c9690365b080e475527b1ac8000000000000001B8') | |
print(SHA256.ProcessBlock(IV, Mb).hex()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment