Silverlight: Cifrar y descifrar Strings (cadena de caracteres)

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:

  1. Cifrar y descifrar cadenas de caracteres dentro de una aplicación Silverlight (out-of-the-browser / fuera-del-navegador).
  2. Cifrar y descifrar cadenas de caracteres dentro de una aplicación de negocios Silverlight (donde existe comunicación entre Servicio y Aplicación Silverlight)

La idea principal aquí es demostrar cómo cifrar y descifrar el mismo valor en el servidor y en la aplicación cliente, debido a que la comunicación entre ellos se encuentran en texto sin formato.

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()Decrypt(), tal como lo podemos ver a continuación:

namespace Encrypt_Decrypt_SBA.Helpers
{
///
/// 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);
}
}
}
}
}

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.

¡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
{
///
/// 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);
}
}
}
}
}

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:

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);
}

Copyright

El algoritmo de criptografía no es mío. He descargado de aquí hace unos años atrás. Así que, el algoritmo existe gracias a chrishayuk.

Puntos de interés

Este artículo expone cómo puede implementar cifrado y descifrado de cualquier cadena de caracteres en una aplicación Silverlight y también en el servidor. Es muy importante en algunos casos. Sé que puede crear tantas maneras de implementar este escenario. Esto es sólo una manera de hacerlo.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.