Puede ser... que el cifrado del archivo de configuración de tu aplicación no se adecue a la solución que buscas... puede ser... que necesites cifrar cadenas concretas en un archivo... en una base de datos... mandar eMails cifrados a tu novia/mujer/amante... lo que sea...
Estas dos funciones, basadas en el ejemplo de este artículo con algunas modificaciones, cifran y descifran un String con el algoritmo simétrico Rijndael y con una palabra clave que se pasa como SecureString (¿Por qué?). De esta forma, podemos cifrar/descifrar un texto/cadena mediante ese password.
Necesitamos estos namespaces adicionales:
using System.IO;
using System.Security;
using System.Security.Cryptography;
using System.Runtime.InteropServices;
La función de cifrado:
public static string EncryptString(String Text, SecureString Password)
{
String encryptedString = null;
RijndaelManaged cipher = new RijndaelManaged();
IntPtr bstr = IntPtr.Zero;
try
{
bstr = Marshal.SecureStringToBSTR(Password);
Byte[] passBytes = System.Text.Encoding.Unicode.GetBytes(Text);
Byte[] saltBytes = Encoding.ASCII.GetBytes(Password.Length.ToString());
PasswordDeriveBytes secret = new PasswordDeriveBytes(Marshal.PtrToStringUni(bstr), saltBytes);
using (ICryptoTransform encryptor = cipher.CreateEncryptor(secret.GetBytes(32), secret.GetBytes(16)))
using (MemoryStream ms = new MemoryStream())
using (CryptoStream cryptoStream = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(passBytes, 0, passBytes.Length);
cryptoStream.FlushFinalBlock();
encryptedString = Convert.ToBase64String(ms.ToArray());
}
}
finally
{
if (IntPtr.Zero != bstr)
Marshal.ZeroFreeBSTR(bstr);
}
return encryptedString;
}
La función de descifrado:
public static string DecryptString(String Text, SecureString Password)
{
String decryptedString = null;
RijndaelManaged cipher = new RijndaelManaged();
IntPtr bstr = IntPtr.Zero;
try
{
bstr = Marshal.SecureStringToBSTR(Password);
Byte[] encryptedBytes = Convert.FromBase64String(Text);
Byte[] saltBytes = Encoding.ASCII.GetBytes(Password.Length.ToString());
PasswordDeriveBytes secret = new PasswordDeriveBytes(Marshal.PtrToStringUni(bstr), saltBytes);
using (ICryptoTransform decryptor = cipher.CreateDecryptor(secret.GetBytes(32), secret.GetBytes(16)))
using (MemoryStream memoryStream = new MemoryStream(encryptedBytes))
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
{
Byte[] PlainText = new Byte[encryptedBytes.Length];
Int32 DecryptedCount = cryptoStream.Read(PlainText, 0, PlainText.Length);
decryptedString = Encoding.Unicode.GetString(PlainText, 0, DecryptedCount);
}
}
finally
{
if (IntPtr.Zero != bstr)
Marshal.ZeroFreeBSTR(bstr);
}
return decryptedString;
}
Podemos probarlo en un pequeño programa:
static void Main(string[] args)
{
String data = "## Prueba de cifrado ##";
SecureString secureS = new SecureString();
secureS.AppendChar('m');
secureS.AppendChar('y');
secureS.AppendChar('p');
secureS.AppendChar('a');
secureS.AppendChar('s');
secureS.AppendChar('s');
Console.WriteLine(" Plano: " + data);
String encryptedData = Cipher.EncryptString(data,secureS);
Console.WriteLine(" Cifrado: " + encryptedData);
Console.WriteLine("Descifrado: " + Cipher.DecryptString(encryptedData,secureS));
Console.ReadKey(true);
secureS.Dispose();
}
Resultado: