Skip to content

Instantly share code, notes, and snippets.

@back-seat-driver
Last active October 4, 2017 02:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save back-seat-driver/b2f81929741cd94b1ff17086fdaad0bd to your computer and use it in GitHub Desktop.
Save back-seat-driver/b2f81929741cd94b1ff17086fdaad0bd to your computer and use it in GitHub Desktop.
SHA-3 Speed Improvement
#https://gist.github.com/back-seat-driver/b2f81929741cd94b1ff17086fdaad0bd
def bin_n_bit(dec,n):
return(str(format(dec,'0'+n+'b')))
def hex_n_bit(dec,n):
return(str(format(dec,'0'+n+'x')))
def xo_set(ip_0,ip_1):
to_return=[]
for i in range(len(ip_0)):
to_return.append(ip_0[i] ^ ip_1[i])
return(to_return)
def L_P(SET,n):
to_return = [] ; j = 0
while j + n <= len(SET):
to_return.append(SET[j:j+n])
j += n
return(to_return)
def str_concat(list_of_strings):
to_return=''
for i in range(len(list_of_strings)):
to_return+=list_of_strings[i]
return(to_return)
def flip_string(a_string):
to_return=''
for i in range(1,len(a_string)+1):
to_return+=a_string[-i]
return(to_return)
def rot(x,n,l):
n = n%l
return((x>>(l-n))+(x<<n))%(1<<l)
def theta(ip):
c_xz=[]
for i in range(5):
c_xz.append(ip[i] ^ ip[i+5] ^ ip[i+10] ^ ip[i+15] ^ ip[i+20])
for i in range(5):
d_xz = c_xz[(i-1)%5] ^ rot(c_xz[(i+1)%5],1,64)
for x in range(0,25,5):
ip[i+x] = ip[i+x] ^ d_xz
return(ip)
def rho(ip):
fast_rot=[0,1,62,28,27,
36,44,6,55,20,
3,10,43,25,39,
41,45,15,21,8,
18,2,61,56,14]
for i in range(25):
ip[i] = rot(ip[i], fast_rot[i], 64)
return(ip)
def pi(ip):
index=[0,6,12,18,24,
3,9,10,16,22,
1,7,13,19,20,
4,5,11,17,23,
2,8,14,15,21]
to_return=[]
for i in range(25):
for x in range(25):
if index[i]==x:
to_return.append(ip[x])
return(to_return)
def chi(ip):
def sf(find_list,set_main):
return(set_main.index(find_list))
sm=[[0,0],[1,0],[2,0],[3,0],[4,0],
[0,1],[1,1],[2,1],[3,1],[4,1],
[0,2],[1,2],[2,2],[3,2],[4,2],
[0,3],[1,3],[2,3],[3,3],[4,3],
[0,4],[1,4],[2,4],[3,4],[4,4]]
to_return=[]
for i in range(25):
to_return.append(ip[i] ^ ~ip[sf([(sm[i][0]+1)%5,sm[i][1]],sm)] &
ip[sf([(sm[i][0]+2)%5,sm[i][1]],sm)])
return(to_return)
def iota(ip,i_r):
RC=[0x0000000000000001,
0x0000000000008082,
0x800000000000808A,
0x8000000080008000,
0x000000000000808B,
0x0000000080000001,
0x8000000080008081,
0x8000000000008009,
0x000000000000008A,
0x0000000000000088,
0x0000000080008009,
0x000000008000000A,
0x000000008000808B,
0x800000000000008B,
0x8000000000008089,
0x8000000000008003,
0x8000000000008002,
0x8000000000000080,
0x000000000000800A,
0x800000008000000A,
0x8000000080008081,
0x8000000000008080,
0x0000000080000001,
0x8000000080008008]
ip[0]=ip[0] ^ RC[i_r]
return(ip)
def boost(ip):
to_return=[]
for i in range(25):
to_return.append(int(ip[i],2))
return(to_return)
def booster(op):
to_return=[]
for i in range(25):
to_return.append(bin_n_bit(op[i],'64'))
return(to_return)
def sha_3_rate(output_len):
if output_len==224:
return(1152)
if output_len==256:
return(1088)
if output_len==384:
return(832)
if output_len==512:
return(576)
def pad(x,m):
j=(-m-2)%x
return('1'+'0'*j+'1')
##def message_processing(bit_string,digest_len):
## if len(bit_string)!=sha_3_rate(digest_len):
## msg_bs = bit_string + '01'
## p = msg_bs + pad(sha_3_rate(digest_len),len(msg_bs))
## if len(bit_string)==sha_3_rate(digest_len):
## p=bit_string
## to_split = L_P(p,8)
## new_hex=[]
## for i in range(len(to_split)):
## new_hex.append(hex_n_bit(int(flip_string(to_split[i]),2),'2'))
## back_append = 200-len(new_hex)
## new_hex = new_hex+['00']*back_append
## total_string=''
## for i in range(len(new_hex)):
## total_string+=new_hex[i]
## to_insert = L_P(total_string,16)
## to_return=[]
## for i in range(len(to_insert)):
## to_return.append(flip_string(L_P(to_insert[i],2)))
## print(to_return)
## return(to_return)
def message_processing(bit_string,digest_len):
if len(bit_string)!=sha_3_rate(digest_len):
msg_bs = bit_string + '01'
p = msg_bs + pad(sha_3_rate(digest_len),len(msg_bs))
if len(bit_string)==sha_3_rate(digest_len):
p=bit_string
state_fill = L_P(bit_string + '0'*(1600-len(bit_string)),64)
print(state_fill)
to_split = L_P(p,8)
new_hex=[]
for i in range(len(to_split)):
new_hex.append(hex_n_bit(int(flip_string(to_split[i]),2),'2'))
back_append = 200-len(new_hex)
new_hex = new_hex+['00']*back_append
total_string=''
for i in range(len(new_hex)):
total_string+=new_hex[i]
to_insert = L_P(total_string,16)
to_return=[]
for i in range(len(to_insert)):
to_return.append(flip_string(L_P(to_insert[i],2)))
print(to_return)
return(to_return)
def message_expansion(hex_list):
to_convert=''
for i in range(len(hex_list)):
to_convert+=bin_n_bit(int(hex_list[i],16),'8')
return(to_convert)
def message_bit_return(string_input):
bit_list=''
for i in range(len(string_input)):
bit_list+=bin_n_bit(ord(string_input[i]),'8')
return(bit_list)
def main_bit_set(bit_string,digest_len):
#All this function does is take the primary sha_3 seed
#and return the block chain to be iterated to hashing.
front_append=L_P(bit_string,sha_3_rate(digest_len))
back_string=''
for i in range(len(bit_string)%sha_3_rate(digest_len)):
back_string+=bit_string[-(i+1)]
back_string=flip_string(back_string)
return(front_append+[back_string])
def edian_bit_convert(list_of_strings):
to_return=[]
for i in range(len(list_of_strings)):
inter=L_P(list_of_strings[i],8)
insert=''
for x in range(1,len(inter)+1):
insert+=inter[-x]
to_return.append(insert)
return(to_return)
def edian_byte_convert(list_strings):
to_return=[]
for i in range(len(list_strings)):
inter=L_P(list_strings[i],2)
insert=''
for x in range(1,len(inter)+1):
insert+=inter[-x]
to_return.append(insert)
return(to_return)
def hex_bin_convert(hex_string):
to_return=''
for i in range(len(hex_string)):
to_return+=bin_n_bit(int(hex_string[i],16),'4')
return(to_return)
def set_convert(list_hex_string):
to_return=[]
def hex_bin_convert(hex_string):
to_return=''
for i in range(len(hex_string)):
to_return+=bin_n_bit(int(hex_string[i],16),'4')
return(to_return)
for i in range(len(list_hex_string)):
to_return.append(hex_bin_convert(list_hex_string[i]))
return(to_return)
def output_final(input_set,digest_len):
to_flip=[]
if digest_len!=224:
for i in range(int(digest_len/64)):
to_flip.append(input_set[i])
if digest_len==224:
for i in range((digest_len//64)+1):
to_flip.append(input_set[i])
to_convert=[]
for i in range(len(to_flip)):
to_convert.append(L_P(to_flip[i],8))
bin_list=[]
for i in range(len(to_convert)):
bin_list.append(flip_string(to_convert[i]))
bin_list=L_P(str_concat(bin_list),4)
to_return=[]
for i in range(len(bin_list)):
to_return.append(hex_n_bit(int(bin_list[i],2),'1'))
to_return=str_concat(to_return)
if digest_len!=224:
return(to_return)
return(to_return[0:56])
def s3b(bit_string,digest_len):
if len(bit_string) < sha_3_rate(digest_len):
x = L_P(message_expansion(L_P(str_concat(message_processing(bit_string,digest_len)),2)),64)
stat_test=[]
for i in range(24):
x = booster(iota(chi(pi(rho(theta(boost(x))))),i))
return(output_final(x,digest_len))
if len(bit_string) >= sha_3_rate(digest_len):
set_main=main_bit_set(bit_string,digest_len)
x=L_P(message_expansion(L_P(str_concat(message_processing(set_main[0],digest_len)),2)),64)
for i in range(24):
x = booster(iota(chi(pi(rho(theta(boost(x))))),i))
for c in range(len(set_main)-1):
var_0=edian_bit_convert(x)
var_1=set_convert(edian_byte_convert(message_processing(set_main[c+1],digest_len)))
var_2=edian_bit_convert(booster(xo_set(boost(var_0),boost(var_1))))
for i in range(24):
var_2 = booster(iota(chi(pi(rho(theta(boost(var_2))))),i))
x=var_2
return(output_final(x,digest_len))
def s3(a_string,digest_len):
#Online convert will match sha_3 implementation provided
#by python 3.6 distribution. And online sha_3 generators.
#It's a one for one string conversions. s3b is a bit aligned
#sha_3 implementations.
to_return=''
for i in range(len(a_string)):
to_return+=flip_string(message_bit_return(a_string[i]))
return(s3b(to_return,digest_len))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment