jueves, 8 de noviembre de 2012

Cifrado de Vigenère en Java

Cifrado de Vigenère en Java


Siguiendo con la serie de programas de criptografía realizados en Java, ahora veremos el Cifrado Vigenère si no lo conocen o no han profundizado en el tema, a continuación un breve resumen:

"El cifrado Vigenère es un cifrado basado en diferentes series de caracteres o letras del cifrado César formando estos caracteres una tabla, llamada tabla de Vigenère, que se usa como clave. El cifrado de Vigenère es un cifrado de sustitución simple polialfabético.
El cifrado Vigenère se ha reinventado muchas veces. El método original fue descrito por Giovan Battista Belasso en su libro de 1553 La cifra del Sig. Giovan Battista Belasso. Sin embargo, fue incorrectamente atribuido más tarde a Blaise de Vigenère, concretamente en el siglo XIX, y por ello aún se le conoce como el "cifrado Vigenère".
Este cifrado es conocido porque es fácil de entender e implementar, además parece irresoluble; esto le hizo valedor del apodo el código indescifrable (le chiffre indéchiffrable, en francés)."

Si desean profundizar en Seguridad Informática, especificamente en Aplicaciones Web les recomiendo que visiten las siguientes páginas y se suscriban:
Los Sitios pertenecen a la Comunidad de Software Libre y Seguridad Informática [Hackem], y la Escuela Politécnica Nacional (EPN) es actualmente la sede de OWASP (Open Web Application Security Project) del Capítulo Nacional y del Capítulo Universitario de Ecuador gracias a Hackem Research Group, más información en los 2 enlaces antes mencionados.

Pero bueno, ahora entrando en materia, el cifrado Vigenère ganó una gran reputación por ser excepcionalmente robusto. Incluso el escritor y matemático Charles Lutwidge Dodgson (Lewis Carroll) dijo que el cifrado Vigenère era irrompible en el artículo "The Alphabet Cipher" para una revista de niños. En 1917, "Scientific American" describió el cifrado Vigenère como imposible de romper. Esta reputación fue mantenida hasta que el método Kasiski resolvió el cifrado en el siglo XIX y algunos criptoanalistas habilidosos pudieron romper ocasionalmente el cifrado en el siglo XVI.
El cifrado Vigenère es lo suficientemente simple si se usa con discos de cifrado. Los Estados confederados de América, por ejemplo, utilizaron un disco de cifrado para implementar el cifrado Vigenère durante la Guerra Civil Estadounidense. Los mensajes confederados fueron poco secretos, ya que los miembros de la Unión solían descifrar los mensajes.
Gilbert Vernam trató de arreglar el cifrado (creando el cifrado Vernam-Vigenère en 1918), pero no importa lo que hiciera, el cifrado sigue siendo vulnerable al criptoanálisis.

Veamos un ejemplo de un mensaje con una clave y cómo obtenemos el texto cifrado:
mensaje:      P A R I S  V A U T  B I E N
clave:        L O U P L  O U P L  O U P L
criptograma:  A O L X D  J U J E  P C T Y
En este abecedario solo existen 26 letras donde A=0, B=1 , C=2 ... Z=25
En términos matemáticos puede expresarse como:
Yi= (Xi+Zi) mod T
Donde Xi es el numero de ubicación de la letra, es decir, que P le corresponde al numero 15 en modo horizontal y Zi la L en modo vertical le corresponde al numero 11, y la letra T es el total de números del alfabeto. Entonces la ecuación quedará de la siguiente manera: Yi= (15 + 11) mod 26. El resultado es: 0, donde 0 es igual a A en modo horizontal.
Se observa que a una misma letra en el texto claro le pueden corresponder diferentes letras en el texto cifrado.

En base al ejemplo anterior podemos realizar la siguiente función encargada de Cifrar el mensaje con la clave proporcionada:

for (int ptextIndex = 0; ptextIndex < textoPlano.length(); ptextIndex++)
{
    char pChar = textoPlano.charAt(ptextIndex);
    int asciiVal = (int) pChar;
    if (pChar == ' ')
    {
textoCifrado += pChar;
continue;
    }
    if (asciiVal < 65 || asciiVal > 90)
    {
textoCifrado += pChar;
continue;
    }

    int basicPlainTextValue = ((int) pChar) - 65;

    char kChar = llave.charAt(llaveIndex);
    int basicLlaveValue = ((int) kChar) - 65;
    int tableEntry = tablaVigenere[basicPlainTextValue][basicLlaveValue];
    char cChar = (char) (tableEntry + 65);
    textoCifrado += cChar;
    llaveIndex++;
    if (llaveIndex == llave.length())
    {
llaveIndex = 0;
    }
}

Una vez realizada esta función, para hacer la versión que descifre el texto, solo debemos realizar las operaciones inversas:

for (int ctextIndex = 0; ctextIndex < textoCifrado.length(); ctextIndex++)
{
    char cChar = textoCifrado.charAt(ctextIndex);
    int asciiVal = (int) cChar;
    if (cChar == ' ')
    {
        textoPlano += cChar;
        continue;
    }
    if (asciiVal < 65 || asciiVal > 90)
    {
        textoPlano += cChar;
        continue;
    }

    int basictextoCifradoValue = ((int) cChar) - 65;
    char kChar = llave.charAt(llaveIndex);
    int basicKeyValue = ((int) kChar) - 65;

    for (int pIndex = 0; pIndex < TamañoColumnaTabla; pIndex++)
    {
        if (tablaVigenere[basicKeyValue][pIndex] == basictextoCifradoValue)
        {
            char potcChar = (char) (tablaVigenere[basicKeyValue][pIndex] + 65);
            char potpChar = (char) (pIndex + 65);
            textoPlano += potpChar;
        }
    }
    llaveIndex++;
    if (llaveIndex == llave.length())
    {
        llaveIndex = 0;
    }
}

Los dos pedazos de código irían dentro de la clase main o también pueden crearlas como funciones independientes, las cuales serían invocadas en el método principal de su programa. Próximamente si les interesa este ejemplo lo subiré al JavaBox.

Y para terminar les adjunto una ejecución del programa tanto para cifrar como para descifrar una cadena de texto:

Cifrando el Mensaje:
Ingresa el Mensaje en Claro (Texto Plano):
Hola Mundo!
Ingresa la Llave: Secreto
El Texto Cifrado es: ZSNR QNBVS!

Descifrando el Mensaje:
Ingresa el Texto Cifrado:
ZSNR QNBVS!
Ingresa la Llave: Secreto
El Mensaje en Claro (Texto Plano) es: Hola Mundo!

2 comentarios:

  1. hola galo me intereza mucho tu ejemplo, pero creo que no lo subiste al javabox. habra manera que me lo puedas brindar? gracias de antemano y saludos

    ResponderEliminar
    Respuestas
    1. Hola Victor, claro, comparte alguna dirección de correo electrónico a la que te lo pueda mandar.

      Saludos!

      Eliminar