Rabbit-Cipher/Rabbit_Cipher.py

214 lines
7.9 KiB
Python

from Rabbit_Util import *
class Rabbit(object):
def __init__(self,key,iv):
self.ctx=Rabbit_ctx();
self.set_key(key);
if(len(iv)):
self.set_iv(iv);
def g_func(self,x):
x=x&0xffffffff
x=(x*x)&0xffffffffffffffff
result=(x>>32)^(x&0xffffffff)
return result
def set_key(self,key):
#generate four subkeys
key0=int(key[0:4][::-1].encode("hex"),16)
key1=int(key[4:8][::-1].encode("hex"),16)
key2=int(key[8:12][::-1].encode("hex"),16)
key3=int(key[12:16][::-1].encode("hex"),16)
s=self.ctx.m
#generate initial state variables
s.x[0]=key0
s.x[2]=key1
s.x[4]=key2
s.x[6]=key3
s.x[1]=((key3<<16)&0xffffffff)|((key2>>16)&0xffff)
s.x[3]=((key0<<16)&0xffffffff)|((key3>>16)&0xffff)
s.x[5]=((key1<<16)&0xffffffff)|((key0>>16)&0xffff)
s.x[7]=((key2<<16)&0xffffffff)|((key1>>16)&0xffff)
#generate initial counter values
s.c[0]=ROTL32(key2,16)
s.c[2]=ROTL32(key3,16)
s.c[4]=ROTL32(key0,16)
s.c[6]=ROTL32(key1,16)
s.c[1]=(key0&0xffff0000) | (key1&0xffff)
s.c[3]=(key1&0xffff0000) | (key2&0xffff)
s.c[5]=(key2&0xffff0000) | (key3&0xffff)
s.c[7]=(key3&0xffff0000) | (key0&0xffff)
s.carry=0
#Iterate system four times
for i in range(4):
self.next_state(self.ctx.m);
for i in range(8):
#modify the counters
self.ctx.m.c[i]^=self.ctx.m.x[(i+4)&7]
#Copy master instance to work instance
self.ctx.w=self.copy_state(self.ctx.m)
def copy_state(self,state):
n=Rabbit_state()
n.carry=state.carry
for i,j in enumerate(state.x):
n.x[i]=j
for i,j in enumerate(state.c):
n.c[i]=j
return n
def set_iv(self,iv):
#generate four subvectors
v=[0]*4
v[0]=int(iv[0:4][::-1].encode("hex"),16)
v[2]=int(iv[4:8][::-1].encode("hex"),16)
v[1]=(v[0]>>16) |(v[2]&0xffff0000)
v[3]=((v[2]<<16) |(v[0]&0x0000ffff))&0xffffffff
#Modify work's counter values
for i in range(8):
self.ctx.w.c[i]=self.ctx.m.c[i]^v[i&3]
#Copy state variables but not carry flag
tmp=[]
for cc in self.ctx.m.x:
tmp+=[cc]
self.ctx.w.x=tmp
#Iterate system four times
for i in range(4):
self.next_state(self.ctx.w);
def next_state(self,state):
g=[0]*8
x=[0x4D34D34D, 0xD34D34D3, 0x34D34D34]
#calculate new counter values
for i in range(8):
tmp=state.c[i]
state.c[i]=(state.c[i]+x[i%3]+state.carry)&0xffffffff
state.carry=(state.c[i]<tmp)
#calculate the g-values
for i in range(8):
g[i]=self.g_func(state.x[i]+state.c[i])
#calculate new state values
j=7
i=0
while(i <8):
state.x[i]=(g[i] + ROTL32(g[j], 16) + ROTL32(g[j-1], 16))&0xffffffff
i+=1
j+=1
state.x[i]=(g[i] + ROTL32(g[j & 7], 8) + g[j-1])&0xffffffff
i+=1
j+=1
j&=7
def crypt(self,msg):
plain=""
l=len(msg)
c=self.ctx
x=[0]*4
start=0
while(True):
self.next_state(c.w)
for i in range(4):
x[i]=c.w.x[i<<1]
x[0]^=(c.w.x[5]>>16)^(c.w.x[3]<<16)
x[1]^=(c.w.x[7]>>16)^(c.w.x[5]<<16)
x[2]^=(c.w.x[1]>>16)^(c.w.x[7]<<16)
x[3]^=(c.w.x[3]>>16)^(c.w.x[1]<<16)
b=[0]*16
for i,j in enumerate(x):
for z in range(4):
b[z+4*i]=0xff&(j>>(8*z))
for i in range(16):
plain+=chr(ord(msg[start])^b[i])
start+=1
if(start==l):
return plain
def st(b):
a=""
for x in b:
a+=chr(x)
return a
def check(key,iv,out):
msg="\x00"*48
cipher=Rabbit(key,iv)
data=cipher.crypt(msg)
assert data==out
if __name__ == "__main__":
#some test samples
key1 = [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ];
key2 = [ 0xAC, 0xC3, 0x51, 0xDC, 0xF1, 0x62, 0xFC, 0x3B,
0xFE, 0x36, 0x3D, 0x2E, 0x29, 0x13, 0x28, 0x91 ];
key3 = [ 0x43, 0x00, 0x9B, 0xC0, 0x01, 0xAB, 0xE9, 0xE9,
0x33, 0xC7, 0xE0, 0x87, 0x15, 0x74, 0x95, 0x83 ];
iv1 = [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ];
iv2 = [ 0x59, 0x7E, 0x26, 0xC1, 0x75, 0xF5, 0x73, 0xC3 ];
iv3 = [ 0x27, 0x17, 0xF4, 0xD2, 0x1A, 0x56, 0xEB, 0xA6 ];
out1 = [ 0x02, 0xF7, 0x4A, 0x1C, 0x26, 0x45, 0x6B, 0xF5,
0xEC, 0xD6, 0xA5, 0x36, 0xF0, 0x54, 0x57, 0xB1,
0xA7, 0x8A, 0xC6, 0x89, 0x47, 0x6C, 0x69, 0x7B,
0x39, 0x0C, 0x9C, 0xC5, 0x15, 0xD8, 0xE8, 0x88,
0x96, 0xD6, 0x73, 0x16, 0x88, 0xD1, 0x68, 0xDA,
0x51, 0xD4, 0x0C, 0x70, 0xC3, 0xA1, 0x16, 0xF4 ];
out2 = [ 0x9C, 0x51, 0xE2, 0x87, 0x84, 0xC3, 0x7F, 0xE9,
0xA1, 0x27, 0xF6, 0x3E, 0xC8, 0xF3, 0x2D, 0x3D,
0x19, 0xFC, 0x54, 0x85, 0xAA, 0x53, 0xBF, 0x96,
0x88, 0x5B, 0x40, 0xF4, 0x61, 0xCD, 0x76, 0xF5,
0x5E, 0x4C, 0x4D, 0x20, 0x20, 0x3B, 0xE5, 0x8A,
0x50, 0x43, 0xDB, 0xFB, 0x73, 0x74, 0x54, 0xE5 ];
out3 = [ 0x9B, 0x60, 0xD0, 0x02, 0xFD, 0x5C, 0xEB, 0x32,
0xAC, 0xCD, 0x41, 0xA0, 0xCD, 0x0D, 0xB1, 0x0C,
0xAD, 0x3E, 0xFF, 0x4C, 0x11, 0x92, 0x70, 0x7B,
0x5A, 0x01, 0x17, 0x0F, 0xCA, 0x9F, 0xFC, 0x95,
0x28, 0x74, 0x94, 0x3A, 0xAD, 0x47, 0x41, 0x92,
0x3F, 0x7F, 0xFC, 0x8B, 0xDE, 0xE5, 0x49, 0x96 ];
out4 = [ 0xED, 0xB7, 0x05, 0x67, 0x37, 0x5D, 0xCD, 0x7C,
0xD8, 0x95, 0x54, 0xF8, 0x5E, 0x27, 0xA7, 0xC6,
0x8D, 0x4A, 0xDC, 0x70, 0x32, 0x29, 0x8F, 0x7B,
0xD4, 0xEF, 0xF5, 0x04, 0xAC, 0xA6, 0x29, 0x5F,
0x66, 0x8F, 0xBF, 0x47, 0x8A, 0xDB, 0x2B, 0xE5,
0x1E, 0x6C, 0xDE, 0x29, 0x2B, 0x82, 0xDE, 0x2A ];
out5 = [ 0x6D, 0x7D, 0x01, 0x22, 0x92, 0xCC, 0xDC, 0xE0,
0xE2, 0x12, 0x00, 0x58, 0xB9, 0x4E, 0xCD, 0x1F,
0x2E, 0x6F, 0x93, 0xED, 0xFF, 0x99, 0x24, 0x7B,
0x01, 0x25, 0x21, 0xD1, 0x10, 0x4E, 0x5F, 0xA7,
0xA7, 0x9B, 0x02, 0x12, 0xD0, 0xBD, 0x56, 0x23,
0x39, 0x38, 0xE7, 0x93, 0xC3, 0x12, 0xC1, 0xEB ];
out6 = [ 0x4D, 0x10, 0x51, 0xA1, 0x23, 0xAF, 0xB6, 0x70,
0xBF, 0x8D, 0x85, 0x05, 0xC8, 0xD8, 0x5A, 0x44,
0x03, 0x5B, 0xC3, 0xAC, 0xC6, 0x67, 0xAE, 0xAE,
0x5B, 0x2C, 0xF4, 0x47, 0x79, 0xF2, 0xC8, 0x96,
0xCB, 0x51, 0x15, 0xF0, 0x34, 0xF0, 0x3D, 0x31,
0x17, 0x1C, 0xA7, 0x5F, 0x89, 0xFC, 0xCB, 0x9F ];
check(st(key1), "",st(out1));
check(st(key2), "",st(out2));
check(st(key3), "",st(out3));
check(st(key1), st(iv1), st(out4));
check(st(key1), st(iv2), st(out5));
check(st(key1), st(iv3), st(out6));
print "pass all tests"