Cifrando Strings con un password

by Valeriano Tortola 1. febrero 2008 03:00

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:

image

Tags: ,

.NET 2.0 | C# 2.0

Comentarios

01/02/2008 1:39:35 #

pingback

Pingback from elbruno.com

Cifrando Strings con un password - vtortola

elbruno.com |

01/02/2008 1:40:12 #

pingback

Pingback from geeks.ms

Cifrando Strings con un password - Pensando en asíncrono

geeks.ms |

Comentarios no permitidos