Vamos a programar #44 - Código Bacon (ver. C#).
Hola de nuevo a todos, el día de hoy vamos a ver el código en C# que sirve para cifrar un mensaje usando el código Bacon.
El código consiste de 3 funciones, pero además hay una matriz del tipo "string" en el cual se almacena cada valor del código correspondiente a cada letra. En esta matriz verás que hay valores duplicados; pero si hacemos memoria, hay que recordar que el código para los pares de letras "i - j" y "u - v" son iguales, entonces, para fines prácticos, simplemente repetimos los valores de estas.
Antes de empezar con la explicación del código, hay que plantear lo que tenemos que hacer. Para poder trabajar más cómodamente, tenemos que buscar una forma de "entendernos" con la computadora. Si hacemos un poco más de memoria, en el post donde usábamos el cifrado de Vigenere lo que hacíamos realmente, era pasar la letra a su equivalente en el código ASCII. Al revisarlo, notaremos que las letras mayúsculas estaban comprendidas entre el 65 y 90, mientras que las minúsculas, están entre el 97 y 122 (si contar las letras ñ's), así que aprovechando eso y la matriz que creamos al inicio, podemos hacer mucho más fácil el proceso.
Ahora, el código en orden de aparición. Primero tenemos la función "CharToBaconianCode". Está función recibe un parámetro del tipo "string" y lo que hace, es crear el pre-cifrado aplicando a la frase que queremos ocultar las reglas del código, ya que para esta parte no necesitamos distinguir entre mayúsculas o minúsculas, lo primero que hacemos es convertir toda las frase a mayúsculas, así nos aseguraremos que todos los números (que representan a cada letra), estarán dentro del rango 65 ~ 90. Luego convertimos la frase en un arreglo del tipo "char", usando la función "ToCharArray()", cuando separamos todo, tenemos que la letra "A" tiene el código 65, pero en la matriz que creamos al inicio en donde almacenamos el valor del código Bacon para cada letra, esta en la primer posicion (en la posición cero en realidad), entonces para ajustar cada valor y que coincida con loas valores de la matriz "Values", solo debemos de restar 65 y así obtendremos en automático el valor correcto desde la matriz (aquí lo importante de convertir todo a mayúsculas). Está función devuelve un valor del tipo "string" que representa el mensaje ingresado cómo parámetro pero con el pre-cifrado ya aplicado.
La siguiente función es: "IsLower". Cómo su nombre lo indica, está función solo sirve para identificar si un valor está dentro del rango de las letras minúsculas. Esta función recibe un parámetro del tipo "byte" que corresponde a la letra que queramos saber si es minúscula. Esta función devuelve un valor del tipo "bool" "true" si el parámetro ingresado están dentro del rango 97 ~ 122 (indicando que es una letra minúscula).
La última función es "FinalCipher". Esta función recibe dos parámetros, el primero de tipo "string" llamado "PreCipher", este debe de ser SIEMPRE, el resultado de la función "CharToBaconianCode" (o si lo hiciste a mano, el resultado del pre-cifrado). El segundo parámetro, también es del tipo "string" y se llama "Phrase", el cual debe de ser la frase en la cual queremos insertar el mensaje pre-cifrado. Para generar el resultado final, esta función separa los dos parámetros de entrada y los convierte en una matriz del tipo "char", la frase pre-cifrada es la que nos va a dictar cómo debe de estar escrito el mensaje, pero lo que primero nos aseguramos de solo tener "A" y "B", así podemos crear un par de condiciones para cada caso (Al encontrar "A" se escribirá una minúscula y al encontrar una "B", se usara una mayúscula). Dentro de cada condición, vamos a tener otra condición más. Puede ser que el mensaje de destino (o segundo parámetro) tenga ya una letra mayúscula o minúscula, si el pre-cifrado nos dice que debe de haber una minúscula, solamente mandamos a llamar a la función "IsLower" y si el resultado es "true", dejamos las cosas cómo están, pero si es el caso contrario, convertimos el valor de la letra actual a un valor del tipo "byte" y le restaremos 32 (recuerda que la letra "A" es 65 y la letra "a" es 97, al restar 32 a la "a" tenemos "A"), para el caso contrario, solamente bastará con sumarle 32 y obtendremos el mismo resultado.
El Código.
El código en c# que vamos a utilizar es el siguiente:
//El código Bacon sigue las siguientes reglas: // a- AAAAA // b- AAAAB // c- AAABA // d- AAABB // e- AABAA // f- AABAB // g- AABBA // h- AABBB // i j- ABAAA // k- ABAAB // l- ABABA // m- ABABB // n- ABBAA // o- ABBAB // p- ABBBA // q- ABBBB // r- BAAAA // s- BAAAB // t- BAABA // u v- BAABB // w- BABAA // x- BABAB // y- BABBA // z- BABBB using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace Baconiancipher { public partial class FrmMain : Form { private String[] Values = {"AAAAA", "AAAAB", "AAABA", "AAABB", "AABAA", "AABAB", "AABBA", "AABBB", "ABAAA", "ABAAA", "ABAAB", "ABABA", "ABABB", "ABBAA", "ABBAB", "ABBBA", "ABBBB", "BAAAA", "BAAAB", "BAABA", "BAABB", "BAABB", "BABAA", "BABAB", "BABBA", "BABBB"}; private string CharToBaconianCode(string Input) { Input = Input.ToUpper(); char[] Letras = Input.ToCharArray(); string OutValue = ""; for (int X = 0; X < Letras.Length; X++) { if ((byte)Letras[X] < 91 && (byte)Letras[X] > 64) { OutValue += Values[(byte)Letras[X] - 65];// + " "; } } return OutValue; } private bool IsLower(byte Code) { if (Code > 96 && Code < 123) return true; else return false; } private string FinalCipher(string PreCipher, string Phrase) { if (PreCipher.Length != Phrase.Length) { MessageBox.Show("Las longitudes del pre-cifrado y la frase para insertarlo no coinciden", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return "Error"; } char[] PreCipherChars = PreCipher.ToCharArray(); char[] PhraseChars = Phrase.ToCharArray(); string FinalResult = ""; for (int Y = 0; Y < PhraseChars.Length; Y++) { if ((byte)PreCipherChars[Y] == 65) { if (IsLower((byte)Phrase[Y])) FinalResult += PhraseChars[Y]; else FinalResult += (char)(PhraseChars[Y] + 32); } else { if (!IsLower((byte)Phrase[Y])) FinalResult += PhraseChars[Y]; else FinalResult += (char)(PhraseChars[Y] - 32); } } return FinalResult; } public FrmMain() { InitializeComponent(); } private void BtnPreCipher_Click(object sender, EventArgs e) { TxtPrecipherResult.Text = CharToBaconianCode(TxtInput.Text); if (TxtPrecipherResult.TextLength == txtInput2.TextLength) BtnCipher.Enabled = true; } private void txtInput2_TextChanged(object sender, EventArgs e) { GBInput2.Text = "Frase de " + txtInput2.TextLength + " letras."; if (TxtPrecipherResult.TextLength == txtInput2.TextLength) BtnCipher.Enabled = true; else BtnCipher.Enabled = false; } private void BtnCipher_Click(object sender, EventArgs e) { TxtFinalResult.Text = FinalCipher(TxtPrecipherResult.Text, txtInput2.Text); } } }
El código consiste de 3 funciones, pero además hay una matriz del tipo "string" en el cual se almacena cada valor del código correspondiente a cada letra. En esta matriz verás que hay valores duplicados; pero si hacemos memoria, hay que recordar que el código para los pares de letras "i - j" y "u - v" son iguales, entonces, para fines prácticos, simplemente repetimos los valores de estas.
Antes de empezar con la explicación del código, hay que plantear lo que tenemos que hacer. Para poder trabajar más cómodamente, tenemos que buscar una forma de "entendernos" con la computadora. Si hacemos un poco más de memoria, en el post donde usábamos el cifrado de Vigenere lo que hacíamos realmente, era pasar la letra a su equivalente en el código ASCII. Al revisarlo, notaremos que las letras mayúsculas estaban comprendidas entre el 65 y 90, mientras que las minúsculas, están entre el 97 y 122 (si contar las letras ñ's), así que aprovechando eso y la matriz que creamos al inicio, podemos hacer mucho más fácil el proceso.
Ahora, el código en orden de aparición. Primero tenemos la función "CharToBaconianCode". Está función recibe un parámetro del tipo "string" y lo que hace, es crear el pre-cifrado aplicando a la frase que queremos ocultar las reglas del código, ya que para esta parte no necesitamos distinguir entre mayúsculas o minúsculas, lo primero que hacemos es convertir toda las frase a mayúsculas, así nos aseguraremos que todos los números (que representan a cada letra), estarán dentro del rango 65 ~ 90. Luego convertimos la frase en un arreglo del tipo "char", usando la función "ToCharArray()", cuando separamos todo, tenemos que la letra "A" tiene el código 65, pero en la matriz que creamos al inicio en donde almacenamos el valor del código Bacon para cada letra, esta en la primer posicion (en la posición cero en realidad), entonces para ajustar cada valor y que coincida con loas valores de la matriz "Values", solo debemos de restar 65 y así obtendremos en automático el valor correcto desde la matriz (aquí lo importante de convertir todo a mayúsculas). Está función devuelve un valor del tipo "string" que representa el mensaje ingresado cómo parámetro pero con el pre-cifrado ya aplicado.
La siguiente función es: "IsLower". Cómo su nombre lo indica, está función solo sirve para identificar si un valor está dentro del rango de las letras minúsculas. Esta función recibe un parámetro del tipo "byte" que corresponde a la letra que queramos saber si es minúscula. Esta función devuelve un valor del tipo "bool" "true" si el parámetro ingresado están dentro del rango 97 ~ 122 (indicando que es una letra minúscula).
La última función es "FinalCipher". Esta función recibe dos parámetros, el primero de tipo "string" llamado "PreCipher", este debe de ser SIEMPRE, el resultado de la función "CharToBaconianCode" (o si lo hiciste a mano, el resultado del pre-cifrado). El segundo parámetro, también es del tipo "string" y se llama "Phrase", el cual debe de ser la frase en la cual queremos insertar el mensaje pre-cifrado. Para generar el resultado final, esta función separa los dos parámetros de entrada y los convierte en una matriz del tipo "char", la frase pre-cifrada es la que nos va a dictar cómo debe de estar escrito el mensaje, pero lo que primero nos aseguramos de solo tener "A" y "B", así podemos crear un par de condiciones para cada caso (Al encontrar "A" se escribirá una minúscula y al encontrar una "B", se usara una mayúscula). Dentro de cada condición, vamos a tener otra condición más. Puede ser que el mensaje de destino (o segundo parámetro) tenga ya una letra mayúscula o minúscula, si el pre-cifrado nos dice que debe de haber una minúscula, solamente mandamos a llamar a la función "IsLower" y si el resultado es "true", dejamos las cosas cómo están, pero si es el caso contrario, convertimos el valor de la letra actual a un valor del tipo "byte" y le restaremos 32 (recuerda que la letra "A" es 65 y la letra "a" es 97, al restar 32 a la "a" tenemos "A"), para el caso contrario, solamente bastará con sumarle 32 y obtendremos el mismo resultado.
A tomar en cuenta...
A pesar de que el programa funciona, aun está en fase "beta", en el caso de la frase que se quiere cifrar, solo bastará con escribirlo y después pulsar el botón "Pre-Cifrar", dentro del programa se toman las medidas necesarias para que el resultado sea el mensaje correctamente pre-cifrado; pero en el caso de la frase en la cual queremos insertarlo, debemos de asegurarnos de no usar símbolos o espacios, ya que se pueden producir resultados cómo en la imagen siguiente:
No deberían de ir los @ |
Por el momento lo dejare así. El cómo solucionarlo, lo puedes averiguar si revisas los post de cifrado que ya hay en el blog.
Cómo siempre, el código completo, lo puedes descargar de mi dropbox, para que lo revises y lo modifiques. La próxima semana, publicaré el código resuelto y además veremos cómo hacer lo mismo en Java (android) o Javascript.
Por ahora es todo, los leo luego
No hay comentarios.