how to decode rsa with given p,q and e - python

p: 36595219896620598203466837041441890226020928028223099101100300133334608406956417
q: 30995374714748002222830087470985334838922058265073459880006631044742483128394347
e: 65537
c: 112551517443367600226914124474656800456883252179897098198626860064436836858554837037004323690904898146330897248584664231803632050963580641362896311366999264714
i tried this but didnt work it may contain some errors
def egcd(a,b):
x,y, u,v = 0,1, 1,0
while a != 0:
q, r = b//a, b%a
m, n = x-u*q, y-v*q
b,a, x,y, u,v = a,r, u,v, m,n
gcd = b
return gcd, x, y
def main():
p = 36595219896620598203466837041441890226020928028223099101100300133334608406956417
q = 30995374714748002222830087470985334838922058265073459880006631044742483128394347
e = 65537
ct = 112551517443367600226914124474656800456883252179897098198626860064436836858554837037004323690904898146330897248584664231803632050963580641362896311366999264714
# compute n
n = p * q
# Compute phi(n)
phi = (p - 1) * (q - 1)
# Compute modular inverse of e
gcd, a, b = egcd(e, phi)
d = a
print( "n: " + str(d) );
# Decrypt ciphertext
pt = pow(ct, d, n)
print( "pt: " + str(pt) )
if __name__ == "__main__":
main()

Related

SciPy Optimise minimise error - challenge to solve

How do I solve this error?
TypeError: NumPy boolean subtract, the `-` operator, is not supported, use the bitwise_xor, the `^` operator, or the logical_xor function instead.
I have programmed an optimizing program that must minimize the cost of a wall design. The wall is based on 3 parameters, x, k and m. There are constraints to the sizes of x, k and m as shown. Another constraint is that z (or deflection) must be kept under 100mm. The equation for deflection changes based on a certain t (or time) at which the blast wall is experiencing the blast. If t is below a certain time value which is calculated dependent on, x, k and m the equation is as shown. If t is above the same certain time value, the equation for z changes.
Here is the programming... Please help many thanks :)
import numpy as np
from numpy import linspace
from math import cos
from math import sin
from scipy.optimize import minimize
#Function for minimising
def calcCost(c):
k = c[0]
m = c[1]
x = c[2]
Cost = (900 + 825*k**2 - 1725) + (10*m - 200) + ((2400*x**2)/4)
return Cost
#Objective function
def objective(c):
return calcCost(c)
#Defining Variables
def calck(c):
k = c[0]
k=k
k.resize(12,)
return k
def calcm(c):
m = c[1]
m=m
m.resize(12,)
return m
def calcx(c):
x = c[2]
x=x
x.resize(12,)
return x
def calcz(c):
k = c[0]
x = c[1]
m = c[2]
l = linspace(0,140,141)
for t in l:
if t <= ((20 - 0.12*x**2 + 4.2*x)/1000):
deflection = ((((1000+9*x**2-183*x)*1000)/k)*(1-cos(t*((k/m)**0.5))) + (((1000+9*x**2-183*x)*1000)/k*((20 - 0.12*x**2 + 4.2*x)/1000))*((sin(t*((k/m)**0.5))/((k/m)**0.5))-t))*1000
else:
deflection = ((((1000+9*x**2-183*x)*1000)/(k*((k/m)**0.5)*((20 - 0.12*x**2 + 4.2*x)/1000)))*(sin(((k/m)**0.5)*t))-(sin(((k/m)**0.5)*(t-((20 - 0.12*x**2 + 4.2*x)/1000))))-(((1000+9*x**2-183*x)*1000)/k)*cos(((k/m)**0.5)*t))*1000
deflection.resize(12,)
return deflection
#Constraint functions
def kconstraint1(c):
k = c[0]
return k-(1*10**6) >= 0
def kconstraint2(c):
k = c[0]
return k-(7*10**6) <= 0
def mconstraint1(c):
m = c[0]
return m-200 >= 0
def mconstraint2(c):
m = c[0]
return m-1200 <= 0
def xconstraint1(c):
x = c[0]
return x >= 0
def xconstraint2(c):
x = c[0]
return x <= 10
def zconstraint1(c):
k = c[0]
x = c[1]
m = c[2]
l = linspace(0,140,141)
for t in l:
if t <= ((20 - 0.12*x**2 + 4.2*x)/1000):
deflection = ((((1000+9*x**2-183*x)*1000)/k)*(1-cos(t*((k/m)**0.5))) + (((1000+9*x**2-183*x)*1000)/k*((20 - 0.12*x**2 + 4.2*x)/1000))*((sin(t*((k/m)**0.5))/((k/m)**0.5))-t))*1000
else:
deflection = ((((1000+9*x**2-183*x)*1000)/(k*((k/m)**0.5)*((20 - 0.12*x**2 + 4.2*x)/1000)))*(sin(((k/m)**0.5)*t))-(sin(((k/m)**0.5)*(t-((20 - 0.12*x**2 + 4.2*x)/1000))))-(((1000+9*x**2-183*x)*1000)/k)*cos(((k/m)**0.5)*t))*1000
return deflection <= 99.99999999
b = (0.5,1)
be = (0.5,10)
bb = (0.1,2.0)
bnds = (b,be,bb,bb)
con1 = ({'type':'ineq','fun':kconstraint1})
con2 = ({'type':'ineq','fun':kconstraint2})
con3 = ({'type':'ineq','fun':mconstraint1})
con4 = ({'type':'ineq','fun':mconstraint2})
con5 = ({'type':'ineq','fun':xconstraint1})
con6 = ({'type':'ineq','fun':xconstraint2})
con7 = ({'type':'ineq','fun':zconstraint1})
cons = [con1,con2,con3,con4,con5,con6,con7]
xGUESS = 5
kGUESS = 3*10**6
mGUESS = 700
zGUESS = 90
x0 = np.array([xGUESS,kGUESS,mGUESS,zGUESS])
sol = minimize(objective,x0,method='SLSQP',bounds=bnds,constraints=cons,options={'disp':True})
xOpt = sol.x
CostOPT = sol.fun
kOPT = calck(xOpt)
xOPT = calcx(xOpt)
mOPT = calcm(xOpt)
zOPT = calcz(xOpt)
print(str(CostOPT))
print(str(calcx))
print(str(calcm))
print(str(calck))
print(str(calcz))

