martes, 9 de julio de 2013

Esteganografía [programa 4 [P4]]

Tarea Realizada para la Materia de Seguridad de la información y criptografía Esteganografía[Programa 4 [P4]].



Descripción


Ocultar un mensaje (secreto) dentro de otro (público), por ejemplo archivos de imagen, 


sonido, etc. 


Intentando no afectar a la estadística propiedades del mensaje público con el fin de evitar la 

detección.


Al ejecutar el código se necesita la siguiente sintaxis:

para  ocultar información:

python esteganografia.py imagen.ext -o

para  descifrar el mensaje oculto:

python esteganografia.py imagen.ext -d





de preferencia .ext = .png .tiff .bmp con los archivos con formato ,jpg no funcionara.

Implementando código para ocultar un mensaje de texto, en una imagen




from PIL import Image
from sys import argv

'''Convierte el Mensaje a binario'''
''' Convierte binario cada letra en el string, 
    omite los espacios 'b' y toma solo de 8-bits
    para representar el valor de la letra en binario'''
def strToNumToBin(string):
    '''recorre el string y va convirtiendo caracter en caracter en numero y despues en binario'''
    return [bin(ord(caracter))[2:].zfill(8) for caracter in string]  #devuelve el arreglo[]
    '''URL:http://code.activestate.com/recipes/578291-string-to-binary/ @Shawn'''

'''Convierte Binario a String'''    
def binToNumToStr(binario):
    '''recorrre la cadena binaria bit por bit convirtiendo en numero y despues en string :3'''
    return [chr(int(bit,2)) for bit in binario]                      #devuelve el arreglo[] :')
    '''Ejemplo :B binario (oviusly base 2) a numero y de numero a caracter
       probar en interprete de python :3
       >>chr(int('10011010',2))'''

def main():
    entrada= None
    comando= None
    try:
        '''Intenta tomar los argumentos de entrada'''
        imagen  = argv[1]
        comando = argv[2]
    except:
        '''Si no los recibio correctamente los pregunta interactivamente'''
        imagen  = raw_input('Archivo de Imagen: ')
        comando = raw_input('-d para decifrar el mensaje oculto \t  -o para ocultar mensaje: ')

    data = Image.open(imagen).convert('RGB')               #abre imagen de acuerdo a la entrada

    '''Comando para Ocultar el mensaje dentro de la imagen'''
    if comando == '-o':
        (w, h) = data.size                                  #tamanio de imagen
        resultado = Image.new('RGB', (w, h))                #asigna a resultado los  datos de la imagen original
        nuevo = resultado.load()                            #carga resultado a nueva imagen que generamos
        pixel = data.load()                                 #carga pixeles

        '''Entrada de Mensaje '''
        mensaje = raw_input('Mensaje a Ocultar:')
        bits=[]                            #cadenita de bits donde se alojara el numero en binario de el largo del mensaje
        
        for caracter in mensaje:           #checa cada caracter en el mensaje
            bits+= strToNumToBin(caracter) # y acumula cuantos lleva
        largo = len(bits)                  #con esto definimos el largo del mensaje
        cosabin= strToNumToBin(mensaje)#convierte el mensaje en binario
        
        c = 0                         #contador
        for x in xrange(w):           #recorre la imagen
            for y in xrange(h):       # base por altura :3 (w,h) ,i think
                r, g, b = pixel[x, y]   #los pixeles adquieren coordenadas
                if c < largo:         #recorremos el num binario del largo del mensaje bit por bit
                    if (int(bits[c]) % 2) == 0:  
                        if b % 2 == 1:#IMPAR cuando es impar c:
                            b = 0    #y si el canal azul es impar le asigna uno 
                            if b>254: #si se pasa de los 254 que es su color 
                                b=253 #le restamos para que este dentro de los rangos #no estoy segura que funcione ._.
                            elif b<0: #si no alcanza el minimo para ser un color
                                b=1   #se queda en 1 dentro de color azul
                    else:
                        if b % 2 == 0:#PAR
                            b = 1    #y si el canal azul es impar se le asigna uno 
                            if b>254: #si se pasa de los 254 que es su color 
                                b=253 #le restamos para que este dentro de los rangos #no estoy segura que funcione ._.
                nuevo[x, y] = r, g, b
                c += 1
        
        print bits#numero en binario del largo del mensaje
        print largo#numero del largo en decimal ._.
        #if cosabin == mensaje LOAD :D
        print cosabin#imprime el mensaje en binario
        print mensaje#imprime el mensaje original

        #procederiamos a ocultarlo :B
        resultado.save(imagen[:imagen.index('.')]+'copy'+imagen[imagen.index('.'):],'PNG')
        resultado.show()

    else:
        if comando == '-d':
            (w, h) = data.size                                  #tamanio de imagen
            #aqui debe de hacer lo contrario convertir binario a string
            #y luego comparar y Done... :3
            #print binToNumToStr(cosabin)
            #print "".join(binToNumToStr(cosabin))
            #for x in xrange(w):
            #for y in xrange(h):
            #r, g, b = pixel[x, y]
            #nuevo[x, y] = r, r, 0
            #b=1#aqui aun no se que pedo
            print 'ya'
        else:
            print 'comando no valido, empecemos de nuevo.'
            main()
            
