Silverlight: Cifrar y descifrar Strings (cadena de caracteres)
Introducción
En determinadas circunstancias resulta muy útil cifrar y descifrar las cadenas de caracteres en nuestras aplicaciones, especialmente cuando transmitimos datos sensibles a través de la red o entre aplicaciones dentro de nuestras propias máquinas.En aplicaciones Silverlight podemos cifrar y descifrar las cadenas de caracteres fácilmente siguiendo algunos pasos y escribiendo unas cuantas líneas de código en una extensión de clase.
Contexto
Este artículo se ocupa de dos temas muy importantes:- Cifrar y descifrar cadenas de caracteres dentro de una aplicación Silverlight (out-of-the-browser / fuera-del-navegador).
- Cifrar y descifrar cadenas de caracteres dentro de una aplicación de negocios Silverlight (donde existe comunicación entre Servicio y Aplicación Silverlight)
Utilizando el código
Cifrar y descifrar cadena de caracteres dentro de una aplicación Silverlight
Muy bien, aquí debemos crear una sencilla Aplicación de negocios Silverlight en Visual Studio. En mi caso llamé a mi proyecto Encrypt_Decrypt_SBA.Ahora crearemos un método de extensión para todas las cadenas de caracteres en nuestro proyecto Silverlight, la clase será estática y expondrá dos métodos principales:
Encrypt()
y Decrypt()
, tal como lo podemos ver a continuación:
namespace Encrypt_Decrypt_SBA.Helpers { ///En el código anterior, hemos creado dos métodos extensibles para todas las cadenas de caracteres dentro del proyecto Silverlight, de esta manera que podemos implementar fácilmente el cifrado de cualquier cadena de caracteres dentro del proyecto./// Una simple clase disponible sólo en este Ensamblado /// internal static class Cryptography { internal static string Encrypt(this string dataToEncrypt) { // Inicializamos AesManaged encryptor = new AesManaged(); // Obtenemos el salto de cadena, en este caso lo hacemos estáticamente. Luego creamos el objeto byte[] string salt = "EDSBA_EXAMPLE"; byte[] saltBytes = new UTF8Encoding().GetBytes(salt); Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes(salt, saltBytes); encryptor.Key = rfc.GetBytes(16); encryptor.IV = rfc.GetBytes(16); encryptor.BlockSize = 128; // Creamos el objeto Stream en memoria using (MemoryStream encryptionStream = new MemoryStream()) { // Creamos el Stream de criptografía using (CryptoStream encrypt = new CryptoStream(encryptionStream, encryptor.CreateEncryptor(), CryptoStreamMode.Write)) { // Ciframos byte[] utfD1 = UTF8Encoding.UTF8.GetBytes(dataToEncrypt); encrypt.Write(utfD1, 0, utfD1.Length); encrypt.FlushFinalBlock(); encrypt.Close(); // Retornamos el dato cifrado return Convert.ToBase64String(encryptionStream.ToArray()); } } } internal static string Decrypt(this string encryptedString) { // Inicializamos variables AesManaged decryptor = new AesManaged(); byte[] encryptedData = Convert.FromBase64String(encryptedString); // Obtenemos el salto de la cadena, en este caso lo pasamos estáticamente. Luego, creamos el objeto byte[] string salt = "EDSBA_EXAMPLE"; byte[] saltBytes = new UTF8Encoding().GetBytes(salt); Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes(salt, saltBytes); decryptor.Key = rfc.GetBytes(16); decryptor.IV = rfc.GetBytes(16); decryptor.BlockSize = 128; // Creamos un Stream en memoria using (MemoryStream decryptionStream = new MemoryStream()) { // Creamos un Stream de criptografía using (CryptoStream decrypt = new CryptoStream(decryptionStream, decryptor.CreateDecryptor(), CryptoStreamMode.Write)) { try { // Desciframos decrypt.Write(encryptedData, 0, encryptedData.Length); decrypt.Flush(); decrypt.Close(); } catch { } // Retornamos el dato descifrado byte[] decryptedData = decryptionStream.ToArray(); return UTF8Encoding.UTF8.GetString(decryptedData, 0, decryptedData.Length); } } } } }
¡Ejecutamos el proyecto (F5) y lo probamos!
Cifrar y descifrar cadenas de caracteres en una Aplicación de Negocios Silverlight
En este caso, tenemos que crear una clase para implementar el mismo algoritmo que utilizamos en nuestra aplicación Silverlight.Entonces podemos crear la misma clase y exponer el mismo conjunto de métodos dentro de ella, así que el código será:
namespace Encrypt_Decrypt_SBA.Web { ///Ahora vamos a crear un Servicio WCF para Silverlight, dentro de la carpeta de servicios. La llamaremos ServiceTest.svc y crearemos los dos métodos siguientes:/// Una simple clase disponible sólo en este ensamblado /// internal static class Cryptography { internal static string Encrypt(this string dataToEncrypt) { // Inicializamos AesManaged encryptor = new AesManaged(); // Obtenemos el salto de cadena, en este caso lo pasamos estáticamente. Luego, creamos el objeto byte[] string salt = "EDSBA_EXAMPLE"; byte[] saltBytes = new UTF8Encoding().GetBytes(salt); Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes(salt, saltBytes); encryptor.Key = rfc.GetBytes(16); encryptor.IV = rfc.GetBytes(16); encryptor.BlockSize = 128; // Creamos un Stream en memoria using (MemoryStream encryptionStream = new MemoryStream()) { // Creamos el stream de criptografía using (CryptoStream encrypt = new CryptoStream(encryptionStream, encryptor.CreateEncryptor(), CryptoStreamMode.Write)) { // Cifrar byte[] utfD1 = UTF8Encoding.UTF8.GetBytes(dataToEncrypt); encrypt.Write(utfD1, 0, utfD1.Length); encrypt.FlushFinalBlock(); encrypt.Close(); // Retornar el dato cifrado return Convert.ToBase64String(encryptionStream.ToArray()); } } } internal static string Decrypt(this string encryptedString) { // Inicializamos AesManaged decryptor = new AesManaged(); byte[] encryptedData = Convert.FromBase64String(encryptedString); // Obtenemos el salto de cadena, en este caso lo pasamos estáticamente. Luego, creamos el objeto byte[] string salt = "EDSBA_EXAMPLE"; byte[] saltBytes = new UTF8Encoding().GetBytes(salt); Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes(salt, saltBytes); decryptor.Key = rfc.GetBytes(16); decryptor.IV = rfc.GetBytes(16); decryptor.BlockSize = 128; // Creamos el Stream en memoria using (MemoryStream decryptionStream = new MemoryStream()) { // Creamos el Stream de criptografía using (CryptoStream decrypt = new CryptoStream(decryptionStream, decryptor.CreateDecryptor(), CryptoStreamMode.Write)) { try { // Desciframos decrypt.Write(encryptedData, 0, encryptedData.Length); decrypt.Flush(); decrypt.Close(); } catch { } // Retornar el dato descifrado byte[] decryptedData = decryptionStream.ToArray(); return UTF8Encoding.UTF8.GetString(decryptedData, 0, decryptedData.Length); } } } } }
namespace Encrypt_Decrypt_SBA.Web.Services { [ServiceContract(Namespace = "")] [SilverlightFaultBehavior] [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] public class ServiceTest { [OperationContract] public void DoWork() { return; } [OperationContract] public string EncryptString(string unencrypted) { return unencrypted.Encrypt(); } [OperationContract] public string DecryptString(string encrypted) { return encrypted.Decrypt(); } } }Compilamos el proyecto Web. Y agregamos la referencia de servicio en la Aplicación Silverlight.
Ahora, sólo llamaremos a la cadena de caracteres cifrada en el servidor y comprobaremos con el Texto de la aplicación Silverlight, de esta manera:
private void btnEncryptService_Click(object sender, System.Windows.RoutedEventArgs e) { //Instanciamos el proxy para el servicio ServiceTest ServiceTest.ServiceTestClient proxy = new ServiceTest.ServiceTestClient(); //Llamamos al procedimiento desde el proxy proxy.EncryptStringCompleted += (s, args) => { this.simpleTextService.Text = string.Empty; this.EncryptedTextService.Text = args.Result; }; //Llamamos al método async y pasamos el parámetro proxy.EncryptStringAsync(this.simpleTextService.Text); } private void btnDencryptService_Click(object sender, System.Windows.RoutedEventArgs e) { //Instanciamos el proxy para el servicio ServiceTest ServiceTest.ServiceTestClient proxy = new ServiceTest.ServiceTestClient(); //Llamamos al procedimiento del proxy proxy.DecryptStringCompleted += (s, args) => { MessageBox.Show("Vía servicio: "+args.Result); this.EncryptedTextService.Text = string.Empty; }; //Llamar al método async y pasar el parámetro proxy.DecryptStringAsync(this.EncryptedTextService.Text); }