Trust-Region Dogleg Method for Nonlinear Equations

Hi I am trying to write a trust-region algorithm using the dogleg method with python for a class I have. I have a Newton's Method algorithm and Broyden's Method algorthm that agree with each other but I can't seem to get this Dogleg method to work.
Here is the function I am trying to find the solution to:
def test_function(x):
x1 = float(x[0])
x2 = float(x[1])
r = np.array([[x2**2 - 1],
[np.sin(x1) - x2]])
return r
and here is the jacobian I wrote
def Test_Jacobian(x, size):
e = create_ID_vec(size)
#print(e[0])
epsilon = 10e-8
J = np.zeros([size,size])
#print (J)
for i in range(0, size):
for j in range(0, size):
J[i][j] = ((test_function(x[i]*e[j] + epsilon*e[j])[i] - test_function(x[i]*e[j])[i])/epsilon)
return J
and here is my Trust-Region algorithm:
def Trust_Region(x):
trust_radius = 1
max_trust = 300
eta = rand.uniform(0,.25)
r = test_function(x) # change to correspond with the function you want
J = Test_Jacobian(r, r.size) # change to correspond with function
i = 0
iteration_table = [i]
function_table = [vector_norm(r, r.size)]
while vector_norm(r, r.size) > 10e-10:
print(x, 'at iteration', i, "norm of r is", vector_norm(r, r.size))
p = dogleg(x, r, J, trust_radius)
rho = ratio(x, J, p)
if rho < 0.25:
print('first')
trust_radius = 0.25*vector_norm(p,p.size)
elif rho > 0.75 and vector_norm(p,p.size) == trust_radius:
print('second')
trust_radius = min(2*trust_radius, max_trust)
else:
print('third')
trust_radius = trust_radius
if rho > eta:
print('x changed')
x = x + p
#r = test_function(x)
#J = Test_Jacobian(r, r.size)
else:
print('x did not change')
x = x
r = test_function(x) # change to correspond with the function you want
J = Test_Jacobian(r, r.size) # change to correspond with function
i = i + 1
#print(r)
#print(J)
#print(vector_norm(p,p.size))
print(rho)
#print(trust_radius)
iteration_table.append(i)
function_table.append(vector_norm(r,r.size))
print ('The solution to the non-linear equation is: ', x)
print ('This solution was obtained in ', i, 'iteratations')
plt.figure(figsize=(10,10))
plt.plot(iteration_table, np.log10(function_table))
plt.xlabel('iteration number')
plt.ylabel('function value')
plt.title('Semi-Log Plot for Convergence')
return x, iteration_table, function_table
def dogleg(x, r, J, trust_radius):
tau_k = min(1, vector_norm(J.transpose().dot(r), r.size)**3/(trust_radius*r.transpose().dot(J).dot(J.transpose().dot(J)).dot(J.transpose()).dot(r)))
p_c = -tau_k*(trust_radius/vector_norm(J.transpose().dot(r), r.size))*J.transpose().dot(r)
if vector_norm(p_c, p_c.size) == trust_radius:
print('using p_c')
p_k = p_c
else:
p_j = -np.linalg.inv(J.transpose().dot(J)).dot(J.transpose().dot(r))
print ('using p_j')
tau = tau_finder(x, p_c, p_j, trust_radius, r.size)
p_k = p_c + tau*(p_j-p_c)
return p_k
def ratio(x, J, p):
r = test_function(x)
r_p = test_function(x + p)
print (vector_norm(r, r.size)**2)
print (vector_norm(r_p, r_p.size)**2)
print (vector_norm(r + J.dot(p), r.size)**2)
rho_k =(vector_norm(r, r.size)**2 - vector_norm(r_p, r_p.size)**2)/(vector_norm(r, r.size)**2 - vector_norm(r + J.dot(p), r.size)**2)
return rho_k
def tau_finder(x, p_c, p_j, trust_radius, size):
a = 0
b = 0
c = 0
for i in range(0, size):
a = a + (p_j[i] - p_c[i])**2
b = b + 2*(p_j[i] - p_c[i])*(p_c[i] - x[i])
c = (p_c[i] - x[i])**2
c = c - trust_radius**2
tau_p = (-b + np.sqrt(b**2 - 4*a*c))/(2*a)
tau_m = (-b - np.sqrt(b**2 - 4*a*c))/(2*a)
#print(tau_p)
#print(tau_m)
if tau_p <= 1 and tau_p >=0:
return tau_p
elif tau_m <= 1 and tau_m >=0:
return tau_m
else:
print('error')
return 'error'
def model_function(p):
r = test_function(x)
J = Test_Jacobian(r, r.size)
return 0.5*vector_norm(r + J.dot(p), r.size)**2
The answer should be about [[1.57076525], [1. ]]
but here is the output after about 28-30 iterations:
ZeroDivisionError Traceback (most recent call last)
<ipython-input-359-a414711a1671> in <module>
1 x = create_point(2,1)
----> 2 Trust_Region(x)
<ipython-input-358-7cb77bd44d7b> in Trust_Region(x)
11 print(x, 'at iteration', i, "norm of r is", vector_norm(r, r.size))
12 p = dogleg(x, r, J, trust_radius)
---> 13 rho = ratio(x, J, p)
14
15 if rho < 0.25:
<ipython-input-358-7cb77bd44d7b> in ratio(x, J, p)
71 print (vector_norm(r_p, r_p.size)**2)
72 print (vector_norm(r + J.dot(p), r.size)**2)
---> 73 rho_k =(vector_norm(r, r.size)**2 - vector_norm(r_p, r_p.size)**2)/(vector_norm(r, r.size)**2 - vector_norm(r + J.dot(p), r.size)**2)
74 return rho_k
75
ZeroDivisionError: float division by zero