if __name__ == '__main__':
    main()
    ''' Al llamar a al programa la sintaxis para que funcione
    a partir de argumentos de programa es la siguiente:
    esteganografia.py imagen.extencion -comando
    donde:
    extencion = .png /.tiff /.bmp 
    y comando = -o / -d '''





Código completo para descarga y visualización

Solamente Oculta Información.



Referencias



Esteganografía [programa 4 [P4]] - [hidden messages in images of kittens :3]


-.-
Imagen 0


:o
Imagen 1

Imagen 2
Imagen 3


Imagen 4


Imagen 5







jueves, 4 de julio de 2013

Firmas Digitales implementando RSA para la autenticacion [Programa 3 [P3]]

Tarea Realizada para la Materia de Seguridad de la información y criptografía implementar un repositorio de claves publicas (public Key's) para el intercambio de claves que utiliza firmas digitales basado en RSA[Programa 3 [P3]].


miércoles, 3 de julio de 2013

Implementación del RSA en Python,mediante sistema cliente-servidor con sockets

Tarea Realizada para la Materia de Seguridad de la información y criptografía Implementar RSA para validar la autenticacion en Python  mediante cliente-servidor con sockets,[Programa 2 [P2]]



Algoritmo RSA, comunicación de Bob y Alice:

Generar n = p × q, que ambos p y q sean primos.
             n\  se usa como el módulo para ambas claves, pública y privada

Bob realiza el cifrado(e, n): e es la clave publica (public key from Alice);  c = m^e mod n.
          e (entero positivo menor que ndebe de ser relativamente primo (coprimo) con ɸ(n) y menor que esta.

Alice decifra(d, n): es la clave privada(private key from Alice only she knows); m = c^d  mod n.
          de-1\  es dividido exactamente por ɸ (n)

Requisito: e × d  1 mod ɸ (n);
         ɸ(n) = (p - 1) × (q - 1)
m^e × d  m mod debido al teorema de Euler.

Alice envía a Bob una caja con una cerradura abierta, de la que solo Alice tiene la llave. Bob recibe la caja, escribe el  mensaje, lo pone en la caja y la cierra con su cerradura (ahora Bob no puede leer el mensaje). Bob envía la caja a Alice y ella la abre con su llave. En este ejemplo, la caja con la cerradura es la «clave pública» de Alice, y la llave de la cerradura es su «clave privada».


Descripcion:


Programa en Python que realiza el protocolo de la comunicación entre Alice y Bob utilizando el algoritmo RSA para cumplir con la autenticacion:

para este caso (cifrado) 
F(x) = m^e mod n ,(decifrado) F(x) 

m = c^d  mod n
, (la funcion que ambas partes de la comunicación tendran sera la del ejemplo anterior ).


El host envía a Alice una entrada al azar.
m
Alice realiza algo basado en esta entrada, y 
encripta el resultado con su clave privada.

m^d mod n

El servidor descifra con la clave pública de Alice, 
calcula, y se compara.

m = c^e  mod n.



Si coincide, Alice es de confianza para entrar en el host.
Alice también puede desafiar al anfitrión de manera similar para poder 

confiar en él.

CÓDIGO 
PANTALLAS 

Mejoras Futuras
Terminar el programa para cumplir con la siguiente tarea.


Referencias

martes, 2 de julio de 2013

Alice, Bob y Eve (Diffie–Hellman key exchange) [Reporte 1 [R1]]


Tarea Realizada para la Materia de Seguridad de la información y criptografía Protocolos [Reporte 1 [R1]]

Protocolo:
1- Alice y Bob deciden públicamente un primo p y un generador g ∈ Zp. (que pertenezca al grupo Zp)
2- Alice genera x envía f(X) a Bob,    f(X) = g^x mod p.
3- Bob genera y envía f(Y) a Alice,    f(Y) = g^y mod p.
4- Alice calcula s = f(Y)^x mod p
5- Bob calcula s = f(X)^y mod p
6- Alice y Bob ahora comparten un secreto s. (Esto se debe a que x*y es lo mismo que y*x. Así que alguien que conocía a estos dos números enteros privados también podrían haber calculado s de la siguiente manera:
 s =  (g ^x*y mod p) mod p
Tando Alice y Bob han llegado al mismo valor, porque
(g^x)^y    &     (g^y)x son iguales mod p            

Utilizando el metodo que vimos en clase
def potmod(x,pot,mod):#x numero, pot potencia, mod si es binario es 2 :l          
    bi=pot
    res=1
    temp=x
    while bi >0:
        if bi %2 ==1:
            res=(res*temp)%mod
        temp=(temp*temp)%mod
        bi= bi >> 1
    return res




y para comprobar:


La intervención de Eve:
Eve tiene que realizar operaciones prueba con los datos que ella conoce los cuales son:
 p=11                       g=3              f(X)=5            f(Y)=3
con los cuales realizara operaciones prueba para encontrar los supuestos valores de x y lo que se tiene que hacer para descubrir la clave secreta que hay entre Alice y Bob
Kf(Y)^x mod  = f(X)^y mod 
es lo siguiente:
tomar el generador elevándolo a números prueba iniciando en 1 realizando modulo del 11:
R= 3^ n  mod  11
hasta que sea 5 o 3:
 3^1 mod 11= 3
3^2 mod 11= 9
3^3 mod 11= 5
3^4 mod 11= 4
y tomando los exponentes que dieron al resultado se realiza el calculo de K

K= 3^3 mod 11      =        5^1 mod 11 
K=5

cuando Eve tiene la clave con la que ellos logran obtener el mensaje del otro ella puede escuchar todo lo que Alice y Bob se envian.




"Toda la seguridad es inherente en el conocimiento de la clave y ninguna es inherente en el conocimiento de la algoritmo ".

domingo, 30 de junio de 2013

Pruebas estadísticas de aleatoriedad [programa 1 [P1]

Tarea Realizada para la Materia de Seguridad de la información y criptografía  [programa 1 [P1]]

Se realizaron pruebas estadísticas de aleatoriedad al resultado de la generación de claves de números aleatorios del programa One-time Pad [T1] (de la entrada anterior) para saber si cumple con las características de datos generados aleatoriamente:
  • Unpredictable        (Impredecible) 
  • Uncompressible    (Incompresible)   
  • Unreproducible     (Irreproducible)
Si los resultados de las pruebas son satisfactorios, es seguro y , si es seguro, resiste ataques, si los resultados son malos y la generación de números realmente no es aleatoria, podremos atacar nuestro propio One-Time Pad.

Para llevar a cabo las pruebas se realizaran generadores de números aleatorios en diferentes lenguajes, para el experimento también se realizaron generadores de números pseudo-aleatorios, utilizando el Método Congruencial Mixto:

Donde se utilizaran los siguientes parámetros de entrada:

X0 = la semilla (X0 > 0), las semilla tienen que ser mayor a 0.
a= el multiplicador (a>0), estas variables preferiblemente que no tengan divisores en común.
c= constante aditiva (c>0), pueden ser por ejemplo números primos.
m= el modulo (m>X0  , m>a y m>c), el modulo preferentemente mayor a todas las variables.

Los códigos los podran ver en las siguientes ligas:
Numeros aleatorios utilizando funciones rand():
Aleatorio.java                                            aleatorio.c 
aleatorio.py                                             aleatorio.rb
Generadores de Numeros PseudoAleatorios:
Generador.java                                        generador.py                             


Se Utilizó la Prueba de Frecuencias entre ciertos rangos, consiste en generar N números aleatorios y agruparlos por frecuencias y estas se comparan con su valor esperado mediante la siguiente formula:
 VEi=N/M
La sumatoria de las se compara contra el valor de la Tabla de Distribución Ji.
utilizando α = 0.05 y grados de libertad de N-1 (gld: 8).

X²=(VE-VO)²/ VO
Pruebas aplicadas a el generador de numeros pseudoaleatorios:


Prueba de Frecuencias:



También se realizó la prueba de Corridas, una corrida es una sucesión de eventos similares seguidos y precedidos por eventos diferentes:

1000000001  <-- Corrida de longitud k 
                                                           k                                                                                            
donde   n[i]>n[i-1]
entonces   cadena[i] = '0'
de lo contrario cadena[i] ='1'

.382           .421          .126          .328          .421          .638          .431          .126           .207
cadena[]:
0                  1               0               0               0               1               1                  
Longitud de Corrida:
->        1                  1                               3                                           2                         1

en la que si  cadena[i]es igual a cadena[i+1]
entonces imprime cadena[i],veces++
si no son iguales veces = 0,veces++
e imprime cadena[i],veces.

ya que se tiene las longitudes de corrida en una lista de las veces que se repitió se podrá utilizar la sumatoria de los datos en el calculo de la x².
(para este ejemplo):
k

VO
1
3
2
1
3
1
4
0
la prueba implica determinar las frecuencias de corridas de distinta longitud y comparar con sus valores esperados mediante el calculo de x²

valor esperado:
VE(k)=2[(k²+3k+1)N-(k³+3k²-k-4)] /(k+3)!
Para corridas de longitud k

valor de ji:
 X²=(VE-VO)²/ VO

La sumatoria de las x² se compara contra el valor de la Tabla de Distribución Ji.
utilizando α = 0.05 y grados de libertad de N-1 (gld: 8).

Σ x²  < ValorTabla  ...[Resultado Satisfactorio del Experimento]

Nota: En el ejercicio practico se realiza con muestras Grandes, en este ejemplo solo se utilizo una muestra de números aleatorios pequeña.

y continuación se muestran las corridas cuando se le realizan con la Prueba de Corridas.

_________Repeat__________________________
0
44
18
4
1
0
0
0
0
0
VE(k)=2[(k²+3k+1)N-(k³+3k²-k-4)] /(k+3)!
X²=(VE-VO)²/ VO
k= 1 VE= 41.75  x²=0.11505681818181818
k= 2 VE= 18.1  x²=5.555555555555714E-4
k= 3 VE= 5.147222222222222  x²=0.3290297067901234
k= 4 VE= 1.1095238095238096  x²=0.011995464852607721
Sumatoria de x²= 0.45663754538010487
Si FTablas > x²
 los numeros probablemente son aleatorios
karenalduncin@lilalduncin:~/modelado/crypto$

Salida Completa Aqui

y aqui se muestran los archivos antes y despues de comprimirlos.


karenalduncin@lilalduncin:~/modelado/crypto/keys$ ls -l
total 24
-rw-rw-r-- 1 karenalduncin karenalduncin 1098 jul  1 04:26 c.dat
-rw-rw-r-- 1 karenalduncin karenalduncin 1060 jul  1 04:29 Genjava.dat
-rw-rw-r-- 1 karenalduncin karenalduncin 1506 jul  1 04:30 genpython.dat
-rw-rw-r-- 1 karenalduncin karenalduncin 1931 jul  1 04:26 java.dat
-rw-rw-r-- 1 karenalduncin karenalduncin 1500 jul  1 04:27 python.dat
-rw-rw-r-- 1 karenalduncin karenalduncin 1798 jul  1 04:28 ruby.dat
karenalduncin@lilalduncin:~/modelado/crypto/keys$



karenalduncin@lilalduncin:~/modelado/crypto/keys$ ls -l
total 24
-rw-rw-r-- 1 karenalduncin karenalduncin 431 jul  1 04:26 c.dat.gzcalc
-rw-rw-r-- 1 karenalduncin karenalduncin 499 jul  1 04:29 Genjava.dat.gz
-rw-rw-r-- 1 karenalduncin karenalduncin 732 jul  1 04:30 genpython.dat.gz
-rw-rw-r-- 1 karenalduncin karenalduncin 972 jul  1 04:26 java.dat.gz
-rw-rw-r-- 1 karenalduncin karenalduncin 745 jul  1 04:27 python.dat.gz
-rw-rw-r-- 1 karenalduncin karenalduncin 900 jul  1 04:28 ruby.dat.gz
karenalduncin@lilalduncin:~/modelado/crypto/keys$

Las diferencias de los archivos ya comprimidos algunas como en leguaje ruby y python y java son casi del 50% ,y en los archivos que fueron con generadores fue aun mayor el porcentaje lo que significa que no son numeros confiablemente aleatorios, en el que el porcentaje de comprimido fue aun mayor al 50% fue solamente en C.

Futuras Mejoras:
El método para sacar la longitud de corrida y pruebas de frecuencias necesita mejorarse ya que aun no funciona al 100%,

Referencias:

Valores Críticos de la Distribución Ji Cuadrada (x²), Facultad Regional Mendoza.
URL del Documento de Consulta

Carlos Marquez
Generación de Números Pseudoaleatorios U4, Febrero 2012.
URL del Documento de Consulta

Ruby Tutorial
http://rubytutorial.wikidot.com/