Sie sind auf Seite 1von 11

Memoria Practica 1

Alumno: Joaquin Cardoso Buzn

Practica 1 : Modos de operacin para cifrados en bloque


Se exponen en la siguiente memoria los modos de operacin de cifrados en bloque ECB, CTR y CBC junto con el efecto avalancha y canal con ruido pedidos a desarrollar en la prctica 1. Cabe mencionar antes de la exposicin de los distintos modos, que el algoritmo que utilizaremos para cifrar/descifrar los mensajes ser el AES128. -Ejercicio 0, Modo ECB: Para este modo se proporciona una implementacin y slo se pide el desarrollo de la clase principal donde se pone en prctica el modo de operacin. ste modo de operacin para cifrados en bloque opera de forma muy bsica. Divide el mensaje en bloques del mismo tamao (en nuestro caso 16 bytes) y cifra el mensaje con la clave que se proporciona. Para descifrar el mensaje divide el mensaje encriptado en bloques del mismo tamao y aplicamos el algoritmo de descifrado para recuperar el mensaje original. Podemos concluir aadiendo que ste tipo de cifrado es bastante inseguro ya que siempre se cifra con la misma clave el mensaje. En el siguiente trozo de cdigo podemos ver cmo operan los mtodos cifrar y descifrar en el modo de operacin ECB:
public class ModoECB { public static byte[] cifrar(byte[] key, byte[] msg){ byte[] mensajeCifrado = new byte[msg.length]; for(int i=0; i<msg.length; i+=AES128.TAM_BLOQUE_BYTES){ // Copiamos un bloque del mensaje, empezando en la posicin i. // Recordemos que los bloques tienen longitud 16 bytes. byte[] bloque_i = new byte[AES128.TAM_BLOQUE_BYTES]; System.arraycopy(msg, i, bloque_i, 0, AES128.TAM_BLOQUE_BYTES); // Ciframos el bloque byte[] bloqueCifrado = AES128. cifrarBloque(key, bloque_i); // Copiamos el bloque en la array que contendr el mensaje System.arraycopy(bloqueCifrado, 0, mensajeCifrado, i, AES128.TAM_BLOQUE_BYTES); } return mensajeCifrado; } public static byte[] descifrar(byte[] key, byte[] mensajeCifrado){ byte[] mensaje = new byte[mensajeCifrado.length]; for(int i=0; i<mensajeCifrado.length; i+=AES128.TAM_BLOQUE_BYTES){ // Copiamos un bloque del mensaje, empezando en la posicin i. // Recordemos que los bloques tienen longitud 16 bytes. byte[] bloque_i = new byte[AES128.TAM_BLOQUE_BYTES]; System.arraycopy(mensajeCifrado, i, bloque_i, 0, AES128.TAM_BLOQUE_BYTES); // Desciframos byte[] bloqueMensaje = AES128. descifrarBloque(key, bloque_i);

// Copiamos el bloque en la array que contendr el mensaje

System.arraycopy(bloqueMensaje, 0, mensaje, i, AES128.TAM_BLOQUE_BYTES); } return mensaje; } } -Ejercicio 1, Modo CTR: Para este modo se pide que se desarrolle su implementacin de forma que pueda aceptar mensajes de cualquier tamao, por lo que tendremos que desarrollar dos mtodos adicionales para introducir padding al mensaje para que su tamao sea mltiplo de 16 y otro para eliminar el padding del mensaje. ste modo de operacin utiliza un contador que se va incrementando de uno en uno, se cifra el contador con la clave y se hace xor con el bloque del mensaje original. Para descifrar el mensaje se vuelve a utilizar un contador que se va incrementando de uno en uno y se descifra el contador con la clave, para terminar haciendo xor con el bloque de mensaje cifrado.

En el siguiente trozo de cdigo podemos ver cmo operan los mtodos cifrar y descifrar en el modo de operacin CTR junto con los mtodos para aadir y quitar el padding:
public class ModoCTR { public static byte[] cifrar(byte[] key, byte[] msg){ msg = conPaddin(msg); byte[] mensajeCifrado = new byte[msg.length]; byte[] contador = new byte[AES128.TAM_BLOQUE_BYTES]; int tamaoPad = msg[msg.length-1]; for(int i=0; i<msg.length; i+=AES128.TAM_BLOQUE_BYTES){ // Damos valor al contador // Copiamos un bloque del mensaje, empezando en la posicin i. // Recordemos que los bloques tienen longitud 16 bytes. contador[contador.length-1]=(byte) i; byte[] bloque_i = new byte[AES128.TAM_BLOQUE_BYTES]; System.arraycopy(msg, i, bloque_i, 0, AES128.TAM_BLOQUE_BYTES); //Ciframos byte[] bloqueCifrado = AES128. cifrarBloque(key, contador); //Copiamos el bloque en el mensaje cifrado System.arraycopy(Util.xor(bloqueCifrado, bloque_i), 0, mensajeCifrado, i, AES128.TAM_BLOQUE_BYTES);

} mensajeCifrado[mensajeCifrado.length-1]=(byte) tamaoPad; return sinPaddin( mensajeCifrado); } public static byte[] descifrar(byte[] key, byte[] mensajeCifrado){ mensajeCifrado = conPaddin(mensajeCifrado); byte[] mensaje = new byte[mensajeCifrado.length]; byte[] contador = new byte[AES128.TAM_BLOQUE_BYTES]; int tamaoPad = mensajeCifrado[mensajeCifrado.length-1]; for(int i=0; i<mensajeCifrado.length; i+=AES128.TAM_BLOQUE_BYTES){ // Damos valor al contador

// Copiamos un bloque del mensaje, empezando en la posicin i. // Recordemos que los bloques tienen longitud 16 bytes. contador[contador.length-1]=(byte) i; byte[] bloque_i = new byte[AES128.TAM_BLOQUE_BYTES]; System.arraycopy(mensajeCifrado, i, bloque_i, 0, AES128.TAM_BLOQUE_BYTES); // Desciframos byte[] bloqueDescifrado = AES128. cifrarBloque(key, contador); //Copiamos el bloque en el mensaje descifrado System.arraycopy(Util.xor(bloqueDescifrado, bloque_i), 0, mensaje, i, AES128.TAM_BLOQUE_BYTES); } //Copiamos el tamao del paddin al final del mensaje mensaje[mensaje.length-1]=(byte) tamaoPad; return sinPaddin(mensaje); } public static byte[] conPaddin(byte[] msg){ //Guardamos en tamaoArray el tamao de debe tener el array con paddin int tamaoArray = msg.length + (16-(msg.length%16)); int tamaoPad = tamaoArray - msg.length; byte[] msgPadding = new byte[tamaoArray]; //Rellenamos con el tamao del pad for(int i=0;i<msgPadding.length;i++){ msgPadding[i]=(byte)(tamaoPad); } //copiamos el mensaje original System.arraycopy(msg, 0, msgPadding, 0, msg.length); return msgPadding; } public static byte[] sinPaddin(byte[] msgPad){ //Obtenemos el tamao del paddin que se encuentra al final de msgPad y damos tamao a msgSinP int tamaoPad = (int)(msgPad[msgPad.length-1]); byte[] msgSinP = new byte[msgPad.length-tamaoPad]; //Eliminamos el paddin copiando el mensaje en msgSinP System.arraycopy(msgPad, 0, msgSinP, 0, msgSinP.length); return msgSinP; } } -Ejercicio 2, Modo CBC bsico: Para este modo se pide que se desarrolle su implementacin bsica. ste modo de operacin es el ms potente de los tres estudiados. Utiliza un vector inicial con el que hace xor con el bloque del mensaje a cifrar. Lo obtenido en de la operacin xor se cifrar junto con la clave. Para descifrar el mensaje se dividir el mensaje en bloques y se descifrar el mensaje con la clave y para obtener el mensaje original se har xor con el vector iniciacin.

En el siguiente trozo de cdigo podemos ver cmo operan los mtodos cifrar y descifrar en el modo de operacin CBC bsico:
public static byte[] cifrar(byte[] key, byte[] msg){ byte[] vectorIniciacion = Util.hexStringToBytes("000102030405060708090A0B0C0D0E0F"); byte[] mensajeCifrado = new byte[msg.length]; for(int i=0; i<msg.length; i+=AES128.TAM_BLOQUE_BYTES){ // Copiamos un bloque del mensaje, empezando en la posicin i. // Recordemos que los bloques tienen longitud 16 bytes. byte[] bloque_i = new byte[AES128.TAM_BLOQUE_BYTES]; System.arraycopy(msg, i, bloque_i, 0, AES128.TAM_BLOQUE_BYTES); //Realizamos xor System.arraycopy(Util.xor(bloque_i, vectorIniciacion),0,bloque_i, 0, bloque_i.length); //Ciframos el bloque byte[] bloqueCifrado = AES128.cifrarBloque(key, bloque_i); //actualizamos el valor del VectorIniciacion y guardamos el bloque obtenido System.arraycopy(bloqueCifrado, 0, vectorIniciacion, 0, vectorIniciacion.length); System.arraycopy(bloqueCifrado, 0, mensajeCifrado, i, AES128.TAM_BLOQUE_BYTES); } return mensajeCifrado; } public static byte[] descifrar(byte[] key, byte[] mensajeCifrado){ byte[] vectorIniciacion = Util.hexStringToBytes("000102030405060708090A0B0C0D0E0F"); byte[] mensaje = new byte[mensajeCifrado.length]; for(int i=0; i<mensajeCifrado.length; i+=AES128.TAM_BLOQUE_BYTES){ // Copiamos un bloque del mensaje, empezando en la posicin i. // Recordemos que los bloques tienen longitud 16 bytes. //bloque_i para recorrer mensajeCifrado byte[] bloque_i = new byte[AES128.TAM_BLOQUE_BYTES]; System.arraycopy(mensajeCifrado, i, bloque_i, 0, AES128.TAM_BLOQUE_BYTES); //Desciframos byte[] bloqueCifrado = AES128.descifrarBloque(key, bloque_i); //Hacemos xor entre bloqueCifrado y vectorIniciacion para almacenar en mensaje //Actualizamos el vectorIniciacion System.arraycopy(Util.xor(bloqueCifrado, vectorIniciacion),0,mensaje, i, AES128.TAM_BLOQUE_BYTES);

System.arraycopy(bloque_i, 0, vectorIniciacion, 0, bloque_i.length); } return mensaje; } } -Ejercicio 3, Modo CBC con padding: Para este modo se pide que se desarrolle su implementacin de forma que pueda aceptar mensajes de cualquier tamao, por lo que tendremos que desarrollar dos mtodos adicionales para introducir padding al mensaje para que su tamao sea mltiplo de 16 y otro para eliminar el padding del mensaje. ste modo de operacin es el ms potente de los tres estudiados. Utiliza un vector inicial con el que hace xor con el bloque del mensaje a cifrar. Lo obtenido en la xor se cifrar junto con la clave. Para descifrar el mensaje se dividir el mensaje en bloques y se descifrar el mensaje con la clave y para obtener el mensaje original se har xor con el vector inicializacin. Antes de comenzar con el cifrado del mensaje se debe aadir el pandding al mensaje. En ste caso se ha utilizado el esquema de padding PKCS#5, PKCS#7: Si necesitamos N bytes de padding, usamos N veces el valor N. Una vez descifrado el mensaje que proceder a eliminar el padding del mensaje.

En el siguiente trozo de cdigo podemos ver cmo operan los mtodos cifrar y descifrar en el modo de operacin CBC con padding:
public class ModoCBCPad { public static byte[] cifrar(byte[] key, byte[] msg){ //aadimos el paddin al mensaje para que su tamao sea multiplo de 16 msg = conPaddin(msg); byte[] vectorIniciacion = Util.hexStringToBytes("000102030405060708090A0B0C0D0E0F"); byte[] mensajeCifrado = new byte[msg.length]; for(int i=0; i<msg.length; i+=AES128.TAM_BLOQUE_BYTES){ // Copiamos un bloque del mensaje, empezando en la posicin i. // Recordemos que los bloques tienen longitud 16 bytes. byte[] bloque_i = new byte[AES128.TAM_BLOQUE_BYTES]; System.arraycopy(msg, i, bloque_i, 0, AES128.TAM_BLOQUE_BYTES); //Realizamos xor System.arraycopy(Util.xor(bloque_i, vectorIniciacion),0,bloque_i, 0, bloque_i.length); //Ciframos el bloque byte[] bloqueCifrado = AES128. cifrarBloque(key, bloque_i); //actualizamos el valor del VectorIniciacion y guardamos el bloque obtenido System.arraycopy(bloqueCifrado, 0, vectorIniciacion, 0, vectorIniciacion.length);

System.arraycopy(bloqueCifrado, 0, mensajeCifrado, i, AES128.TAM_BLOQUE_BYTES); } return mensajeCifrado; }

public static byte[] descifrar(byte[] key, byte[] mensajeCifrado){ byte[] vectorIniciacion = Util.hexStringToBytes("000102030405060708090A0B0C0D0E0F"); byte[] mensaje = new byte[mensajeCifrado.length]; for(int i=0; i<mensajeCifrado.length; i+=AES128.TAM_BLOQUE_BYTES){ // Copiamos un bloque del mensaje, empezando en la posicin i. // Recordemos que los bloques tienen longitud 16 bytes. //bloque_i para recorrer mensajeCifrado byte[] bloque_i = new byte[AES128.TAM_BLOQUE_BYTES]; System.arraycopy(mensajeCifrado, i, bloque_i, 0, AES128.TAM_BLOQUE_BYTES); //Desciframos byte[] bloqueCifrado = AES128.descifrarBloque(key, bloque_i); //Hacemos xor entre bloqueCifrado y vectorIniciacion para almacenar en mensaje //Actualizamos el vectorIniciacion System.arraycopy(Util.xor(bloqueCifrado, vectorIniciacion),0,mensaje, i, AES128.TAM_BLOQUE_BYTES); System.arraycopy(bloque_i, 0, vectorIniciacion, 0, bloque_i.length); } return sinPaddin(mensaje); }

public static byte[] conPaddin(byte[] msg){ //Guardamos en tamaoArray el tamao de debe tener el array con paddin int tamaoArray = msg.length + (16-(msg.length%16)); int tamaoPad = tamaoArray - msg.length; byte[] msgPadding = new byte[tamaoArray]; //Rellenamos con el tamao del pad for(int i=0;i<msgPadding.length;i++){ msgPadding[i]=(byte)(tamaoPad); } System.out.println(Util.bytesToHexString(msgPadding)); //copiamos el mensaje original System.arraycopy(msg, 0, msgPadding, 0, msg.length);

return msgPadding; }

public static byte[] sinPaddin(byte[] msgPad){ //Obtenemos el tamao del paddin que se encuentra al final de msgPad y damos tamao a msgSinP int tamaoPad = (int)(msgPad[msgPad.length-1]); byte[] msgSinP = new byte[msgPad.length-tamaoPad]; //Eliminamos el paddin copiando el mensaje en msgSinP System.arraycopy(msgPad, 0, msgSinP, 0, msgSinP.length); return msgSinP; } -Ejercicio 5.a, Efecto Avalancha: Para este ejercicio se pide que se implemente una clase en la que se ponga en prctica el efecto avalancha en los distintos modos de operacin expuestos en la memoria y se cuente las diferencias que se obtienen sobre el mensaje original una vez cifrado en los diferentes modos. El efecto avalancha consistir en cambiar un bit del segundo bloque de un mensaje y lo cifraremos en cada modo de operacin. Una vez cifrados, compararemos los mensajes con el cifrado del mensaje original para comprobar hasta qu punto puede alterar este cambio sobre el mensaje original cifrado. El efecto avalancha demuestra cunto de bueno es un modo de operacin ya que cuanto mayor sea el nmero de diferencias obtenidas con respecto al mensaje original cifrado, ms difcil ser de descifrar el mensaje. En el siguiente trozo de cdigo se muestra como se aplica el efecto avalancha en los 3 modos de operacin expuestos en esta memoria junto con una operacin que consiste en contar las diferencias entre los mensajes obtenidos en los distintos modos.

public class Avalancha { public static void main(String[] args){ String s = "Este es un texto de ejemplo largo que ocupa 48 B"; byte[] k = Util.hexStringToBytes("2b7e151628aed2a6abf7158809cf4f3c"); byte[] m1 = Util.stringToBytes(s); //mensaje al que le cambiaremos un bit byte[] m2 = Util.stringToBytes(s); // mensaje original int diferencias = 0; //Cambiamos un bit m1[18] = Util.cambiarBit(m1[18],5); //Ciframos con los diferentes modos //Modo CTR byte[] c1 = ModoCTR.cifrar(k, m1); //Modo ECB byte[] c2 = ModoECB.cifrar(k, m1); //Modo CBC byte[] c3 = ModoCBC.cifrar(k, m1); byte[] c0 = ModoCTR.cifrar(k, m2);//mensje original

System.out.println("Mensaje System.out.println("Mensaje System.out.println("Mensaje System.out.println("Mensaje System.out.println(); //Diferencias CTR

ori: CTR: ECB: CBC:

"+Util.bytesToHexString(c0)); "+Util.bytesToHexString(c1)); "+Util.bytesToHexString(c2)); "+Util.bytesToHexString(c3));

c0=ModoCTR.cifrar(k, m2); for(int i=0;i<c1.length;i++){ diferencias+=Util.contarBitsDiferentes(c1[i], c0[i]); } System.out.println("Diferencias en CTR : "+diferencias); //Diferencias CBC diferencias = 0; c0 = ModoCBC.cifrar(k, m2); for(int i=0;i<c1.length;i++){ diferencias+=Util.contarBitsDiferentes(c0[i], c3[i]); } System.out.println("Diferencias en CBC : "+diferencias); //Diferencias ECB diferencias = 0; c0= ModoECB.cifrar(k, m2); for(int i=0;i<c3.length;i++){ diferencias+=Util.contarBitsDiferentes(c0[i], c2[i]); } System.out.println("Diferencias en ECB : "+diferencias); } }

La salida mostrada para dicha clase es: Mensaje ori: 38841F693ADDEA934B2CD033DC6320005E1D2F33A22316D9CF39DE2F36F8768FA453ECA17B246 5AA1EF4FF3C6FD5FD77 Mensaje CTR: 38841F693ADDEA934B2CD033DC6320005E1D2B33A22316D9CF39DE2F36F8768FA453ECA17B246 5AA1EF4FF3C6FD5FD77 Mensaje ECB: DF5EF50BE94480DD2316A86B74B0613ABFAE83E4C910B72426B38894CB5539C9BACAFCB4C131D 15ED118F48F9F24423F Mensaje CBC: 7CDBD884DCE8492AEB05793A475F2865EF9107D174C6178191B06DA4DA2DF397A45ABE1D255F6 638E14C5369692715FB Diferencias en CTR : 1 Diferencias en ECB : 63 Diferencias en CBC : 130 El modo CTR slo ha encontrado una diferencia, debido a que en el proceso de cifrado no interviene el mensaje original. En este caso quienes intervienen en el cifrado son la clave y el contador, y el texto plano se hace xor con el bloque cifrado, vindose alterado nicamente el bit que hemos cambiado.

El modo ECB ha encontrado 63, debido a que en este caso s que se utiliza el mensaje en el proceso de cifrado, que es directo, es decir, participan tanto el mensaje como la clave. El modo CBC ha encontrado 130 errores, es el modo en el que se aprecia un nmero mayor de diferencias. Esto es debido a que en este modo se utiliza un vector de iniciacin (proporcionado en la clase) que se utiliza para hacer xor con el primer bloque de texto plano. El bloque obtenido se cifrar con la clave, dando lugar al mensaje cifrado y se utilizar para como vector iniciacin para hacer xor con el siguiente bloque del mensaje a cifrar. Debido a que el mensaje participa en el proceso de cifrado y adems se utiliza cada bloque como vector iniciacin (cada bloque participa en el cifrado del siguiente bloque), podemos concluir con que ste es el modo de operacin ms poderoso de los expuestos en la memoria. -Ejercicio 5.b, canal con Ruido: Para este ejercicio se pide que se implemente una clase en la que se ponga en prctica un canal con ruido. Con este ejercicio se pretende simular cmo puede afectar a un mensaje la modificacin de un bit. Para esta simulacin utilizaremos un mensaje que utilizaremos para cifrar en cada uno de los modos de operacin expuestos en esta memoria (CTR, ECB, CBC). Una vez cifrado en dichos modos, cambiamos un bit a cada uno de ellos, y descifraremos el mensaje. En el siguiente trozo de cdigo se muestra como se aplica un canal con ruido:

public class CanalConRuido { public static void main(String[] args){ byte[] k = Util.hexStringToBytes("2b7e151628aed2a6abf7158809cf4f3c"); byte[] m1 = Util.stringToBytes("Este es un texto de ejemplo largo que ocupa 48 B"); System.out.println(); int diferentes = 0; System.out.println(Util.bytesToString(m1)); //Modo CTR byte[] c1 = ModoCTR.cifrar(k, m1); c1[18] = Util.cambiarBit(c1[18],5); c1 = ModoCTR.descifrar(k, c1); System.out.println("Mensaje CTR: "+Util.bytesToString(c1));

for(int i=0;i<c1.length;i++){ diferentes+=Util.contarBitsDiferentes(c1[i], m1[i]); } System.out.println("Diferencias Modo CTR: "+diferentes); System.out.println(); //Modo CBC byte[] c2 = ModoCBC.cifrar(k, m1); c2[20] = Util.cambiarBit(c2[20],5); c2 = ModoCBC.descifrar(k, c2); System.out.println("Mensaje CBC: "+Util.bytesToString(c2)); diferentes = 0; for(int i=0;i<c2.length;i++){ diferentes+=Util.contarBitsDiferentes(c2[i], m1[i]); }

System.out.println("Diferencias Modo CBC: "+diferentes); System.out.println(); //Modo ECB byte[] c3 = ModoECB.cifrar(k, m1); c3[18] = Util.cambiarBit(c3[18],5); c3 = ModoECB.descifrar(k, c3); System.out.println("Mensaje ECB: "+Util.bytesToString(c3)); diferentes = 0; for(int i=0;i<m1.length;i++){ diferentes+=Util.contarBitsDiferentes(c3[i], m1[i]); } System.out.println("Diferencias Modo ECB: "+diferentes); } }

La salida mostrada por dicha implementacin es: Mensaje ori: Este es un texto de ejemplo largo que ocupa 48 B Mensaje CTR: Este es un texto da ejemplo largo que ocupa 48 B Diferencias Modo CTR: 1 Mensaje ECB: Este es un texto?_?M?_,?Xy? ;?s?o que ocupa 48 B Diferencias Modo ECB: 57 Mensaje CBC: Este es un texto ?G? ?2?_??_?_?Lo qua ocupa 48 B Diferencias Modo CBC: 69 El modo CTR slo se ve afectado por una diferencia, debido a lo expuesto en el mtodo avalancha. Como el mensaje en texto plano no acta directamente con el proceso de descifrado, sino que se hace xor entre el bloque cifrado y el bloque obtenido al descifrar el contador y la clave, slo se ve alterado en el bit cambiado. El modo ECB se ve afectado de mayor manera, debido a que al cambiar el bit del mensaje cifrado, e intentar descifrar, en este caso si interviene el bloque de mensaje cifrado en el proceso de descifrado directamente, provocando que el bloque donde hemos cambiado el bit cambie por completo. El modo CBC es de nuevo al que ms le afecta ste cambio. Ocurre como el modo ECB, pero como en este modo se utiliza parte del bloque anterior como vector iniciacin para hacer xor con el bloque descifrado, se ve afectado el bloque donde hemos cambiado el bit (en nuestro caso el segundo bloque) y el siguiente bloque a ste, debido a la operacin xor con el bloque anterior. -Conclusiones: Podemos concluir diciendo que de entre los tres modos de operacin estudiados el que otorga un cifrado ms poderoso es el modo CBC ya que es el que ms errores ha obtenido en el efecto avalancha, aunque tambin se ve ms afectado en un canal con ruido y el que ofrece un cifrado ms dbil es el CTR, aunque ofrece una mayor oposicin a un canal con ruido, quedando el modo ECB en un estado intermedio.

Das könnte Ihnen auch gefallen