Proteger una cadena de conexión con RSA por código

Si no nos interesa que nuestra cadena de conexión a una base de datos esté visible en nuestro fichero config, bien sea un app.config o un fichero config de Web, podemos escribir un código que lo encripte mediante protección RSA.

Para ello y partiendo de un fichero de configuración como el siguiente:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <connectionStrings>
    <add name="MainConnection" connectionString="Data Source=.MSSQL2008STD
         ;Initial Catalog=AdventureWorks; Integrated Security=SSPI"/>
  </connectionStrings>
</configuration>

Podemos escribir el código necesario para encriptarlo.

El código sería el siguiente:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Data.SqlClient;

namespace ProtectConnection
{
    class Program
    {
        static void Main(string[] args)
        {
            //Primero abrimos el fichero de configuración
            System.Configuration.Configuration config =
            ConfigurationManager.OpenExeConfiguration(
             ConfigurationUserLevel.None);

            // No es necesario pero probamos a Conectarnos para probar la cadena de conexión que hemos creado…
            String cadenaconexion = ConfigurationManager.ConnectionStrings["MainConnection"].ConnectionString;
            SqlConnection miconexion = new SqlConnection();
            miconexion.ConnectionString = cadenaconexion;
            miconexion.Open();
            Console.WriteLine("Conexion Creada");
            miconexion.Close();

            //A continuación cargamos la sección de cadenas de conexión.
            ConfigurationSection cadenasdeconexion =
                config.GetSection("connectionStrings");

            //si no está encriptada la encriptamos.
            if (!cadenasdeconexion.SectionInformation.IsProtected)
            {
                Console.WriteLine("Encriptando fichero");
                cadenasdeconexion.SectionInformation.ProtectSection
                    ("RsaProtectedConfigurationProvider");
                cadenasdeconexion.SectionInformation.ForceSave = true;
                config.Save(ConfigurationSaveMode.Full);
            }
            Console.ReadLine();
        }
    }
}

 

Si observamos en el directorio una vez generado el .exe, veremos que si abrimos nuestro fichero de configuración, está sin encriptar:

conexion0

Si ejecutamos una vez el programa veremos como se conecta a la base de datos y luego encripta la conexión:

conexion1

Si lo volvemos a ejecutar, veremos que ya no lo encripta y que vuelve a desencriptarlo automáticamente sin escribir código adicional.

conexion2

Una vez ejecutado el programa, el fichero pasaría a tener el siguiente contenido:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <connectionStrings configProtectionProvider="RsaProtectedConfigurationProvider">
    <EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element"
      xmlns="http://www.w3.org/2001/04/xmlenc#">
      <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />
      <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
        <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
          <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
          <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
            <KeyName>Rsa Key</KeyName>
          </KeyInfo>
          <CipherData>
            <CipherValue>q3+U3GzGciObvpgVZgjWRGMpeNYXsgpQEKFHP6q+SG3EfG54ZhcK69ocFpnqnhZZE3eZaLE0KUZBecRWeZLbtz6zI+zqg2x1er7t4DeZn5LODslURYlmNelTrR4AmXwj+ZlMMiwTb0kFjTrzlrgCe0kpo346QtxV/4shW2c4Zw0=</CipherValue>
          </CipherData>
        </EncryptedKey>
      </KeyInfo>
      <CipherData>
        <CipherValue>I9uyNHeclHjakBYoa2Y53MGFYHKJAka+GI3Lr8lYREDh7wEDyGd54ijwOLuO7BEckpIB92bHEulvP0HsKFfYUEvuP3WTBwgsbKrwNR7fJ3iHKmYf/n770Ms0f5WByFlBKki9EXO+/bmBNCBKxy8ZKMqC/mtYU5M3QtX3vjJqzRzf+gL8/Ix33neAob3qFIn554Ho+wLKbsLpSBuYD2FVLUmCfN6NdXtO6ElfB6CEIrw9ayIhvd9qzRhxHIGhfIotpuD+gu0/YtdHKLSD6/wH4vwNsM8YmSF+17AX8+oRIYl3aZbQHk0olIyq0BqRsx1vTgAPZW9z5RZC1RD0lc2zeII/NcLFup09Z5k8jbVRFYcOnUKnC0FnWJXa6TlikpUYxkuRQIR+wsQDyBbu7oHUKBRe/249DNUP/GXKwxiwYO/T132w/rjGEiESVMx+/QkrEG7KsQZpuiPgDNyvtxKdlQOzsQFKJtGlR7D6l3Az+0pfB9mUprLeJP0JIYH8pN4UtY0cWUGeR6hc+PmljhSQ6U3njC8eASJL0HdNGTcB7+0JphDchDn8VmNM5846dY18qNE30n2ZAHGW96CCTv+UhA==</CipherValue>
      </CipherData>
    </EncryptedData>
  </connectionStrings>
</configuration>

3 comentarios sobre “Proteger una cadena de conexión con RSA por código”

  1. Buenos días Javier,

    La limitación del ejemplo que planteas es que este cifrado está acoplado a la máquina (no sé si usuario también) donde los cifres. Estamos cifrando sin dar una clave, así que tiene tendrá que coger algo único de la máquina.

    Para poder usar esta técnica y compartir ficheros de configuración entre máquinas (especialmente importante para servidores ) el ejemplo se puede extender creando una clave y exportándola en un KeyContainer, ver http://msdn.microsoft.com/en-us/library/yxw286t2.aspx para información detallada.

Deja un comentario

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