Vamos a programar #31 - Calculadora de Vigenere en javascript.

Hola de nuevo a todos el día de hoy vamos a ver cómo automatizar un poco el proceso de encriptar texto usando el cifrado de Vigenere.
En el post anterior vimos cómo realizarlo "a mano" pero cómo hacer eso requiere tiempo, el día de hoy veremos código en javascript que realiza el trabajo de manera mucho más rápida y "eficiente".

El Cuerpo.

Para empezar debemos de incluir un nuevo formulario con los siguientes controles:

  1. TextArea.
  2. Textbox.
  3. Boton1
  4. Boton2.
  5. Text Area.
El código que se encarga de insertar los controles es el siguiente (no olvides que estos van en la seccion "body" de la página).

<form class="formVigenere">
<span class="h1v">Frase a des/encriptar:</span>
<textarea class="textareaV" id="InputText" rows="5"></textarea> 
<span class="h1v">Contraseña</span> 
<input class="TextV" id="PassWord" type="text" /> 
<input class="ButtonV" id="Encrypt" onclick="RebuildString(Encriptar(true))" type="button" value="Encriptar" /> 
<input class="ButtonV" id="UnEncrypt" onclick="RebuildString(Encriptar(false))" type="button" value="Desencriptar" /> 
<span class="h1v">Resultado</span>
<textarea class="textareaV" id="Result" rows="5"></textarea></form>

Con el código anterior insertamos 2 Textareas con ID "InputText" y "Resultado", ellas servirán para pedir la frase que se quiere procesar y para mostrar el resultado.
Tambien insertamos un Textbox con ID "PassWord" que serevirá para que el usuario instroduzca la frase que se usará cómo contraseña.
Finalmente insertaremos dos Buttons con ID "Encrypt" y "UnEncrypt" que se usarán para hace el proceso.

El cerebro.

Ahora veamos el código de javascript que se encarga de hacer los cálculos.
<script type="text/javascript">
  function PhraseToArray(Frase)
  {
   var Out = [];
   for(var i = 0; i < Frase.length; i++)
   {
    var CodeNumber = Frase.charCodeAt(i);
    if(CodeNumber >= 97 && CodeNumber <= 122)
    {
     CodeNumber = CodeNumber - 32;
    }
    if(CodeNumber == 209 || CodeNumber == 241)
    {
     Out.push(15);
    }
    if(CodeNumber == 32)
    {
     Out.push(32);
    }
    else{
     if(CodeNumber-64 < 15)
     {
      Out.push(CodeNumber-64);
     }
     else if(CodeNumber-64 >= 15 && CodeNumber-64 < 28){
      Out.push(CodeNumber-63);
     }
    }
   }
   return Out;
  }
  function Encriptar(ModeEnc)
  {
   var GetPhrase = document.getElementById('InputText').value;
   var GetPass = document.getElementById('PassWord').value;
   var Codes = [];
   if(GetPhrase.length < 1 || GetPass.length < 1)
   {
    alert('La frase/contraseña no puede estar en blanco')
    return;
   }
   var PassData = PhraseToArray(GetPass);
   var PhraseData = PhraseToArray(GetPhrase);
   var SpaceCount = 0;
   if (ModeEnc == true)
   {
    for(var i = 0; i < PhraseData.length; i++)
    {
     if(PhraseData[i] == 32)
     {
      Codes.push(32);
      SpaceCount += 1;
     }else{
      Codes.push((PassData[(i - SpaceCount) % PassData.length] + PhraseData[i]) % 27);
     }
    }
   }else{
    for(var i = 0; i < PhraseData.length; i++)
    {
     if(PhraseData[i] == 32)
     {
      Codes.push(32);
      SpaceCount += 1;
     }else{
      var Value = PhraseData[i] - PassData[(i - SpaceCount) % PassData.length];
      if (Value < 1)
      {
       Value += 27;
      }
     Codes.push(Value % 27);
     }
    }
   }
   return Codes;
  }
<!-- Devolver el resultado -->
  function RebuildString(Codigos)
  {
   var Salida = ""
   for(var i = 0; i < Codigos.length; i++)
   {
    if (Codigos[i] == 15 )
    {
     Salida += String.fromCharCode(209);
    }
    if (Codigos[i] == 32)
    {
     Salida += String.fromCharCode(32);
    }
    if (Codigos[i] == 0)
    {
     Salida += String.fromCharCode(90);
    }
    if(Codigos[i] < 15 && Codigos [i] > 0)
     Salida += String.fromCharCode(Codigos[i]+64);
    else if(Codigos[i] > 15 && Codigos[i] < 28){
     Salida += String.fromCharCode(Codigos[i]+63);
    }
   }
   document.getElementById('Result').value = Salida;
  }
  </script>

El código anterior está "sucio" pero el principal motivo del post es mostrar cómo pasar la idea (lo que hicimos en el post anterior) a su versión de código mas cruda. En el próximo post modificaré el código para evitar todas esas partes que a la hora de la eficiencia se vuelven innecesarias.

Todo el proceso de encriptar se lleva a cabo con tres funciones.
La función "PhraseToArray" se encarga de convertir las letras de la frase a encriptar junto con la contraseña a números que se puedan usar en el cifrado donde "A = 1" y "Z = 27". Pero antes de hacer eso hay que recordar que internamente en una computadora, cada símbolo, letra o número;posee un valor y que realmente cuando pides que la computadora escriba un "@" utiliza un numero que representa a ese símbolo.

