Created
December 13, 2023 11:54
-
-
Save socram8888/45fb35c7cb4e78cbeb60943fad23c615 to your computer and use it in GitHub Desktop.
Pure Python SHA-256 implementation
This file contains 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
# Pure Python SHA-256 implementation | |
# (c) Marcos Del Sol Vives <[email protected]> | |
# License: WTFPL | |
import struct | |
# 32-bit right rotation | |
def rotr32(a, c): | |
return ((a >> c) | (a << (32 - c))) & 0xFFFFFFFF | |
# Round constants | |
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 | |
] | |
def sha256(message): | |
# Pack message length in bits | |
msg_len = struct.pack('>Q', 8 * len(message)) | |
# Append end-of-message | |
message += b'\x80' | |
# Calculate padding. 1 due to end-of-message we'll latter | |
padding_len = (64 - len(message) - len(msg_len)) & 63 | |
# Add padding and original length | |
message += b'\x00' * padding_len + msg_len | |
# Initialize hash value | |
digest = [ | |
0x6a09e667, | |
0xbb67ae85, | |
0x3c6ef372, | |
0xa54ff53a, | |
0x510e527f, | |
0x9b05688c, | |
0x1f83d9ab, | |
0x5be0cd19, | |
] | |
# Process message in 64 byte chunks | |
for chunk in range(0, len(message), 64): | |
chunk = message[chunk : chunk + 64] | |
# Unpack chunk into 32-bit words in big endian | |
w = list(struct.unpack('>' + 'I' * 16, chunk)) | |
# Extend chunk into the remaining 48 words of the message schedule array | |
for i in range(16, 64): | |
s0 = rotr32(w[-15], 7) ^ rotr32(w[-15], 18) ^ (w[-15] >> 3) | |
s1 = rotr32(w[-2], 17) ^ rotr32(w[-2], 19) ^ (w[-2] >> 10) | |
w.append((w[-16] + s0 + w[-7] + s1) & 0xFFFFFFFF) | |
# Initialize working variables to current hash value | |
a, b, c, d, e, f, g, h = digest | |
# Main compression loop | |
for r_w, r_k in zip(w, K): | |
S1 = rotr32(e, 6) ^ rotr32(e, 11) ^ rotr32(e, 25) | |
ch = (e & f) ^ ((e ^ 0xFFFFFFFF) & g) | |
temp1 = (h + S1 + ch + r_k + r_w) | |
S0 = rotr32(a, 2) ^ rotr32(a, 13) ^ rotr32(a, 22) | |
maj = (a & b) ^ (a & c) ^ (b & c) | |
temp2 = (S0 + maj) | |
h = g | |
g = f | |
f = e | |
e = (d + temp1) & 0xFFFFFFFF | |
d = c | |
c = b | |
b = a | |
a = (temp1 + temp2) & 0xFFFFFFFF | |
# Add the result to the current digest | |
digest = [(x + y) & 0xFFFFFFFF for x, y in zip(digest, (a, b, c, d, e, f, g, h))] | |
# Pack the words in big-endian, and return as the digest | |
return struct.pack('>' + 'I' * 8, *digest) | |
if __name__ == '__main__': | |
vectors = [ | |
('e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', b''), | |
('ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad', b'abc'), | |
('cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0', b'a' * 1000000), | |
('248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1', b'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'), | |
('cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1', b'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu'), | |
] | |
for correct, inp in vectors: | |
assert(sha256(inp).hex() == correct) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment