import binascii import copy class Gascon(object): def __init__(self,nw,rounds): assert(1==(nw%2)) #sbox not bijective if nw is even assert(nw in [5,9]) self.__nw = nw self.__rounds = rounds assert(self.__rounds <= 12) @staticmethod def sbox(i,nw): S = [0]*nw for b in range(0,nw): S[b] = (i >> b) & 1 Gascon.sboxes(S,nw) r = 0 for b in range(0,nw): r |= (S[b] & 1)< 5: S[5] ^= self.rotr64_interleaved(S[5], 31) ^ self.rotr64_interleaved(S[5], 26) S[6] ^= self.rotr64_interleaved(S[6], 53) ^ self.rotr64_interleaved(S[6], 58) S[7] ^= self.rotr64_interleaved(S[7], 9) ^ self.rotr64_interleaved(S[7], 46) S[8] ^= self.rotr64_interleaved(S[8], 43) ^ self.rotr64_interleaved(S[8], 50) #if self.__nw > 9: # S[ 9] ^= self.rotr64_interleaved(S[ 9], ?) ^ self.rotr64_interleaved(S[ 9], ?) # S[10] ^= self.rotr64_interleaved(S[10], ?) ^ self.rotr64_interleaved(S[10], ?) # S[11] ^= self.rotr64_interleaved(S[11], ?) ^ self.rotr64_interleaved(S[11], ?) # S[12] ^= self.rotr64_interleaved(S[12], ?) ^ self.rotr64_interleaved(S[12], ?) # S[13] ^= self.rotr64_interleaved(S[13], ?) ^ self.rotr64_interleaved(S[13], ?) # S[14] ^= self.rotr64_interleaved(S[14], ?) ^ self.rotr64_interleaved(S[14], ?) self.__dbg(S,spy) #if spy: # exit() @staticmethod def rotr64(val, r): return ((val >> r) ^ (val << (64-r))) % (1 << 64) @staticmethod def rotr32(val, r): return ((val >> r) ^ (val << (32-r))) % (1 << 32) @staticmethod def rotr64_interleaved(val, r): i = [val & 0xFFFFFFFF, val>>32] shift2 = r//2 if r & 1: tmp = Gascon.rotr32(i[1],shift2); i[1] = Gascon.rotr32(i[0],(shift2+1)%32); i[0] = tmp; else: i[0] = Gascon.rotr32(i[0],shift2); i[1] = Gascon.rotr32(i[1],shift2); val = (i[1]<<32) | i[0] return val if __name__ == "__main__": def sbox_nw7_equations1(i): x0 = (i >> 0) & 1 x1 = (i >> 1) & 1 x2 = (i >> 2) & 1 x3 = (i >> 3) & 1 x4 = (i >> 4) & 1 x5 = (i >> 5) & 1 x6 = (i >> 6) & 1 a0 = x0 ^ x6 a1 = x1 a2 = x2 ^ x1 a3 = x3 a4 = x4 ^ x3 a5 = x5 a6 = x6 ^ x5 b0 = (1 ^ a0) & a1 b1 = (1 ^ a1) & a2 b2 = (1 ^ a2) & a3 b3 = (1 ^ a3) & a4 b4 = (1 ^ a4) & a5 b5 = (1 ^ a5) & a6 b6 = (1 ^ a6) & a0 c0 = a0 ^ b1 c1 = a1 ^ b2 c2 = a2 ^ b3 c3 = a3 ^ b4 c4 = a4 ^ b5 c5 = a5 ^ b6 c6 = a6 ^ b0 d0 = c0 ^ c6 d1 = c1 ^ c0 d2 = c2 d3 = c3 ^ c2 d4 = c4 d5 = c5 ^ c4 d6 = c6 y0 = d0 y1 = d1 y2 = d2 y3 = d3 ^ 1 y4 = d4 y5 = d5 y6 = d6 o = y0 o |= y1<<1 o |= y2<<2 o |= y3<<3 o |= y4<<4 o |= y5<<5 o |= y6<<6 return o def sbox_nw7_equations2(i): x0 = (i >> 0) & 1 x1 = (i >> 1) & 1 x2 = (i >> 2) & 1 x3 = (i >> 3) & 1 x4 = (i >> 4) & 1 x5 = (i >> 5) & 1 x6 = (i >> 6) & 1 b0 = ((1 ^ x0 ^ x6) & x1) b1 = ((1 ^ x1) & (x2 ^ x1)) b2 = ((1 ^ x2 ^ x1) & x3) b3 = ((1 ^ x3) & (x4 ^ x3)) b4 = ((1 ^ x4 ^ x3) & x5) b5 = ((1 ^ x5) & (x6 ^ x5)) b6 = ((1 ^ x6 ^ x5) & (x0 ^ x6)) c0 = x0 ^ x6 ^ (b1) c1 = x1 ^ (b2) c2 = x2 ^ x1 ^ (b3) c3 = x3 ^ (b4) c4 = x4 ^ x3 ^ (b5) c5 = x5 ^ (b6) c6 = x6 ^ x5 ^ (b0) d0 = c0 ^ c6 d1 = c1 ^ c0 d2 = c2 d3 = c3 ^ c2 d4 = c4 d5 = c5 ^ c4 d6 = c6 y0 = d0 y1 = d1 y2 = d2 y3 = d3 ^ 1 y4 = d4 y5 = d5 y6 = d6 o = y0 o |= y1<<1 o |= y2<<2 o |= y3<<3 o |= y4<<4 o |= y5<<5 o |= y6<<6 return o def sbox_nw7_equations3(i): x0 = (i >> 0) & 1 x1 = (i >> 1) & 1 x2 = (i >> 2) & 1 x3 = (i >> 3) & 1 x4 = (i >> 4) & 1 x5 = (i >> 5) & 1 x6 = (i >> 6) & 1 c0 = x0 ^ x6 ^ ((1 ^ x1) & (x2 ^ x1)) c1 = x1 ^ ((1 ^ x2 ^ x1) & x3) c2 = x2 ^ x1 ^ ((1 ^ x3) & (x4 ^ x3)) c3 = x3 ^ ((1 ^ x4 ^ x3) & x5) c4 = x4 ^ x3 ^ ((1 ^ x5) & (x6 ^ x5)) c5 = x5 ^ ((1 ^ x6 ^ x5) & (x0 ^ x6)) c6 = x6 ^ x5 ^ ((1 ^ x0 ^ x6) & x1) d0 = c0 ^ c6 d1 = c1 ^ c0 d2 = c2 d3 = c3 ^ c2 d4 = c4 d5 = c5 ^ c4 d6 = c6 y0 = d0 y1 = d1 y2 = d2 y3 = d3 ^ 1 y4 = d4 y5 = d5 y6 = d6 o = y0 o |= y1<<1 o |= y2<<2 o |= y3<<3 o |= y4<<4 o |= y5<<5 o |= y6<<6 return o def sbox_nw7_equations4(i): x0 = (i >> 0) & 1 x1 = (i >> 1) & 1 x2 = (i >> 2) & 1 x3 = (i >> 3) & 1 x4 = (i >> 4) & 1 x5 = (i >> 5) & 1 x6 = (i >> 6) & 1 d0 = x0 ^ x6 ^ ((1 ^ x1) & (x2 ^ x1)) ^ x6 ^ x5 ^ ((1 ^ x0 ^ x6) & x1) d1 = x1 ^ ((1 ^ x2 ^ x1) & x3) ^ x0 ^ x6 ^ ((1 ^ x1) & (x2 ^ x1)) d2 = x2 ^ x1 ^ ((1 ^ x3) & (x4 ^ x3)) d3 = x3 ^ ((1 ^ x4 ^ x3) & x5) ^ x2 ^ x1 ^ ((1 ^ x3) & (x4 ^ x3)) d4 = x4 ^ x3 ^ ((1 ^ x5) & (x6 ^ x5)) d5 = x5 ^ ((1 ^ x6 ^ x5) & (x0 ^ x6)) ^ x4 ^ x3 ^ ((1 ^ x5) & (x6 ^ x5)) d6 = x6 ^ x5 ^ ((1 ^ x0 ^ x6) & x1) y0 = d0 y1 = d1 y2 = d2 y3 = d3 ^ 1 y4 = d4 y5 = d5 y6 = d6 o = y0 o |= y1<<1 o |= y2<<2 o |= y3<<3 o |= y4<<4 o |= y5<<5 o |= y6<<6 return o def sbox_nw7_equations5(i): x0 = (i >> 0) & 1 x1 = (i >> 1) & 1 x2 = (i >> 2) & 1 x3 = (i >> 3) & 1 x4 = (i >> 4) & 1 x5 = (i >> 5) & 1 x6 = (i >> 6) & 1 y0 = x0 ^ x6 ^ ((1 ^ x1) & (x2 ^ x1)) ^ x6 ^ x5 ^ ((1 ^ x0 ^ x6) & x1) y1 = x1 ^ ((1 ^ x2 ^ x1) & x3) ^ x0 ^ x6 ^ ((1 ^ x1) & (x2 ^ x1)) y2 = x2 ^ x1 ^ ((1 ^ x3) & (x4 ^ x3)) y3 = x3 ^ ((1 ^ x4 ^ x3) & x5) ^ x2 ^ x1 ^ ((1 ^ x3) & (x4 ^ x3)) ^ 1 y4 = x4 ^ x3 ^ ((1 ^ x5) & (x6 ^ x5)) y5 = x5 ^ ((1 ^ x6 ^ x5) & (x0 ^ x6)) ^ x4 ^ x3 ^ ((1 ^ x5) & (x6 ^ x5)) y6 = x6 ^ x5 ^ ((1 ^ x0 ^ x6) & x1) o = y0 o |= y1<<1 o |= y2<<2 o |= y3<<3 o |= y4<<4 o |= y5<<5 o |= y6<<6 return o def sbox_nw7_equations(i): x0 = (i >> 0) & 1 x1 = (i >> 1) & 1 x2 = (i >> 2) & 1 x3 = (i >> 3) & 1 x4 = (i >> 4) & 1 x5 = (i >> 5) & 1 x6 = (i >> 6) & 1 y0 = (x6 & x1) ^ x5 ^ (x2 & x1) ^ x2 ^ (x1 & x0) ^ x1 ^ x0 y1 = x6 ^ (x3 & x2) ^ (x3 & x1) ^ x3 ^ (x2 & x1) ^ x2 ^ x1 ^ x0 y2 = (x4 & x3) ^ x4 ^ x2 ^ x1 y3 = (x5 & x4) ^ (x5 & x3) ^ x5 ^ (x4 & x3) ^ x4 ^ x3 ^ x2 ^ x1 ^ 1 y4 = (x6 & x5) ^ x6 ^ x4 ^ x3 y5 = (x6 & x0) ^ x6 ^ (x5 & x0) ^ x5 ^ x4 ^ x3 ^ x0 y6 = (x6 & x1) ^ x6 ^ x5 ^ (x1 & x0) ^ x1 o = y0 o |= y1<<1 o |= y2<<2 o |= y3<<3 o |= y4<<4 o |= y5<<5 o |= y6<<6 return o def test_nw7_equations(): nw=7 for i in range(0,1<> 0) & 1 x1 = (i >> 1) & 1 x2 = (i >> 2) & 1 x3 = (i >> 3) & 1 x4 = (i >> 4) & 1 y0 = (x4 & x1) ^ x3 ^ (x2 & x1) ^ x2 ^(x1 & x0) ^ x1 ^ x0 y1 = x4 ^ (x3 & x2) ^ (x3 & x1) ^ x3 ^ (x2 & x1) ^ x2 ^ x1 ^ x0 y2 = (x4 & x3) ^ x4 ^ x2 ^ x1 ^ 1 y3 = (x4 & x0) ^ x4 ^ (x3 & x0) ^ x3 ^ x2 ^ x1 ^ x0 y4 = (x4 & x1) ^ x4 ^ x3 ^ (x1 & x0) ^ x1 o = y0 o |= y1<<1 o |= y2<<2 o |= y3<<3 o |= y4<<4 return o def test_bijectivity(nw): used = {} for i in range(0,1< %4x"%(i,r)) assert(r not in used) used[r]=1 print("nw=%d is bijective"%nw) def gen_latex_ref_table(nw): for i in range(0,1<> i) & 1)<<(width-1-i) return out def print_reversed_indexes(width): [print("0x%02x, "%(reverse(x,width)),end="") for x in range(0,1< for col in range(0,numcols): for row in range(0,numrows): b = 255 r = 255 if t[row][col]: r = max(0,255-(t[row][col] * 4+4)) g = r svg += '\n'%(col*10,row*10,r,g,b) svg += "" return svg def test_nw5_equations(): nw=5 for i in range(0,1< 0: if (n & 1 == 1): count += 1 n >>= 1 return count def diff_branch_number(sbox): n = get_sbox_size(sbox) out = 1<