-0-1-2-3-4-5-6-7-8-9-A-B-C-D-E-F
0-0-
1-§1-
2-!"#$%&'()*+,-./2-
3-0123456789:;<=>?3-
4-@ABCDEFGHIJKLMNO4-
5-PQRSTUVWXYZ[\]^_5-
6-`abcdefghijklmno6-
7-pqrstuvwxyz{|}~7-
8-ÇüéâäàåçêëèïîìÄÅ8-
9-ÉæÆôöòûùÿÖÜ¢£¥ƒ9-
A-áíóúñѪº¿¬½¼¡«»A-
B-B-
C-C-
D-D-
E-αßΓπΣσµτΦΘΩδφεE-
F-±÷°·²F-
-0-1-2-3-4-5-6-7-8-9-A-B-C-D-E-F

Cómo podrás ver, en la tabla (original de Wikipedia) hay toda una serie de símbolo y letras que se pueden mostrar usando el standard ascii (está es la versón extendida).
Antes que nada lo primero que puedes notar es que las letras minúsculas y mayúsculas tienen un numero diferente, entonces si queremos escribir la letra "A", su valor interno será diferente al de la letra "a", para poder usar el cifrado de Vigenere debemos de buscar una forma tal que sin importar que sea mayúscula o minúscula siempre nos devuelva 1.
Para eso en la función "PhraseToArray" nos encargamos de convertir cualquier valor que entre  y dejarlo de tal forma que corresponda a la forma A1Z27.
La funcion "Encriptar" es la que se encargara de hacer los cálculos para que el resultado tenga el mensaje cifrado. Además la misma funcion recibe un parámetro booleano que indica cual es el método a seguir; es decir; si debe de encriptar o des-encriptar el texto. Internamente hace un para de llamadas a la función "PhraseToArray", la primera se usará para volver todas las letras de la frase a encriptar al modo A1Z27 y la segunda hará lo mismo pero está vez lo hará para la contraseña.
Después se encargará de hacer los cálculos, hay que recordar que los "valores" de las letras se suman, pero en ocasiones, la contraseña será mas corta que el texto a encriptar. entonces para evitar que si por ejemplo: tenemos una frase de 10 letras con una contraseña de 4 letras, cuando alcanzamos el numero máximo de letras en la contraseña, hay que repetir otra vez desde el inicio, ademas hay que recordar que cuando trabajamos con texto en una computadora, todos los caracteres tienen un valor por lo que si hay un espacio " " también contara, por lo que si tenemos una frase de 3 palabras con 10 letras podríamos tener en realidad 12 letras en una computadora.
Para evitar ese tipo de errores, la función se encarga de contar los espacios en blanco y hacer las operaciones pertinentes de tal modo que si hay espacios (y eso es lo que se debe de hacer con todos los caracteres NO alfabéticos) al momento de hacer las sumas no se tome en cuenta.
Lo mismo más o menos hace con el otro proceso.
Finalmente, el resultado serán los valores A1Z27 por lo que hay que volverlos a pasar a ASCII.
Para realizar este trabajo se usa la funcion "RebuildString" que lo único que hace es sumar determinado numero de tal forma que si tenemos 1 (que representa a la letra A) nos devuelva la letra en cuestión.
Los botones se usarán para mandar a llamar a la funcion "Encriptar" y el resultado se mostrará en el TextArea "Result".

Un punto importante a resltar es que al haber letras "Ñ" en el idioma español, es realmente importante hacer los cambios necesarios para que en el momento de realizar los calculos no nos llevemos sorpresas. La Ñ ocupa el lugar 15 pero en el standard ASCII si directamente le sumáramos el numero seguido de la N obtendríamos la O. Esto se debe a que la Ñ es representada por los números 209 para la Ñ y 241 para la ñ Mientras que la O es el 79.

Con el código anterior ya estaria todo listo pero para que no quede muy feo el formulario agregamos el siguiente código CSS.

<style type="text/css">
.h1v
{
    font-size: 16px;
}
.formVigenere{
    font: 95% Arial, Helvetica, sans-serif;
    max-width: 400px;
    margin: 10px auto;
    padding: 16px;
    background: #F9F9F9;
}
.textareaV
{
    width: 100%;
    height: 150px;
    padding: 2px 5px;
    box-sizing: border-box;
    border: 2px solid #999;
    border-radius: 4px;
    resize: none;
}
.TextV
{
    width: 100%;
    box-sizing: border-box;
    border: 2px solid #999;
    border-radius: 4px;
}
.ButtonV
{
width: 100%;
    background-color: #4CAF50;
    border: none;
    color: white;
    padding: 15px 32px;
    text-align: center;
    text-decoration: none;
    display: inline-block;
}
</style>


Con eso ya tendrás lista la calculadora de Vigenere. En el siguiente post vamos a ver la versión optimizada de este código, se puede reducir bastante, además de que en este si se incluyen símbolos o números, no funciona correctamente.

El resultado:
Frase a des/encriptar:

Contraseña





Resultado

Los leo Luego.

1 comentario

  1. Claro, pero el objetivo es tratar de codificar los pasos del post anterior. Es la explicación hecha código.
    Gracias por pasarte.

    ResponderBorrar