La tarea 2 es checar si las claves que genera nuestro otp (one time pad) realmente es aleatoria.
La clave evaluada fue la siguiente:
Esta clave es generada del programa anterior con el siguiente código:
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
def generar_claves(): | |
k='' | |
for m in range(10): | |
s = binary(randint(0,255)) | |
k += s | |
return k |
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
def leer_archivo(archivo,test): | |
archivo = open(archivo, 'r') | |
numero='' | |
for i in archivo.readline().strip(): | |
numero+=i | |
# print numero | |
#print (len(numero)) | |
if test==3: | |
print numero | |
return numero | |
else: | |
numero = map(int,numero) | |
numero = array(numero) | |
return numero |
Primero yo realice un test sencillo que se llama Monobit:
Monobit
Detecta los ceros y los unos que se encuentran en la cadena binaria, sustituyendo los ceros que encuentre por -1, asi realizando una suma. La aparición de ceros y unos en la secuencia global deberan de ser igualmente probables
Datos a tener:
n = tamaño de la clave binaria
ε =La secuencia de bits que se esta probando
Procedimiento:
1. Como mencione se buscan los ceros y se sustituyen por -1y se realiza una suma, ejemplo:
lista=[1,1,0,0,1,0,1]
quedaría:
lista=[11,-1-1,1-11]
y se realiza la suma de la lista
2-Se calcula la prueba estadística:
3. Se calcula p_value ( erfc es la función error complementaria.)
4.Si P - value > 0.01, la secuencia es aleatoria.
Código:
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
def monobit(lista): | |
print 'Test Monobit' | |
n=len(lista)#tam de lalista | |
for m in range(n):# recorre la lista | |
if lista[m]==0: | |
lista[m]= -1 # Si encuentra un 0 en la lista lo hace -1 | |
sn=sum(lista) # realiza la suma | |
s_obs=abs(sn)/math.sqrt(n) #calcula prueba estadistica | |
p_value= math.erfc(s_obs/math.sqrt(2)) #calcula p_value | |
if p_value > 0.01: | |
print ">> Frequency Test: PASSED -->", p_value | |
else: | |
print ">> Frequency Test: NOT PASSED --> ", p_value |
Captura de pantalla de la prueba:
También utilice otras dos pruebas que es la de Poker y la de frecuencia de Bloques
Frecuencia de Bloques
En la prueba de bloques los ceros y unos deberan de ser igualmente probables.
Datos:
n - largo de la secuencia
m - el largo de cada bloque
ε - secuencia de bits generada
Recomendaciones:
Procedimiento:
1. Se parte la prueba e bloques de un cierto tamaño se calcula de la siguiente manera:
2. Se determina la proporción de unos:
3. Se calcula la chi2=X2
4. Se calcula la p_value:
Código
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
def frequency_block(list): | |
print 'Test Block' | |
n = len(list) | |
M = 0.01*n | |
N =int( n/M) | |
blocks = [] | |
X2 = 0 | |
print type(blocks) | |
i=0 | |
while(len(blocks) != N): | |
blocks.append(list[i:(i+M)]) | |
i = i + M | |
sumas = [] | |
for i in range(len(blocks)): | |
sumas.append(0) | |
for j in range(len(blocks[i])): | |
sumas[i] = sumas[i] + blocks[i][j]/float(M) | |
for i in range(N): | |
X2 = X2 + math.pow((sumas[i] - .5), 2) | |
X2 = X2 * 4*M | |
df = M - 1 | |
p_value = chi2.cdf(X2, df) | |
if p_value < 0.01: | |
print "Frequency Test with Blocks: NOT PASSED" | |
else: | |
print "Frequency Test with Blocks: PASSED" |
Captura de pantalla
Prueba de Póker
Lo que hace la prueba de póker es dividir la clave en numeros de 4 bist, por ejemplo si yo tengo esta:
0101000001100011
se divide de la siguiente manera :
0101 0000 0110 0011
entonces como se divide en 4 hay 16 posibles resulados que pueden salir y esos 16 resultados son contados las veces que estan o el número de frecuencias de cada uno.
La formula que se realiza es la siuiente:
en donde:
m = es el tamaño de la división de la secuencia en este caso 4
n = lóngitud o tamaño de la secuencia binaria
k = es la división de m entre n
Pasos:
1. Se divide la serie de número binarios en secciones de 4 numeros (0000).
2. Se buscan las frecuencias de los 16 diferentes numeros que se pueden encontrar
3. La frecuencia se eleva al cuadrado
4. Se realiza lo que es la ecuación anterior:
x2=(16/k)(frecuencias al cuadrado)-k
La prueba se pasa cuando 1.03 < x < 57.4
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
def poker(arch): | |
n=len(arch) # Tam de la cadena binaria | |
m=4 #longitud de los bloques | |
numeros=list()#lista de separaciones de numeros de 4 | |
frecuencia=list() #lista para guardar las frecuencias | |
y = n/m #cantidad de grupo de 4 | |
for i in range(y): # recorre la cantidad de grupos de 4 | |
numeros.append(arch[4*i:4+(4*i)]) #los agrega a la lista numeros | |
for i in range(16): #realiza la lista de los 16 posibles numeros | |
z=bin(i)[2:].zfill(4) | |
frecuencia.append((numeros.count(z))**2) #cuenta las frecuencias de los numeros | |
print frecuencia | |
x = 0 | |
a= 16.0/y | |
x = (a)*(sum(frecuencia)-y) #realiza la operacion | |
print 'x---->', x | |
if 1.03 < x < 57.4: | |
print 'Poker Test: PASSED' | |
else: | |
print 'Poker Test: NOT PASSED' | |
Con otra cantidad de claves:
Monobit
Frecuencia de Bloques
Poker test
La clave pasa las pruebas eso quiere decir que es segura.
Referencias:
Link1
Link2
LInk3