Rabbit Cipher Stream
What is the Rabbit algorithm ?
This algorithm can be described as follows:
Rabbit needs a key of 128 bits and also can use a (iv) 64-bit input which is used in the iterations in the algorithm
Iv = It is a starting vector for different types of cryptographic systems. This can generate a randomly.
Both encryption and decryption use the substitution method to generate our XOR'ed ciphertext. Where the internal state of the algorithm is 512-bit and 8 states are divided by 32 bits each. Different states vectors are modified during the execution of the algorithm.
Diagram of the algorithm
Rabbit algorithm description:
First step: The key of 128 bits is genereted randomly and is divided into eight subkeys of 16 bits each and also the vector "IV" 64-bit is genereted
Second step: Initializing a vector "x" and a counter vector "c" with eight elemts
Third step: This step can be skipped but is recommended. Use the substitution method Xor vector for each counter using vector "IV"
Fourth step: This step is the most important of all, the endless cycle begins to generate different outputs "S" and use them to our substitution method Plaintext.
Variable g is used to cycle the different values of both counters as the vector x, and to generate new values for the vector x and iterating using "g" of the previous two iterations
Here the equations:
Some terms from here:
"<<" Means that there is a tour of some bit to the left
">>" Means that there is a tour of some bit to the right
Fifth step: Subsequently, to get the specific output for each output interaction, the following equations are performed:
The implementation code:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import random | |
##variables para diferentes usos | |
a = 0 | |
b = 0 | |
c = 0 | |
##variables para diferentes usos | |
#y = random.randint(0,1) | |
##llaves para algoritmo | |
key = [] ##llave inicial 128 bits | |
keym = [] ###Matriz de llaves | |
iv = [] ##vector de inicieacion | |
##llaves para algoritmo | |
text = [] ## | |
#c = [] ##vector de contadores | |
#x = [] ##vector para iteraciones | |
cont = 0 | |
#conti = 0 | |
#contf = 15 | |
fg = [] ##para realizar conversiones | |
g = 0 | |
num = 0 | |
gf = [] ##para la variable g | |
xf = [] ##vector de g | |
s = [] | |
##128 bits llaves## | |
for z in range(17): | |
key.append(hex(random.randint(0,10))) | |
##64 bits iv## | |
for z in range(9): | |
iv.append(hex(random.randint(0,10))) | |
#def rotar16(): | |
#def rotar32(): | |
##iniceacion del vector x y vector c | |
for j in range(8): | |
x.append([]) | |
c.append([]) | |
num = j % 2 | |
if num == 0: | |
a = bin(int((key[j]),16) + (1 % 8))[2:] | |
x[j].append(str(""+a+""+bin(int((key[j]),16))[2:]+"")) | |
a = bin(int((key[j]),16) + (4 % 8))[2:] | |
b = bin(int((key[j]),16) + (5 % 8))[2:] | |
c[j].append(str(""+a+""+b+"")) | |
else: | |
a = bin(int((key[j]),16) + (5 % 8))[2:] | |
x[j].append(str(""+a+""+bin(int((key[j]),16))[2:]+"")) | |
a = bin(int((key[j]),16) + (1 % 8))[2:] | |
b = bin(int((key[j]),16))[2:] | |
c[j].append(str(""+b+""+a+"")) | |
#print "valor cadena 1 = ",str(bin(int(key[1],16))) | |
#print "valor cadena 2 = ",str(bin(int(key[2],16))) | |
#print "hex = ",hex(c[0][0]) | |
#print "int = ",int(str(bin(int(key[2],16)))[0]) | |
#a = 2 | |
#b = 0 | |
##iniceacion del vector x y c | |
##funcion para obtener el valor de g | |
def funcion(lugarx): | |
size1 = 0 | |
size2 = 0 | |
a = 0 | |
g = 0 | |
pasado = 0 | |
actual = 0 | |
cambio = 0 | |
lista = [] | |
y = 0 | |
g = pow((int(x[lugarx][0],2) + int(c[lugarx][0],2)),2) | |
size1 = len(str(bin(g)[2:])) | |
cont = 0 | |
size1 = size1 - 1 | |
for y in range(size1 + 1): | |
lista.append(str(bin(g)[2:])[y]) | |
size2 = len(lista) | |
while cont <= size1: | |
b = size1 | |
while a == 32: | |
b = b + 1 | |
a = a + 1 | |
if b >= size1: | |
b = 0 | |
a = 0 | |
#print "valor de cont",str(g)[cont] | |
pasado = str(bin(g)[2:])[b] | |
actual = str(bin(g)[2:])[cont] | |
lista[b] = lista[cont] | |
lista[cont] = pasado | |
cont = cont + 1 | |
#print "valor dle contador=",cont | |
cont = 0 | |
for cont in range(size1): | |
if str(bin(g)[2:])[cont] == str(lista[cont]): | |
fg[lugarx].append(str(0)) | |
else: | |
fg[lugarx].append(str(1)) | |
cont = 0 | |
hahaha = 0 | |
size1 = len(fg[lugarx]) | |
valor = 0 | |
for cont in range(size1): | |
#print cosa[ahaha] | |
if fg[lugarx][cont] == '1': | |
valor=2*valor+1 | |
size1 -=1 | |
else: | |
valor=2*valor | |
# apartida = partida + 1 | |
#partida = partida + 1 | |
return valor | |
##funcion para obtener el valor de g | |
##iteraccion del ciclo una vuelta completa | |
for k in range(8): | |
fg.append([]) | |
#algo = funcion(k) | |
gf.append(funcion(k)) | |
#fg.append( ) | |
#print fg[0] | |
resta = 0 | |
a = 0 | |
b = 0 | |
suma = 0 | |
for k in range(8): | |
xf.append([]) | |
resta = k - 1 | |
if resta < 0: | |
a = 8 + resta | |
b = 8 + resta | |
suma = gf[a] +gf[b] + gf[k] | |
xf[k].append(str(suma)) | |
##iteraccion del ciclo una vuelta completa | |
#print bin(int(xf[0])) | |
#print xf[1] | |
a = 0 | |
b = 5 | |
cont = 0 | |
binari1 = 0 | |
binario2 = 0 | |
##apartado para sacar las cadenas S en una vuela | |
for k in range(8): | |
s.append([]) | |
size1 = len(str(bin(int(xf[a][0]))[2:])) | |
size2 = len(str(bin(int(xf[b][0]))[2:])) | |
binario1 = str(bin(int(xf[a][0]))[2:]) | |
binario2 = str(bin(int(xf[b][0]))[2:]) | |
for j in range(16): | |
if size2 <= j: | |
if binario1[j] == '0': | |
s[k].append(str(0)) | |
else: | |
s[k].append(str(1)) | |
else: | |
if size1 <= j: | |
if binario2[j] == '0': | |
s[k].append(str(0)) | |
else: | |
s[k].append(str(1)) | |
else: | |
if binario1[j] == binario2[j]: | |
s[k].append(str(0)) | |
else: | |
s[k].append(str(1)) | |
cont = cont + 1 | |
if cont == 2: | |
a = a + 2 | |
cont = 0 | |
##apartado para sacar las cadenas S en una vuela | |
##imprecion de las cadenas s | |
for k in range (8): | |
print "VAlor final : ",s[k] | |
##imprecion de las cadenas s | |
Here is a picture of a first round generating 8 blocks of "Si"
This algorithm has different strengths and weaknesses:
One of the biggest advantages of this algorithm is the use of a 128-bit key that grabs one of the best sytems about execution speed, different blocks also constantly change. The attacks is more difficult to perform in against a random key.
The strength is the division of the keys in 8 to modify the state variables, for different types of attacks such as statistical and brute force
http://www3.iam.metu.edu.tr/iam/images/6/6a/Tarkanolcuogluterm.pdf
http://cr.yp.to/streamciphers/rabbit/desc.pdf
https://tools.ietf.org/html/rfc4503
http://reference.kfupm.edu.sa/content/r/a/rabbit__a_new_high_performance_stream_ci_66630.pdf
http://en.wikipedia.org/wiki/Initialization_vector
Me hubiera gustado un ejemplo más bien paso por paso y un poco más sobre lo de ataques. Van 6 pts.
ResponderEliminar