Skip to content

Instantly share code, notes, and snippets.

@marchon
Forked from Nikolaj-K/bit_level_SHA256.py
Created July 13, 2021 05:52
Show Gist options
  • Save marchon/05bd483232ff2d53dfe3ac2acf8af859 to your computer and use it in GitHub Desktop.
Save marchon/05bd483232ff2d53dfe3ac2acf8af859 to your computer and use it in GitHub Desktop.
A python script to perform sha2 in terms of if-statements and for-loops.
"""
Bit level SHA2.
Script to perform sha2 in terms of if-statements and for-loops. This runs 1 batch iteration
(i.e. about 50 bytes max input, but should be easy to extend to any size.)
No warranty.
Explanation video:
https://youtu.be/UziK-Hqzwi4
2019
Nikolaj Kuntner
"""
################################################## online hashing tool
### https://passwordsgenerator.net/sha256-hash-generator
HELLO_HASH = '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824' ## hash of "hello"
HELLP_HASH = 'fdd7585e08c4e2afd71dcabdb4636c89d557a3f42db9e2040c8bbd1708aa4ce7' ## hash of "hellp"
## ouptut is base 16=2**4 and has 64 chars or 64 * 4 = 256 bits
def num2arr(n):
bs = []
while n > 1:
bs = [n % 2] + bs ## [remaider] + [accumulation]
n = n // 2 ## integer division, i.e. quotient without remainder
return [1] + bs if n else bs
################################################ bit functions
F = 'some value' ## respresents False, 0, fNumber
T = 'a different value' ## respresents True, 1, tNumber
def TRUE(x): return x==T
def IF(x, a, b): return a if TRUE(x) else b
## return a if x else b
## return x * a + (1-x) * b
## return 'some polynomials of x, a, b with coefficients being simple functions of nF and nT'
def NOT(x): return IF(x, F, T)
def AND(x, y): return IF(x, y, F)
def XOR(x, y): return IF(x, NOT(y), y)
def MAJ(x, y, z): return IF(x, IF(y, T, z), IF(y, z, F))
def XORXOR(x, y, z): return XOR(x, XOR(y, z))
#IF(x, IF(y, z, NOT(z)), IF(y, NOT(z), z))
## return x+y+z mod 2
## return XOR(x, XOR(y, z))
################################################ bit array functions
####################### component-wise functions
def if_(x, y, z): return [IF(xi, yi, zi) for xi, yi, zi in zip(x, y, z)]
def and_(x, y): return [AND(xi, yi) for xi, yi in zip(x, y)]
def xor(x, y): return [XOR(xi, yi) for xi, yi in zip(x, y)]
def maj(x, y, z): return [MAJ(xi, yi, zi) for xi, yi, zi in zip(x, y, z)]
def xorxor(x, y, z): return [XORXOR(xi, yi, zi) for xi, yi, zi in zip(x, y, z)]
####################### addition
N = 32
def add(x, y): ## binary addition of N bit numbers (automatically mod 2**N)
res = list(range(N))
ci = F ## carry bit
for i in range(N-1, -1, -1):
res[i] = XORXOR(x[i], y[i], ci)
ci = MAJ(x[i], y[i], ci)
return res
####################### utility functions
def rotr(x, n): return x[-n:] + x[:-n]
def cut(x, n): return n * [F] + x[:(len(x) - n)]
################################################## "random" numbers used in SHA256
K = [ ## 64 * 32 = 2048 bits (256 bytes)
[F,T,F,F,F,F,T,F,T,F,F,F,T,F,T,F,F,F,T,F,T,T,T,T,T,F,F,T,T,F,F,F], ## 32 bits (4 bytes)
[F,T,T,T,F,F,F,T,F,F,T,T,F,T,T,T,F,T,F,F,F,T,F,F,T,F,F,T,F,F,F,T],
[T,F,T,T,F,T,F,T,T,T,F,F,F,F,F,F,T,T,T,T,T,F,T,T,T,T,F,F,T,T,T,T],
[T,T,T,F,T,F,F,T,T,F,T,T,F,T,F,T,T,T,F,T,T,F,T,T,T,F,T,F,F,T,F,T],
[F,F,T,T,T,F,F,T,F,T,F,T,F,T,T,F,T,T,F,F,F,F,T,F,F,T,F,T,T,F,T,T],
[F,T,F,T,T,F,F,T,T,T,T,T,F,F,F,T,F,F,F,T,F,F,F,T,T,T,T,T,F,F,F,T],
[T,F,F,T,F,F,T,F,F,F,T,T,T,T,T,T,T,F,F,F,F,F,T,F,T,F,T,F,F,T,F,F],
[T,F,T,F,T,F,T,T,F,F,F,T,T,T,F,F,F,T,F,T,T,T,T,F,T,T,F,T,F,T,F,T],
[T,T,F,T,T,F,F,F,F,F,F,F,F,T,T,T,T,F,T,F,T,F,T,F,T,F,F,T,T,F,F,F],
[F,F,F,T,F,F,T,F,T,F,F,F,F,F,T,T,F,T,F,T,T,F,T,T,F,F,F,F,F,F,F,T],
[F,F,T,F,F,T,F,F,F,F,T,T,F,F,F,T,T,F,F,F,F,T,F,T,T,F,T,T,T,T,T,F],
[F,T,F,T,F,T,F,T,F,F,F,F,T,T,F,F,F,T,T,T,T,T,F,T,T,T,F,F,F,F,T,T],
[F,T,T,T,F,F,T,F,T,F,T,T,T,T,T,F,F,T,F,T,T,T,F,T,F,T,T,T,F,T,F,F],
[T,F,F,F,F,F,F,F,T,T,F,T,T,T,T,F,T,F,T,T,F,F,F,T,T,T,T,T,T,T,T,F],
[T,F,F,T,T,F,T,T,T,T,F,T,T,T,F,F,F,F,F,F,F,T,T,F,T,F,T,F,F,T,T,T],
[T,T,F,F,F,F,F,T,T,F,F,T,T,F,T,T,T,T,T,T,F,F,F,T,F,T,T,T,F,T,F,F],
[T,T,T,F,F,T,F,F,T,F,F,T,T,F,T,T,F,T,T,F,T,F,F,T,T,T,F,F,F,F,F,T],
[T,T,T,F,T,T,T,T,T,F,T,T,T,T,T,F,F,T,F,F,F,T,T,T,T,F,F,F,F,T,T,F],
[F,F,F,F,T,T,T,T,T,T,F,F,F,F,F,T,T,F,F,T,T,T,F,T,T,T,F,F,F,T,T,F],
[F,F,T,F,F,T,F,F,F,F,F,F,T,T,F,F,T,F,T,F,F,F,F,T,T,T,F,F,T,T,F,F],
[F,F,T,F,T,T,F,T,T,T,T,F,T,F,F,T,F,F,T,F,T,T,F,F,F,T,T,F,T,T,T,T],
[F,T,F,F,T,F,T,F,F,T,T,T,F,T,F,F,T,F,F,F,F,T,F,F,T,F,T,F,T,F,T,F],
[F,T,F,T,T,T,F,F,T,F,T,T,F,F,F,F,T,F,T,F,T,F,F,T,T,T,F,T,T,T,F,F],
[F,T,T,T,F,T,T,F,T,T,T,T,T,F,F,T,T,F,F,F,T,F,F,F,T,T,F,T,T,F,T,F],
[T,F,F,T,T,F,F,F,F,F,T,T,T,T,T,F,F,T,F,T,F,F,F,T,F,T,F,T,F,F,T,F],
[T,F,T,F,T,F,F,F,F,F,T,T,F,F,F,T,T,T,F,F,F,T,T,F,F,T,T,F,T,T,F,T],
[T,F,T,T,F,F,F,F,F,F,F,F,F,F,T,T,F,F,T,F,F,T,T,T,T,T,F,F,T,F,F,F],
[T,F,T,T,T,T,T,T,F,T,F,T,T,F,F,T,F,T,T,T,T,T,T,T,T,T,F,F,F,T,T,T],
[T,T,F,F,F,T,T,F,T,T,T,F,F,F,F,F,F,F,F,F,T,F,T,T,T,T,T,T,F,F,T,T],
[T,T,F,T,F,T,F,T,T,F,T,F,F,T,T,T,T,F,F,T,F,F,F,T,F,T,F,F,F,T,T,T],
[F,F,F,F,F,T,T,F,T,T,F,F,T,F,T,F,F,T,T,F,F,F,T,T,F,T,F,T,F,F,F,T],
[F,F,F,T,F,T,F,F,F,F,T,F,T,F,F,T,F,F,T,F,T,F,F,T,F,T,T,F,F,T,T,T],
[F,F,T,F,F,T,T,T,T,F,T,T,F,T,T,T,F,F,F,F,T,F,T,F,T,F,F,F,F,T,F,T],
[F,F,T,F,T,T,T,F,F,F,F,T,T,F,T,T,F,F,T,F,F,F,F,T,F,F,T,T,T,F,F,F],
[F,T,F,F,T,T,F,T,F,F,T,F,T,T,F,F,F,T,T,F,T,T,F,T,T,T,T,T,T,T,F,F],
[F,T,F,T,F,F,T,T,F,F,T,T,T,F,F,F,F,F,F,F,T,T,F,T,F,F,F,T,F,F,T,T],
[F,T,T,F,F,T,F,T,F,F,F,F,T,F,T,F,F,T,T,T,F,F,T,T,F,T,F,T,F,T,F,F],
[F,T,T,T,F,T,T,F,F,T,T,F,T,F,T,F,F,F,F,F,T,F,T,F,T,F,T,T,T,F,T,T],
[T,F,F,F,F,F,F,T,T,T,F,F,F,F,T,F,T,T,F,F,T,F,F,T,F,F,T,F,T,T,T,F],
[T,F,F,T,F,F,T,F,F,T,T,T,F,F,T,F,F,F,T,F,T,T,F,F,T,F,F,F,F,T,F,T],
[T,F,T,F,F,F,T,F,T,F,T,T,T,T,T,T,T,T,T,F,T,F,F,F,T,F,T,F,F,F,F,T],
[T,F,T,F,T,F,F,F,F,F,F,T,T,F,T,F,F,T,T,F,F,T,T,F,F,T,F,F,T,F,T,T],
[T,T,F,F,F,F,T,F,F,T,F,F,T,F,T,T,T,F,F,F,T,F,T,T,F,T,T,T,F,F,F,F],
[T,T,F,F,F,T,T,T,F,T,T,F,T,T,F,F,F,T,F,T,F,F,F,T,T,F,T,F,F,F,T,T],
[T,T,F,T,F,F,F,T,T,F,F,T,F,F,T,F,T,T,T,F,T,F,F,F,F,F,F,T,T,F,F,T],
[T,T,F,T,F,T,T,F,T,F,F,T,T,F,F,T,F,F,F,F,F,T,T,F,F,F,T,F,F,T,F,F],
[T,T,T,T,F,T,F,F,F,F,F,F,T,T,T,F,F,F,T,T,F,T,F,T,T,F,F,F,F,T,F,T],
[F,F,F,T,F,F,F,F,F,T,T,F,T,F,T,F,T,F,T,F,F,F,F,F,F,T,T,T,F,F,F,F],
[F,F,F,T,T,F,F,T,T,F,T,F,F,T,F,F,T,T,F,F,F,F,F,T,F,F,F,T,F,T,T,F],
[F,F,F,T,T,T,T,F,F,F,T,T,F,T,T,T,F,T,T,F,T,T,F,F,F,F,F,F,T,F,F,F],
[F,F,T,F,F,T,T,T,F,T,F,F,T,F,F,F,F,T,T,T,F,T,T,T,F,T,F,F,T,T,F,F],
[F,F,T,T,F,T,F,F,T,F,T,T,F,F,F,F,T,F,T,T,T,T,F,F,T,F,T,T,F,T,F,T],
[F,F,T,T,T,F,F,T,F,F,F,T,T,T,F,F,F,F,F,F,T,T,F,F,T,F,T,T,F,F,T,T],
[F,T,F,F,T,T,T,F,T,T,F,T,T,F,F,F,T,F,T,F,T,F,T,F,F,T,F,F,T,F,T,F],
[F,T,F,T,T,F,T,T,T,F,F,T,T,T,F,F,T,T,F,F,T,F,T,F,F,T,F,F,T,T,T,T],
[F,T,T,F,T,F,F,F,F,F,T,F,T,T,T,F,F,T,T,F,T,T,T,T,T,T,T,T,F,F,T,T],
[F,T,T,T,F,T,F,F,T,F,F,F,T,T,T,T,T,F,F,F,F,F,T,F,T,T,T,F,T,T,T,F],
[F,T,T,T,T,F,F,F,T,F,T,F,F,T,F,T,F,T,T,F,F,F,T,T,F,T,T,F,T,T,T,T],
[T,F,F,F,F,T,F,F,T,T,F,F,T,F,F,F,F,T,T,T,T,F,F,F,F,F,F,T,F,T,F,F],
[T,F,F,F,T,T,F,F,T,T,F,F,F,T,T,T,F,F,F,F,F,F,T,F,F,F,F,F,T,F,F,F],
[T,F,F,T,F,F,F,F,T,F,T,T,T,T,T,F,T,T,T,T,T,T,T,T,T,T,T,T,T,F,T,F],
[T,F,T,F,F,T,F,F,F,T,F,T,F,F,F,F,F,T,T,F,T,T,F,F,T,T,T,F,T,F,T,T],
[T,F,T,T,T,T,T,F,T,T,T,T,T,F,F,T,T,F,T,F,F,F,T,T,T,T,T,T,F,T,T,T],
[T,T,F,F,F,T,T,F,F,T,T,T,F,F,F,T,F,T,T,T,T,F,F,F,T,T,T,T,F,F,T,F]
]
H = [ ## 64 * 32 = 256 bits (32 bytes), like the hash output (e.g. HELLO_HASH)
[F,T,T,F,T,F,T,F,F,F,F,F,T,F,F,T,T,T,T,F,F,T,T,F,F,T,T,F,F,T,T,T],
[T,F,T,T,T,F,T,T,F,T,T,F,F,T,T,T,T,F,T,F,T,T,T,F,T,F,F,F,F,T,F,T],
[F,F,T,T,T,T,F,F,F,T,T,F,T,T,T,F,T,T,T,T,F,F,T,T,F,T,T,T,F,F,T,F],
[T,F,T,F,F,T,F,T,F,T,F,F,T,T,T,T,T,T,T,T,F,T,F,T,F,F,T,T,T,F,T,F],
[F,T,F,T,F,F,F,T,F,F,F,F,T,T,T,F,F,T,F,T,F,F,T,F,F,T,T,T,T,T,T,T],
[T,F,F,T,T,F,T,T,F,F,F,F,F,T,F,T,F,T,T,F,T,F,F,F,T,F,F,F,T,T,F,F],
[F,F,F,T,T,T,T,T,T,F,F,F,F,F,T,T,T,T,F,T,T,F,F,T,T,F,T,F,T,F,T,T],
[F,T,F,T,T,F,T,T,T,T,T,F,F,F,F,F,T,T,F,F,T,T,F,T,F,F,F,T,T,F,F,T]
]
################################################## start SHA-256
def sha(w):
for i in range(16, 64): ## fill rest of w
w[i] = add(add(add(
w[i-16],
w[i- 7]),
xorxor(rotr(w[i-15], 7), rotr(w[i-15], 18), cut(w[i-15], 3))),
xorxor(rotr(w[i-2] , 17), rotr(w[i-2] , 19), cut(w[i-2] , 10)))
a, b, c, d, e, f, g, h = H
for j in range(64): ## digest
temp1 = add(add(add(add(
w[j],
h),
if_(e, f, g)),
xorxor(rotr(e, 6), rotr(e, 11), rotr(e, 25))),
K[j])
tempd = add(
maj(a, b, c),
xorxor(rotr(a, 2), rotr(a, 13), rotr(a, 22)))
h = g
g = f
f = e
e = add(
temp1,
d)
d = c
c = b
b = a
a = add(
temp1,
tempd)
return [add(x, y) for x, y in zip([a, b, c, d, e, f, g, h], H)]
################################################## utility funcitons for base conversion
def arrsToHex(arrs):
def arr2dec(arr):
return sum([b * 2**k for k, b in enumerate(arr[::-1])])
def arr2hex(arr):
return '{:x}'.format(arr2dec(arr))
return (arr2hex(arr) for arr in arrs)
def translateArrBits(arr, source, target):
for i, row in enumerate(arr):
for j, elem in enumerate(row):
if arr[i][j]==source:
arr[i][j] = target
################################################## initialize a message on w, run and print!
w = [32*[F] for _ in range(64)]
w[15] = [F,F,F,F,F,F,F,F, F,F,F,F,F,F,F,F, F,F,F,F,F,F,F,F, F,F,T,F,T,F,F,F] ## message length
w[0] = [F,T,T,F,T,F,F,F, F,T,T,F,F,T,F,T, F,T,T,F,T,T,F,F, F,T,T,F,T,T,F,F] ## "hell"
w[1] = [F,T,T,F,T,T,T,T, T,F,F,F,F,F,F,F, F,F,F,F,F,F,F,F, F,F,F,F,F,F,F,F] ## "o" and message end
#w[1] = [F,T,T,T,F,F,F,F, T,F,F,F,F,F,F,F, F,F,F,F,F,F,F,F, F,F,F,F,F,F,F,F] ## "p" and message end
digestBool = sha(w) # run!
translateArrBits(digestBool, F, 0)
translateArrBits(digestBool, T, 1)
for row in digestBool:
print("".join(map(str, row)))
for row in arrsToHex(digestBool):
print(row)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment