Buenas, estoy recien metiendome en esto de la Criptografía (creo que deje pasar mucho tiempo), antes de ponerme a estudiar y estudiar decidí hacer un pequeño algoritmo personal y romperlo, pero fracase, realmente no se me ocurre como romper mi pequeño y básico algoritmo.
Es un metodo simetrico por contraseña, en realidad se puede usar un archivo como contraseña lo que sea. Esto lo hice originalmente en PHP por que justo me pidieron algo para encriptar los datos de un server a otro sin instalar ninguna extención, y como las clases que encontre no me gustaron hice la mia propia, pero el tema es asi:
Primero agarro la "llave" que puede ser una contraseña corta o un algo mas largo, en el caso de los datos que mando de server a server lo hago con un archivo que genere de random:
$ dd if=/dev/random of=key.kry bs=1024 count=5
primero agarramos el contenido a encriptar y le sumamos una cadena con metadata, la hora exacta de creación, el tamaño en bytes del contenido y un hash md5 de estos 2 datos para firmarlos, eso se lo sumo al contenido dejandolo:
[metadata(128Bytes)][contenido]
Luego (opcionalmente) a todo eso lo comprimo con gzip (sin cabeceras ni nada) y termino teniendo un contenido binario.
Luego, como va encriptando en bloques, saco la cantidad de bloques, de entre 1 y 32 bytes y relleno lo que falta con caracteres al azar para crear algo de suciedad:
[metadata(128B)][contenido][suciedad]
---------------------
Divisible por el tamaño de bloques
una vez hecho esto, saco un checksum de todo con sha256 (64 bytes) que van a quedar al principio del archivo.
A la vez genero un sha512 (128 Bytes) del checksum del contenido sumado (como string) un sha512 de la llave, algo que en php seria:
hash('sha512', $cheksum . hash('sha512',$key) );
Al resto empiezo a hacer la magia:
Voy por bloques (supongamos que de 8):
------- <- basura
Hola mun do cruel ld4fkaM2
--------|--------|--------
A B C
Luego aplico un metodo del cesar, pero basandome en los caracteres que tengo del hash que genere con el contenido y la llave, supongamos que tengo
a4bxta33....
lo que hago (en ese orden) es sumarle el valor del char al char original:
Hola mun
a4bxta33
Ahi obtendria nuevos bytes.
Y para que no pueda desencriptar el contenido sacando el patron de suma de bytes, desordeno:
Del recorrido que hago al hash aparte de sacar un byte para sumarle al original, saco 4 bytes para generar un número (con crc32) que uso de semilla para la funcion rand, de esa forma obtengo una serie de numeros (del tamaño del bloque) no repetidos, que en un array podrian quedar asi:
[0] = 1
[1] = 3
[2] = 5
[3] = 2
[4] = 7
[5] = 4
[6] = 6
[7] = 0
Luego con este nuevo orden desordeno el bloque:
Hola mun
13527460
"nHaomlu "
OjO, aca se los muestro en claro, pero recuerden que a esos caracteres se les sumaron otros, por lo que el resultado (aun encriptando texto) seguramente terminaria siendo binario.
Bueno, par revertir esto y decodificarlo, obviamente, necesito de el hash sha512 que genero con el checksum y la llave, el cheksum esta en la cabecera:
[cheksum(64B)][contenido encriptado]
Eso para pasarlo por XML lo encodeo en base64, pero supongo que eso es obvio.
La verdad no puedo auto romper el método, pense en todo tipo de estadística pero no se me ocurre nada. Si alguno me da los primeros pasos para romper estos algoritmos se lo agradesco.
Aca un ejemplo:
Este está encritado con una contraseña simple, en bloques de 8 bytes, se puede sacar por fuerza bruta, pero obviamente no es la idea:
Codigo
Exos3 Julio 2010 - 2:47am
Bueno dejo el código fuente de la clase en PHP:
http://pastebin.com/VknuHzDX
Para los que sepan C seguro que van a saber entender el codigo.
Me pondre a estudiar eso entonces
Exos2 Julio 2010 - 11:19pm
Bueno la idea de publicar el método aca era para saber precisamente que comenzar a leer :-)
Estoy con poco tiempo, pero voy a ver si paso el codigo a C (asi lo entienden mejor aca) y cuando termine de pulirla hiba a publicar la clase.
Gracias por el empujon, la verdad que busque las soluciones mas simples para evitar metodos estadisticos, hasta los caracteres aleatoreos basura al final estan para que el codigo final no se repita nisiquiera en contenidos originales identicos con keys identicas, si se encripta 2 veces el mismo archivo con la misma key, se obtendrian 2 contenidos finales diferentes, inclusive los 64 primeros bytes del checksum.
Ok, ya me imaginaba
salarin (no verificado)2 Julio 2010 - 10:01pm
Ok, ya me imaginaba que no lo habia entendido bien. Ahora ya no me parece debil.. ;)
La mayoría de algoritmos de cifrado hacen sustituciones, rotaciones y permutaciones a ser posible de forma no simétrica y no lineal. El tuyo tiene sustituciones (aunque lineales) y permutaciones aleatorias asi que no son simetricas. La parte bonita es que la clave para cifrar cada mensaje cambia, asi que hace mas dificil utilizar muchos mensajes para encontrar la clave. Pero no se si tu sistema resistiria el criptoanalisis lineal. No se tanto de criptografia.
Saludos!
No se revela el hash usado
Exos2 Julio 2010 - 5:52pm
1- Mal: los cheksum no se suman, osea, no es un "c = a + b", sino que a la suma de la key con el cheksum del mensaje, se le saca otro checksum c = sha512( a + b ) entonces en la cabecera del mensaje se tiene el checksum del [metadata][mensaje][suciedad], solo con ese hash no se puede desencriptar nada, sino que se usa, para sacar OTRO hash partiendo de su suma con la contraseña o llave, y para validar una vez terminada la desencriptación, que el mensaje no alla sido alterado.
2- Como te dije del hash que esta al principio del mensaje no se saca nada, solo se usa para chequear la integridad del mensaje y generar el otro hash que si se usa. Los 4 bytes que uso para generar crc32 y usarlo de cemilla para la funcion rand, los saco de este ultimo hash generado.
Aparte el desorden es por bloque, por eso si ves el ejemplo era "Hola mun" que es el bloque de ejemplo de 8 bytes, asi que aunque se sepa el desorden de un bloque, habria que sacar el resto.
En fin, a simple vista, no se conoce la mitad del hash usado, ni tampoco el desorden.
Parece un cifrado debil..
salarin (no verificado)2 Julio 2010 - 1:42pm
Hola,
primero tengo un par de preguntas para asegurarme de que he entendido bien el proceso.
1. La clave que se utiliza para cifrar es un string formado por el checksum del mensaje (mas lo que has añadido) y el checksum de la clave. Además el checksum del mensaje lo añades al principio de forma que la mitad de la clave usada para cifrar es conocida. Y el resto está limitado a la longitud del checksum (y no a la longitud de la clave como deberia ser). ¿Es asi o lo he entendido mal?
2. Sobre el desorden "aleatorio" del final. El receptor necesita conocer ese desorden, por lo tanto, o es público o forma parte de la clave. Si es público no aporta mucho. No estoy seguro de si el crc que sacas de los 4 bytes de clave se puede obtener con el checksum que va al principio de la clave usada (es decir, el checksum del mensaje) o si forma parte de la segunda parte de la clave, es decir, la desconocida para el atacante.
Asumiendo que conocemos el desorden (punto 2) y que no se haya usado la opción del gzip, creo que el cifrado es bastante debil. En primer lugar, se conoce la mitad de la clave usada para cifrar (punto 1) y, no solo eso, sino que al ser cifrado cesar se puede usar para descifrar la mitad del mensaje!! Con la mitad del mensaje, si se trata de un texto, se puede extrapolar gran parte de la otra mitad. De forma que si el mensaje es suficientemente largo se podria obtener fácilmente los bytes de la mitad de la clave que desconocemos (el cheksum de la clave original). Además, se puede confirmar que se ha descifrado bien ya que se dispone del checksum del mensaje original.
En otras palabras, se podria obtener algo asi sin conocer la clave:
H*l* *u*d* *r*e*
La otra mitad se podria llegar a deducir, por ejemplo, con un modelo de trigramas del idioma usado. Un modelo de trigramas nos da la probabilidad de que 3 letras aparezcan juntas en un idioma.