from sage.crypto.sbox import SBox
def bits2word(L): return L[0]*8+L[1]*4+L[2]*2+L[3]
def word2bits(W): return [(W//8)%2, (W//4)%2, (W//2)%2, W%2]
def xorbits(x,y): return (((x)+(y))%2)
def xor(L,M): return map(xorbits,L,M)
def int2state(i): return [((i//(2**(15-b)))%2) for b in range(16)]
def state2int(L): return sum([(L[b]*(2**(15-b))) for b in range(16)],0)
def randkey(): return int2state(getrandbits(16))
PP=[0,4,8,12,1,5,9,13,2,6,10,14,3,7,11,15]
def permbits(L): return [L[PP[i]] for i in range(16)]
def permbitsinv(L): return permbits(L)
def state2words(L): return [bits2word(L[0:4]), bits2word(L[4:8]),bits2word(L[8:12]), bits2word(L[12:16])]
def words2state(L): return sum(map(word2bits, L),[])
SB=SBox(14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7);
SBinv=SBox(14,3,4,8,1,12,10,15,7,13,9,6,11,2,0,5);
def substbits(L): return words2state(map(SB, state2words(L)))
def substbitsinv(L): return words2state(map(SBinv, state2words(L)))
def encryptround(L,K): return permbits(substbits(xor(L,K)))
def encryptfinalround(L,K1,K2): return xor(substbits(xor(L,K1)),K2)
def encrypt(L): return encryptfinalround(encryptround(encryptround(encryptround(L,k1),k2),k3),k4,k5)
def decryptround(L,K): return xor(substbitsinv(permbitsinv(L)),K)
def decryptfinalround(L,K1,K2): return xor(substbitsinv(xor(L,K2)),K1)
def decrypt(L): return decryptround(decryptround(decryptround(decryptfinalround(L,k4,k5),k3),k2),k1)