Python using givens rotation for QR decomposition

I need help defining a function to compute the QR decomposition of a matrix using rotators and a conditional to check if a number is nearly zero before applying a rotator (tolerance of 1e-15)
import numpy as np
A = np.array(([(1,-2,3),(0,-1,4),(0,2,5)]))
def QRrot(A):
m,n = A.shape
indexI = np.zeros(m,n)
indexJ = np.zeros(m,n)
C = np.zeros(m,n)
S = np.zeros(m,n)
for i in range(1, n):
for j in range(i+1, m):
c = A(i,i)/((A(i,i))**2 + (A(j,i)**2))**0.5;
s = A(j,i)/((A(i,i))**2 + (A(j,i)**2))**0.5;
A[i,:] = c*A[i,:] + s*A[j,:];
A[j,:] = -s*A[i,:] + c*A[j,:];
indexI[j,i] = i;
indexJ[j,i] = j;
C[j,i] = c;
S[j,i] = s;
R = A
Q = np.eye(m)
Q[:,i] = c*Q[:,i] + s*Q[:,j];
Q[:,j] = -s*Q[:,i] + c*Q[:,j];
return(Q,R)

Python Linear Diophantine Equation

I am doing the homework for class and I was doing some research. I found the example equation for finding the diophantine equation.
The assignment is given when there is gcd(a, b) == 1, then there is a diophantine equation where
ax + by = 1.
I understood how this equation finds the value for x and y but I am not sure how this function is working. I got the part where there is divmod and recursive method inside the function, but I do not know when does it stop.
sorry for complex and ambiguous questions, but I wanna know how this equation works. I mean, how this equation ends.
For example, when there is given number 43 and 486 then gcd(43, 486) == 1.
That mean there's a equation where 43x + 486y = 1. the solution said 43(-113) + 486(10) = 1. And the function solve got the x and y value as well.
I was trying to follow through the code and see how it process, but I do not understand else: part.
def isolve(a, b):
quotient, remainder = divmod(a, b)
if remainder == 0:
return [0, 1 / b]
else:
sol = isolve(b, remainder)
x = sol[0]
y = sol[1]
return [y, x - quotient * y]
I am not sure I understand exactly what you are after, but let's consider the following modified code:
def simple_linear_diophantine_r(a, b):
q, r = divmod(a, b)
if r == 0:
return (0, b)
else:
x, y = simple_linear_diophantine_r(b, r)
return (y, x - q * y)
a, b = 43, 486
x, y = simple_linear_diophantine_r(a, b)
print(f'({a}) * ({x}) + ({b}) * ({y}) == {a * x + b * y}')
# (43) * (-113) + (486) * (10) == 1
which works as expected. Compared to the original code, I have rewritten the math in a way that only int-safe operations are used (no float division is used).
Additionally, I have renamed the function itself and some of the internal variables.
So far, this is more or less what you knew already.
Now, one way to understand what is happening is to use a Python's debugger.
A simpler to illustrate approach is to place some print() calls in strategic places:
def simple_linear_diophantine_r(a, b):
q, r = divmod(a, b)
print(f'a={a}, b={b}, q={q}, r={r}') # DEBUG
if r == 0:
return (0, b)
else:
x, y = simple_linear_diophantine_r(b, r)
print(f'x={x}, y={y}') # DEBUG
return (y, x - q * y)
a, b = 43, 486
x, y = simple_linear_diophantine_r(a, b)
print(f'(a={a}) * (x={x}) + (b={b}) * (y={y}) == {a * x + b * y}')
# a=43, b=486, q=0, r=43
# a=486, b=43, q=11, r=13
# a=43, b=13, q=3, r=4
# a=13, b=4, q=3, r=1
# a=4, b=1, q=4, r=0
# x=0, y=1, q=3
# x=1, y=-3, q=3
# x=-3, y=10, q=11
# x=10, y=-113, q=0
# -113 10
# (a=43) * (x=-113) + (b=486) * (y=10) == 1
and now you can more easily follow what is happening at each function call.
The same result can be obtained with an iterative function:
def simple_linear_diophantine_i(a, b, debug=False):
qs = []
while True:
q, r = divmod(a, b)
if debug:
print(f'a={a}, b={b}, q={q}, r={r}')
a = b
b = r
if r != 0:
qs.append(q)
else:
break
x, y = b, a
for q in qs[::-1]:
if debug:
print(f'x={x}, y={y}, q={q}')
x, y = y, x - q * y
return x, y
a, b = 43, 486
x, y = simple_linear_diophantine_i(a, b, True)
print(x, y)
# a=43, b=486, q=0, r=43
# a=486, b=43, q=11, r=13
# a=43, b=13, q=3, r=4
# a=13, b=4, q=3, r=1
# a=4, b=1, q=4, r=0
# x=0, y=1, q=3
# x=1, y=-3, q=3
# x=-3, y=10, q=11
# x=10, y=-113, q=0
# (a=43) * (x=-113) + (b=486) * (y=10) == 1
with somewhat similar timing:
a = 123464357645765475246432152143432154321543256432654367547658641353276548767132465498760908567542543215
b = 65432654786531234532634712432
funcs = simple_linear_diophantine_r, simple_linear_diophantine_i
base = funcs[0](a, b)
print(base)
# (-14645224987639174972552062305, 27633958939547408859252562549330013276609719423270432707256961858787144635978588031424076994432005543)
for func in funcs:
res = func(a, b)
is_good = base == res
timed = %timeit -n 128 -r 128 -oq func(a, b)
timing = timed.best * 1e6
print(f"{func.__name__:>24} {is_good} {timing:10.3f} µs")
# simple_linear_diophantine_r True 25.855 µs
# simple_linear_diophantine_i True 22.439 µs
I also wrote a Linear Diophantine program that has stats and is faster than egcd python programs iv'e used so wanted to include it here for others interested in programs that solve these:
def llinear_diophantinex(a, b, divmodx=1, x=1, y=0, withstats=False):
origa, origb = a, b
r=a
q = a//b
prevq=1
if withstats == True:
print(f"a = {a}, b = {b}, q = {q}, r = {r}")
while r != 0:
prevr = r
a,r,b = b, b, r
q,r = divmod(a,b)
x, y = y, x - q * y
if withstats == True:
print(f"a = {a}, b = {b}, q = {q}, r = {r}, x = {x}, y = {y}")
y = 1 - origb*x // origa - 1
x,y=y,x
modx = (-abs(x)*divmodx)%origb
if withstats == True:
print(f"x = {x}, y = {y}, modx = {modx}")
return x, y, modx
In [5410]: llinear_diophantinex(272,1009, withstats=True)
a = 272, b = 1009, q = 0, r = 272
a = 1009, b = 272, q = 3, r = 193, x = 0, y = 1
a = 272, b = 193, q = 1, r = 79, x = 1, y = -1
a = 193, b = 79, q = 2, r = 35, x = -1, y = 3
a = 79, b = 35, q = 2, r = 9, x = 3, y = -7
a = 35, b = 9, q = 3, r = 8, x = -7, y = 24
a = 9, b = 8, q = 1, r = 1, x = 24, y = -31
a = 8, b = 1, q = 8, r = 0, x = -31, y = 272
x = 115, y = -31, modx = 894
Out[5410]: (115, -31, 894)

