Continuando la serie de artículos sobre cifrados, el turno es para Vigenère un cifrado creado por Leone Battista Alberti que trabaja por sustitución, este algoritmo es muy parecido al Cesar y la diferencia es que tiene una semilla mucho más complicada de hallar ya que esta es una palabra la cual se itera también y se hace la suma de la siguiente manera:
(PosicionTxT + PosicionSeed) % alfabeto.longitud
Conociendo el funcionamiento básico de vigenere, pasemos a ver su implementación en diferentes lenguajes de programación:
Códigos disponibles en Github: RiCrypt: Vigenere en Java
Java
/* Modulo Vigenere para RiCrypt Cifrado por sustitucion usando sumas y restas modulares en el alfabeto normal pero altercadas con una semilla como palabra. Phicar project-ric.org phicar@yashira.org */ public class Vigenere{ public static String TxT,Seed; public static String Charset = "abcdefghijklmnopqrstuvwxyz"; public Vigenere(String TxT,String Seed){ this.Seed = Desn(Seed); this.TxT = TxT; } public static String Cifrar(){ String Cifrado = "",a=TxT.toLowerCase(); for(int n = 0,c=0;n<TxT.length();n++,c = (c+1)%Seed.length()){ if(Charset.indexOf(a.charAt(n))!=-1){ int tmp = (Charset.indexOf(a.charAt(n))+Charset.indexOf(Seed.charAt(c)))%Charset.length(); Cifrado+=(Charset.indexOf(TxT.charAt(n))!=-1)?Charset.charAt(tmp):String.valueOf(Charset.charAt(tmp)).toUpperCase(); }else{ c-=1; Cifrado+=TxT.charAt(n); } } return Cifrado; } public static String DesCifrar(){ String DesCifrado = ""; String a = TxT.toLowerCase(); for(int n = 0,c=0;n<a.length();n++,c=(c+1)%Seed.length()){ if(Charset.indexOf(a.charAt(n))!=-1){ int tmp = (Charset.indexOf(a.charAt(n))-Charset.indexOf(Seed.charAt(c))); tmp = (tmp<0)?(tmp+Charset.length()):tmp; DesCifrado+=(Charset.indexOf(TxT.charAt(n))!=-1)?Charset.charAt(tmp):String.valueOf(Charset.charAt(tmp)).toUpperCase(); }else{ c-=1; DesCifrado+=TxT.charAt(n); } } return DesCifrado; } public static String Desn(String a){ String b = ""; for(int n = 0;n<a.length();n++){ if((Charset.indexOf(a.charAt(n))!=-1)||(Charset.indexOf(String.valueOf(a.charAt(n)).toLowerCase())!=-1)) b+=a.charAt(n); } return b; } }
C++
/************************************************ * Nombre : Vigenere.cpp * * * * Cifrado de cesar de sustitución multiple * * por medio de sumas y restas del alfabeto * * * * Fulapol * * Fulapol@gmail.com * * my.opera.com/fulapol * * * ************************************************/ #include <string> Public Class Vigenere{ private: string texto,semilla,letras; letras = "abcdefghijklmnopqrstuvwxyz" string limpiar(string cadena); //Las variables son privadas, el metodo limpiar //es privada ya que solo lo utilizan los otros //metodos para limpiar la entrada public: vigenere(string orig, string sem); string cifrar(); string descifrar(); //Esto es publico porque es la unica forma de //accesar a los datos de la clase } /************************************************ * * * El Constructor que debe recibir la cadena a * * tratar y la cadena semilla * * * ************************************************/ vigenere::vigenere(string orig, string sem){ this->texto = limpiar(orig); this->semilla = limpiar(sem); } /************************************************ * * * El metodo cifrar, que regresa una cadena de * * texto que solo despues de ser cifrada * * * ************************************************/ vigenere::cifrar(){ string final; int i,movimiento,rotacion,total; size_t pos,pos2; //Las variables serviran para registrar la posicion //de las letras y calcular la semilla for(i=0,rotacion=0;i<texto.length();i++,rotacion++){ pos = letras.find(texto.at(i)); pos2 = letras.find(semilla.at(rotacion)); total = ((int)(pos+pos2))%letras.length(); //El total que marca la posicion de la letra y la //semilla sumadas if(total > letras.legth()) movimiento = total-letras.length(); else movimiento = total; //Para asegurarnos que esta dentro del rango final.apend(letras,movimiento,1) if(rotacion==semilla.length()) rotacion=0; //Si se acaba la semilla, regresar al principio } return final; } /************************************************ * * * El metodo descifrar, que regresa una cadena * * de texto que solo despues de ser descifrada * * * ************************************************/ vigenere::descifrar(){ //La funcion es exactamente la misma que en el metodo //cifrar, solo que aqui las posiciones se restan para //eliminar la semilla del texto string final; int i,movimiento,rotacion,total; size_t pos,pos2; for(i=0,rotacion=0;i<texto.length();i++,rotacion++){ pos = letras.find(texto.at(i)); pos2 = letras.find(semilla.at(rotacion)); total = ((int)(pos-pos2))%letras.length(); if(total < 0) movimiento = total+letras.length(); else movimiento = total; final.apend(letras,movimiento,1) if(rotacion==semilla.length()) rotacion=0; } return final; } /************************************************ * * * El metodo limpiar, que regresa una cadena de * * texto que solo contiene los caracteres * * soportados por la clase * * * ************************************************/ vigenere::limpiar(string cadena){ int i; string final; for(i=0;i<cadena.length();i++){ if(cadena.at(i)>64 && cadena.at(i)<91) cadena.at(i) += 32; //Pasamos el caracter a minusculas if(letras.find(cadena.at(i))!=-1) final.apend(cadena.at(i)) //Agregamos a la cadena final el caracter //si se encuentra en la variable letras } return final; }
PHP
<?php /****************************************************************************** * Nombre : Vigenere.php * Clase para el cifrado de Vigenere para Project-RIC. Este es un cifrado de * sustitución polialfabetico, siendo una variación del cifrado de cesar. La diferencia * es que usa una palabra como semilla, la cual cada caracter representa el indice * del charset a ser sumado en las operaciones modulares. Esta semilla se repita cuantas * veces sea necesario hasta cifrar/descifrar toda la cadena. * @copyLeft : Project-RIC * @package : RiCrypt * @author : D-m-K, d4rk.m0nk3y@gmail.com, my.opera.com/d-m-k ******************************************************************************/ class Vigenere { var $charset; var $txt; var $seed; /***************************************************************************** * Constructor * Cifra la cadena pasada como parametro realizando la sustitucion * de la cadena original la cantidad de veces definida en el parametro * @param $s = Cadena original * $seed = Cantidad de rotaciones a cada letra ******************************************************************************/ public function __construct($s, $seed) { $this->charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; //Definicion del charset $this->txt = strtoupper($s); $this->seed = strtoupper($seed); } /************************************************************************************ * Funcion : encode * Cifra la cadena pasada como parametro realizando una sustitucion * polialfabetica a traves de sumas modulares dependiendo el indice de cada caracter de la semilla * @param $seed = Semilla con la que sera cifrado el mensaje * @return $result = Mensaje cifrado ************************************************************************************/ function encode(){ $result = ""; //Cadena donde queda el resultado $x = 0; //Indice de la semilla $p = 0; //Posicion para relizar la operacion modular for($i=0; $i<strlen($this->txt); $i++){ if(strstr($this->charset, $this->txt{$i})){//Evaluo si existe el caracter en el charset $x = strpos($this->charset, $this->seed{($p % strlen($this->seed))}); $result .= $this->rotate($this->txt{$i}, $x); //Invoco funcion que hace la rotacion $p++; //Aumento el indice para la operacion modular }else{//Si no existe dejo el caracter evaluado $result .= $this->txt{$i}; continue; } } return $result; //Devuelvo la cadena Cifrada =) } /************************************************************************************ * Funcion : decode * DesCifra la cadena pasada como parametro realizando una sustitucion * polialfabetica a traves de sumas modulares dependiendo el indice de cada caracter de la semilla * @param $seed = Semilla con la que sera cifrado el mensaje * @return $result = Mensaje cifrado ************************************************************************************/ function decode(){ $result = ""; //Cadena donde queda el resultado $x = 0; //Indice de la semilla $p = 0; //Posicion para relizar la operacion modular for($i=0; $i<strlen($this->txt); $i++){ if(strstr($this->charset, $this->txt{$i})){//Evaluo si existe el caracter en el charset $x = strpos($this->charset, $this->seed{($p % strlen($this->seed))}); $result .= $this->rotate($this->txt{$i}, -$x); //Invoco funcion que hace la rotacion $p++; //Aumento el indice para la operacion modular }else{//Si no existe dejo el caracter evaluado $result .= $this->txt{$i}; continue; } } return $result; //Devuelvo la cadena DesCifrada =) } /***************************************************************************** * Funcion : rotate * Realiza la rotacion de un caracter sobre el charset dependiendo el valor de la semilla * de la cadena original la cantidad de veces definida en el parametro * @param $s = Cadena original * $n = Cantidad de rotaciones * @return $result = Valor del nuevo caracter de acuerdo al indice *****************************************************************************/ function rotate($c, $n){ $result = ""; //Texto de salida $tamC = strlen($this->charset); //Longitud de la cadena del charset $k = 0; //Indice para sustitucion de la cadena con el charset $n %= $tamC; //Semilla ó rotacion $c = strtoupper($c); //Convierto a mayuscula el caracter //Realizo la sustitución de cada caracter //Evaluo si el caracter en la posicion $i existe, de lo contrario //Dejo el caracter que esta por defecto if(strstr($this->charset, $c)){ $k = (strpos($this->charset, $c) + $n); if($k < 0){ $k += $tamC; }else $k %= $tamC; $result .= $this->charset{$k}; }else{ $result .= $c; } return $result; } } ?>
<?php include 'Vigenere.php'; //Incluyo la clase $mensaje = $_POST['mensaje']; //Mensaje a cifrar $semilla = $_POST['semilla']; //Semilla o palabra con la que se cifrara/descifrara el mensaje $tarea = $_POST['tarea']; //Boton pulsado por el usuario $salida = ""; //Variable que guarda el mensaje //Aqui esta la magia if($_POST && $mensaje != "" && $semilla != ""){ //CIFRADO DEL MENSAJE if($_POST['tarea'] == "Cifrar"){ $cipher = new Vigenere($mensaje, $semilla); $salida = $cipher->encode(); } //DESCIFRADO DEL MENSAJE if($_POST['tarea'] == "DesCifrar"){ $cipher = new Vigenere($mensaje, $semilla); $salida = $cipher->decode(); } } ?> <html> <head> <title> .:: Implementacion de la cifra de vigenere ::. </title> </head> <body> <h1>Vigenere</h1> <hr> <!-- Datos para el cifrado --> <form method="post"> <strong>Mensaje a cifrar / descifrar :</strong> <textarea name="mensaje" style="width:500px;border:1px solid #555"><?php echo $_POST['mensaje']; ?></textarea> <strong>Semilla :</strong> <input type="text" name="semilla" style="width:150px;border:1px solid #555" value="<?php echo $_POST['semilla']; ?>"> | <input type="submit" name="tarea" value="Cifrar"> | <input type="submit" name="tarea" value="DesCifrar"> </form> <?php //Muestro el mensaje de salida if($salida != ""){ echo "<strong> Resultado del criptograma </strong> \n"; echo " <div class='mensaje'>" . $salida . "</div> "; } ?> </body> </html>
Ver Comentarios
Buenos días, gracias por su ayuda, tengo una duda, cuando monto el código en DevC++, me aparece un error en la primera linea, donde dice public class vigenere{ , si me podrías ayudar, gracias :)
Me marca el mismo error que comentar de la primer linea