SHA-256 implementation in Python

I'm looking for a Python implementation of the SHA-256 hash function. I want to use it to get a better understanding of how the SHA-256 function works, and I think Python is the ideal language for this. Pseudo-code has the limitation that I can't run/test it, to see what my modifications of the code do to the output.
PyPy's source contains a pure-python implementation of SHA-256 here. Poking around in that directory, you'll probably also find pure-python implementations of other standard hashes.
initial_hash_values=[
'6a09e667','bb67ae85','3c6ef372','a54ff53a',
'510e527f','9b05688c','1f83d9ab','5be0cd19'
]
sha_256_constants=[
'428a2f98','71374491','b5c0fbcf','e9b5dba5',
'3956c25b','59f111f1','923f82a4','ab1c5ed5',
'd807aa98','12835b01','243185be','550c7dc3',
'72be5d74','80deb1fe','9bdc06a7','c19bf174',
'e49b69c1','efbe4786','0fc19dc6','240ca1cc',
'2de92c6f','4a7484aa','5cb0a9dc','76f988da',
'983e5152','a831c66d','b00327c8','bf597fc7',
'c6e00bf3','d5a79147','06ca6351','14292967',
'27b70a85','2e1b2138','4d2c6dfc','53380d13',
'650a7354','766a0abb','81c2c92e','92722c85',
'a2bfe8a1','a81a664b','c24b8b70','c76c51a3',
'd192e819','d6990624','f40e3585','106aa070',
'19a4c116','1e376c08','2748774c','34b0bcb5',
'391c0cb3','4ed8aa4a','5b9cca4f','682e6ff3',
'748f82ee','78a5636f','84c87814','8cc70208',
'90befffa','a4506ceb','bef9a3f7','c67178f2'
]
def bin_return(dec):
return(str(format(dec,'b')))
def bin_8bit(dec):
return(str(format(dec,'08b')))
def bin_32bit(dec):
return(str(format(dec,'032b')))
def bin_64bit(dec):
return(str(format(dec,'064b')))
def hex_return(dec):
return(str(format(dec,'x')))
def dec_return_bin(bin_string):
return(int(bin_string,2))
def dec_return_hex(hex_string):
return(int(hex_string,16))
def L_P(SET,n):
to_return=[]
j=0
k=n
while k<len(SET)+1:
to_return.append(SET[j:k])
j=k
k+=n
return(to_return)
def s_l(bit_string):
bit_list=[]
for i in range(len(bit_string)):
bit_list.append(bit_string[i])
return(bit_list)
def l_s(bit_list):
bit_string=''
for i in range(len(bit_list)):
bit_string+=bit_list[i]
return(bit_string)
def rotate_right(bit_string,n):
bit_list = s_l(bit_string)
count=0
while count <= n-1:
list_main=list(bit_list)
var_0=list_main.pop(-1)
list_main=list([var_0]+list_main)
bit_list=list(list_main)
count+=1
return(l_s(list_main))
def shift_right(bit_string,n):
bit_list=s_l(bit_string)
count=0
while count <= n-1:
bit_list.pop(-1)
count+=1
front_append=['0']*n
return(l_s(front_append+bit_list))
def mod_32_addition(input_set):
value=0
for i in range(len(input_set)):
value+=input_set[i]
mod_32 = 4294967296
return(value%mod_32)
def xor_2str(bit_string_1,bit_string_2):
xor_list=[]
for i in range(len(bit_string_1)):
if bit_string_1[i]=='0' and bit_string_2[i]=='0':
xor_list.append('0')
if bit_string_1[i]=='1' and bit_string_2[i]=='1':
xor_list.append('0')
if bit_string_1[i]=='0' and bit_string_2[i]=='1':
xor_list.append('1')
if bit_string_1[i]=='1' and bit_string_2[i]=='0':
xor_list.append('1')
return(l_s(xor_list))
def and_2str(bit_string_1,bit_string_2):
and_list=[]
for i in range(len(bit_string_1)):
if bit_string_1[i]=='1' and bit_string_2[i]=='1':
and_list.append('1')
else:
and_list.append('0')
return(l_s(and_list))
def or_2str(bit_string_1,bit_string_2):
or_list=[]
for i in range(len(bit_string_1)):
if bit_string_1[i]=='0' and bit_string_2[i]=='0':
or_list.append('0')
else:
or_list.append('1')
return(l_s(or_list))
def not_str(bit_string):
not_list=[]
for i in range(len(bit_string)):
if bit_string[i]=='0':
not_list.append('1')
else:
not_list.append('0')
return(l_s(not_list))
'''
SHA-256 Specific Functions:
'''
def Ch(x,y,z):
return(xor_2str(and_2str(x,y),and_2str(not_str(x),z)))
def Maj(x,y,z):
return(xor_2str(xor_2str(and_2str(x,y),and_2str(x,z)),and_2str(y,z)))
def e_0(x):
return(xor_2str(xor_2str(rotate_right(x,2),rotate_right(x,13)),rotate_right(x,22)))
def e_1(x):
return(xor_2str(xor_2str(rotate_right(x,6),rotate_right(x,11)),rotate_right(x,25)))
def s_0(x):
return(xor_2str(xor_2str(rotate_right(x,7),rotate_right(x,18)),shift_right(x,3)))
def s_1(x):
return(xor_2str(xor_2str(rotate_right(x,17),rotate_right(x,19)),shift_right(x,10)))
def message_pad(bit_list):
pad_one = bit_list + '1'
pad_len = len(pad_one)
k=0
while ((pad_len+k)-448)%512 != 0:
k+=1
back_append_0 = '0'*k
back_append_1 = bin_64bit(len(bit_list))
return(pad_one+back_append_0+back_append_1)
def message_bit_return(string_input):
bit_list=[]
for i in range(len(string_input)):
bit_list.append(bin_8bit(ord(string_input[i])))
return(l_s(bit_list))
def message_pre_pro(input_string):
bit_main = message_bit_return(input_string)
return(message_pad(bit_main))
def message_parsing(input_string):
return(L_P(message_pre_pro(input_string),32))
def message_schedule(index,w_t):
new_word = bin_32bit(mod_32_addition([int(s_1(w_t[index-2]),2),int(w_t[index-7],2),int(s_0(w_t[index-15]),2),int(w_t[index-16],2)]))
return(new_word)
'''
This example of SHA_256 works for an input string <56 characters.
'''
def sha_256(input_string):
assert len(input_string) < 56, "This example of SHA_256 works for an input string <56 characters."
w_t=message_parsing(input_string)
a=bin_32bit(dec_return_hex(initial_hash_values[0]))
b=bin_32bit(dec_return_hex(initial_hash_values[1]))
c=bin_32bit(dec_return_hex(initial_hash_values[2]))
d=bin_32bit(dec_return_hex(initial_hash_values[3]))
e=bin_32bit(dec_return_hex(initial_hash_values[4]))
f=bin_32bit(dec_return_hex(initial_hash_values[5]))
g=bin_32bit(dec_return_hex(initial_hash_values[6]))
h=bin_32bit(dec_return_hex(initial_hash_values[7]))
for i in range(0,64):
if i <= 15:
t_1=mod_32_addition([int(h,2),int(e_1(e),2),int(Ch(e,f,g),2),int(sha_256_constants[i],16),int(w_t[i],2)])
t_2=mod_32_addition([int(e_0(a),2),int(Maj(a,b,c),2)])
h=g
g=f
f=e
e=mod_32_addition([int(d,2),t_1])
d=c
c=b
b=a
a=mod_32_addition([t_1,t_2])
a=bin_32bit(a)
e=bin_32bit(e)
if i > 15:
w_t.append(message_schedule(i,w_t))
t_1=mod_32_addition([int(h,2),int(e_1(e),2),int(Ch(e,f,g),2),int(sha_256_constants[i],16),int(w_t[i],2)])
t_2=mod_32_addition([int(e_0(a),2),int(Maj(a,b,c),2)])
h=g
g=f
f=e
e=mod_32_addition([int(d,2),t_1])
d=c
c=b
b=a
a=mod_32_addition([t_1,t_2])
a=bin_32bit(a)
e=bin_32bit(e)
hash_0 = mod_32_addition([dec_return_hex(initial_hash_values[0]),int(a,2)])
hash_1 = mod_32_addition([dec_return_hex(initial_hash_values[1]),int(b,2)])
hash_2 = mod_32_addition([dec_return_hex(initial_hash_values[2]),int(c,2)])
hash_3 = mod_32_addition([dec_return_hex(initial_hash_values[3]),int(d,2)])
hash_4 = mod_32_addition([dec_return_hex(initial_hash_values[4]),int(e,2)])
hash_5 = mod_32_addition([dec_return_hex(initial_hash_values[5]),int(f,2)])
hash_6 = mod_32_addition([dec_return_hex(initial_hash_values[6]),int(g,2)])
hash_7 = mod_32_addition([dec_return_hex(initial_hash_values[7]),int(h,2)])
final_hash = (hex_return(hash_0),
hex_return(hash_1),
hex_return(hash_2),
hex_return(hash_3),
hex_return(hash_4),
hex_return(hash_5),
hex_return(hash_6),
hex_return(hash_7))
return(final_hash)
Some time ago I was also studying SHA-256 and created pure-python class that implements this hash. If I remember correctly, mostly I've taken algorithm from Wikipedia SHA-256 Pseudocode and partially from some open-source projects.
Algorithm doesn't import any (even standard) modules. Of cause it is much slower than hashlib's variant and only meant for studying.
If you just run the script it executes 1000 tests comparing hashlib's and my variants. Only testing function imports some modules, algorithm's class itself doesn't need any modules. Interface is same as in hashlib's sha256 class. See test() function for examples of usage.
Try it online!
class Sha256:
ks = [
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,
]
hs = [
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
]
M32 = 0xFFFFFFFF
def __init__(self, m = None):
self.mlen = 0
self.buf = b''
self.k = self.ks[:]
self.h = self.hs[:]
self.fin = False
if m is not None:
self.update(m)
#staticmethod
def pad(mlen):
mdi = mlen & 0x3F
length = (mlen << 3).to_bytes(8, 'big')
padlen = 55 - mdi if mdi < 56 else 119 - mdi
return b'\x80' + b'\x00' * padlen + length
#staticmethod
def ror(x, y):
return ((x >> y) | (x << (32 - y))) & Sha256.M32
#staticmethod
def maj(x, y, z):
return (x & y) ^ (x & z) ^ (y & z)
#staticmethod
def ch(x, y, z):
return (x & y) ^ ((~x) & z)
def compress(self, c):
w = [0] * 64
w[0 : 16] = [int.from_bytes(c[i : i + 4], 'big') for i in range(0, len(c), 4)]
for i in range(16, 64):
s0 = self.ror(w[i - 15], 7) ^ self.ror(w[i - 15], 18) ^ (w[i - 15] >> 3)
s1 = self.ror(w[i - 2], 17) ^ self.ror(w[i - 2], 19) ^ (w[i - 2] >> 10)
w[i] = (w[i - 16] + s0 + w[i - 7] + s1) & self.M32
a, b, c, d, e, f, g, h = self.h
for i in range(64):
s0 = self.ror(a, 2) ^ self.ror(a, 13) ^ self.ror(a, 22)
t2 = s0 + self.maj(a, b, c)
s1 = self.ror(e, 6) ^ self.ror(e, 11) ^ self.ror(e, 25)
t1 = h + s1 + self.ch(e, f, g) + self.k[i] + w[i]
h = g
g = f
f = e
e = (d + t1) & self.M32
d = c
c = b
b = a
a = (t1 + t2) & self.M32
for i, (x, y) in enumerate(zip(self.h, [a, b, c, d, e, f, g, h])):
self.h[i] = (x + y) & self.M32
def update(self, m):
if m is None or len(m) == 0:
return
assert not self.fin, 'Hash already finalized and can not be updated!'
self.mlen += len(m)
m = self.buf + m
for i in range(0, len(m) // 64):
self.compress(m[64 * i : 64 * (i + 1)])
self.buf = m[len(m) - (len(m) % 64):]
def digest(self):
if not self.fin:
self.update(self.pad(self.mlen))
self.digest = b''.join(x.to_bytes(4, 'big') for x in self.h[:8])
self.fin = True
return self.digest
def hexdigest(self):
tab = '0123456789abcdef'
return ''.join(tab[b >> 4] + tab[b & 0xF] for b in self.digest())
def test():
import secrets, hashlib, random
for itest in range(500):
data = secrets.token_bytes(random.randrange(257))
a, b = hashlib.sha256(data).hexdigest(), Sha256(data).hexdigest()
assert a == b, (a, b)
for itest in range(500):
a, b = hashlib.sha256(), Sha256()
for j in range(random.randrange(10)):
data = secrets.token_bytes(random.randrange(129))
a.update(data)
b.update(data)
a, b = a.hexdigest(), b.hexdigest()
assert a == b, (a, b)
print('Sha256 tested successfully.')
if __name__ == '__main__':
test()
If you only want the hash value:
from hashlib import sha256
data = input('Enter plaintext data: ')
output = sha256(data.encode('utf-8'))
print(output)
Python's hashlib also has SHA-1, SHA-384, SHA-512, and MD5 hash functions.
Here is my proposition with redis:
for i in range(len(rserver.keys())):
mdp_hash = rserver.get(rserver.keys()[i])
rserver.set(rserver.keys()[i], hashlib.sha256(mdp_hash.encode()).hexdigest())
Translating http://en.wikipedia.org/wiki/SHA-2#SHA-256_.28a_SHA-2_variant.29_pseudocode to Python should be straight forward.

Categories

Resources