SQL Server 2016 siempre cifrado: fácil de implementar, difícil de descifrar
Publicado: 2022-03-11Los datos son un activo clave de cualquier empresa, en particular los datos transaccionales que contienen secretos comerciales, como registros financieros o de salud. Los datos son más vulnerables en tránsito entre el servidor que los almacena y el cliente que los solicita.
El enfoque estándar para garantizar la seguridad es cifrar los datos en el servidor y utilizar el protocolo HTTPS habilitado para SSL para proteger los datos en el transporte. Sin embargo, ¿qué pasaría si pudiéramos aumentar aún más el nivel de seguridad mediante el uso de HTTPS y el envío de datos en un formato cifrado a través de la línea de comunicación, solo para descifrar los datos de los clientes que tienen certificados válidos? Ese enfoque haría que un ataque tradicional de hombre en el medio (MITM) sea mucho más difícil.
La solución de Microsoft a este problema es Always Encrypted, una forma de enviar datos cifrados a través de la canalización y descifrarlos solo por parte de los usuarios con acceso a certificados válidos. Por lo tanto, incluso si el atacante obtiene los datos, sin un certificado adecuado almacenado en la máquina del cliente, los datos serían inútiles.
Este artículo describe cómo configurar y usar Always Encrypted, y se recomienda su lectura para cualquier persona que envíe datos importantes a través de las líneas de comunicación pública, incluso si están protegidas con SSL.
El concepto detrás de Always Encrypted
Always Encrypted es una tecnología de cifrado del lado del cliente que Microsoft introdujo con SQL Server 2016. Always Encrypted mantiene los datos cifrados automáticamente, no solo cuando se escriben, sino también cuando los lee una aplicación aprobada. A diferencia del cifrado de datos transparente, que cifra los datos y los archivos de registro en el disco en tiempo real, pero permite que cualquier aplicación que los consulte lea los datos, Always Encrypted requiere que su aplicación cliente utilice un controlador habilitado para Always Encrypted para comunicarse con el base de datos. Mediante el uso de este controlador, la aplicación transfiere de forma segura los datos cifrados a la base de datos que luego solo puede descifrar una aplicación que tenga acceso a la clave de cifrado. Cualquier otra aplicación que consulte los datos también puede recuperar los valores encriptados, pero esa aplicación no puede usar los datos sin la clave de encriptación, lo que hace que los datos sean inútiles. Debido a esta arquitectura de cifrado, la instancia de SQL Server nunca ve la versión no cifrada de los datos.
En este momento, los únicos controladores habilitados para Always Encrypted son el proveedor de datos de .NET Framework para SQL Server, que requiere la instalación de la versión 4.6 de .NET Framework en la computadora cliente y el controlador JDBC 6.0. Eso probablemente cambiará con el tiempo, pero estos son los requisitos oficiales de Always Encrypted a partir de abril de 2017.
Pero, ¿por qué necesitamos esta tecnología? Hay un par de buenas razones por las que se debe usar Always Encrypted:
- Seguridad : los datos siempre han sido necesarios para estar seguros. Ahora que SSL se ve comprometido, Always Encrypted llena el vacío con otra capa de protección de canalización de transporte.
- Soporte regulatorio : los datos deben encriptarse y evitar que los DBA los miren a través de más y más regulaciones de la industria, principalmente en las industrias de finanzas y telecomunicaciones. Esto se describe en el estándar PII ("Información de identificación personal") que establece que cosas como números de tarjetas de crédito, números de seguro social, nombres y direcciones deben protegerse, o el propietario de los datos puede ser severamente penalizado.
Cómo usar Siempre cifrado
El uso de Always Encrypted requiere una pequeña cantidad de preparación dentro del servidor de la base de datos que almacena las tablas cifradas. La preparación es un proceso de dos pasos:
- Crear la definición de clave maestra de columna
- Crear la clave de cifrado de columna
Clave maestra de columna
Entonces, ¿qué es una clave maestra de columna?
La clave maestra de columna es un certificado que se almacena dentro de un almacén de certificados de Windows (que se usa en la demostración como una opción de almacenamiento de certificados), un módulo de seguridad de hardware de terceros (un nombre genérico para soluciones de terceros para instalar, administrar y usar certificados), o Azure Key Vault (la solución basada en la nube de Microsoft para la gestión de certificados).
La aplicación que cifra los datos utiliza la clave maestra de columna para proteger varias claves de cifrado de columna que manejan el cifrado de datos dentro de las columnas de una tabla de base de datos. El uso de almacenes de certificados de SQL Server, que a veces se denomina Enterprise Key Manager , requiere el uso de SQL Server Enterprise Edition.
En este artículo, describimos el uso de un certificado autofirmado que almacena en Microsoft Certificate Store del sistema operativo Windows. Si bien este enfoque no es la configuración óptima, demuestra el concepto de Always Encrypted, pero también debe señalarse que este enfoque no es aceptable para entornos de producción , donde la administración de certificados debe realizarse con cuentas de usuario separadas y seguras y, preferiblemente, , en servidores separados.
Puede crear una definición de clave maestra de columna mediante la interfaz gráfica dentro de SQL Server Management Studio (SSMS) o mediante T-SQL. En SSMS, conéctese a la instancia de base de datos de SQL Server 2016 en la que desea usar Always Encrypted para proteger una tabla de base de datos.
Creación y uso de claves maestras de columna
En el Explorador de objetos, navegue primero a la base de datos, luego a Seguridad y luego expanda la carpeta Claves siempre cifradas para mostrar sus dos subcarpetas, como se muestra en las siguientes figuras:
Para crear la clave maestra de columna, haga clic con el botón derecho en la carpeta Column Master Keys
y seleccione New Column Master Key
. En el cuadro de diálogo New Column Master Key
, escriba un nombre para la clave maestra de columna, especifique si desea almacenar la clave en el almacén de certificados del usuario actual o del equipo local o en Azure Key Vault y, a continuación, seleccione un certificado de la lista. Si no hay certificados, o si desea utilizar un nuevo certificado autofirmado, haga clic en el botón Generate Certificate
y luego haga clic en OK
. Este paso crea un certificado autofirmado y lo carga en el almacén de certificados de la cuenta de usuario actual que ejecuta SSMS.
Nota: Debe realizar estos pasos en una máquina confiable, pero no en la computadora que aloja su instancia de SQL Server. De esa forma, los datos permanecen protegidos en SQL Server incluso si la computadora host está comprometida.
Entonces, después de crear el certificado y configurarlo como una clave maestra de columna, debe exportarlo y distribuirlo a todas las computadoras que alojan clientes que requieren acceso a los datos. Si una aplicación cliente está basada en web, debe cargar el certificado en el servidor web. Si es una aplicación instalada en las computadoras de los usuarios, debe implementar el certificado en la computadora de cada usuario individualmente.
Puede encontrar instrucciones aplicables para exportar e importar certificados para su sistema operativo en las siguientes URL:
- Exportación de certificados
- Windows 7 y Windows Server 2008 R2
- Windows 8 y Windows Server 2012
- Windows 8.1 y Windows Server 2012 R2
- Windows 10 y Windows Server 2016
- Importación de certificados
- Windows 7 y Windows Server 2008 R2
- Windows 8 y Windows Server 2012
- Windows 8.1 y Windows Server 2012 R2
- Windows 10 y Windows Server 2016
Cuando importa certificados al almacén de certificados en equipos con una aplicación que cifra y descifra los datos, debe importar los certificados al almacén de certificados del equipo o al almacén de certificados de la cuenta de dominio que ejecuta la aplicación.
Clave de cifrado de columna
Después de crear una clave maestra de columna, está listo para crear claves de cifrado para columnas específicas. El controlador ADO.NET de SQL Server 2016 utiliza claves de cifrado de columnas para cifrar los datos antes de enviarlos a SQL Server y para descifrarlos después de recuperarlos de la instancia de SQL Server 2016. Al igual que con la clave maestra de columna, puede crear claves de cifrado de columna mediante T-SQL o SSMS. Mientras que las claves maestras de columna son más fáciles de crear con T-SQL, las claves de cifrado de columna son más fáciles de crear con SSMS.
Para crear una clave de cifrado de columna, use el Object Explorer
para conectarse a la instancia de la base de datos, vaya a la base de datos, luego a Security
y expanda la carpeta Always Encrypted Keys
. Haga clic con el botón derecho en Column Encryption Keys
y luego seleccione New Column Encryption Key
. En el cuadro de diálogo New Column Encryption Key
, escriba un nombre para la nueva clave de cifrado, seleccione una Column Master Key Definition
en la lista desplegable y luego haga clic en OK
. Ahora puede usar la clave de cifrado de columna en la definición de una nueva tabla.

Creación de una tabla con valores cifrados
Después de crear la definición de clave maestra de columna y las claves de cifrado de columna, puede crear una tabla para contener los valores cifrados.
Antes de hacer esto, debe decidir qué tipo de cifrado usar, qué columnas cifrar y si puede indexar estas columnas. Con la función Always Encrypted , usted define los tamaños de columna normalmente y SQL Server ajusta el tamaño de almacenamiento de la columna en función de la configuración de cifrado. Después de crear su tabla, es posible que deba cambiar su aplicación para ejecutar comandos en esta tabla usando Always Encrypted .
Tipos de cifrado de SQL Server 2016
Antes de crear una tabla para que contenga valores cifrados, debe decidir si cada columna debe cifrarse o no.
Primero, ¿se usará esta columna para buscar valores o simplemente devolver esos valores?
Si la columna se va a utilizar para búsquedas, la columna debe utilizar un tipo de cifrado determinista , que permita operaciones de igualdad. Sin embargo, existen limitaciones en la búsqueda de datos cifrados mediante la función Siempre cifrados . SQL Server 2016 solo admite operaciones de igualdad, que incluyen joins
equal to
, not equal to
(que usan igualdad) y el uso del valor en la cláusula GROUP BY
. No se admite ninguna búsqueda con LIKE
. Además, la clasificación de los datos cifrados con Always Encrypted se debe realizar en el nivel de la aplicación, ya que SQL Server clasificará según el valor cifrado en lugar del valor descifrado.
Si la columna no se va a usar para ubicar registros, entonces la columna debe usar el tipo de cifrado aleatorio. Este tipo de cifrado es más seguro, pero no admite búsquedas, uniones ni operaciones de agrupación.
Creación de una tabla con columnas cifradas
Al crear tablas, utiliza la sintaxis CREATE TABLE
normal con algunos parámetros adicionales dentro de la definición de la columna. Se utilizan tres parámetros dentro de la sintaxis ENCRYPTED WITH
para la CREATE TABLE
.
El primero de ellos es el parámetro ENCRYPTION_TYPE
, que acepta un valor de RANDOMIZED
o DETERMINISTIC
. El segundo es el parámetro ALGORITHM
, que solo acepta un valor de RAEAD_AES_256_CBC_HMAC_SHA_256
. El tercer parámetro es COLUMN_ENCRYPTION_KEY
, que es la clave de cifrado que utiliza para cifrar el valor.
CREATE TABLE [dbo].[Customers] ( [CustomerId] [int] IDENTITY(1,1), [TaxId] [varchar](11) COLLATE Latin1_General_BIN2 ENCRYPTED WITH (ENCRYPTION_TYPE = DETERMINISTIC, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256', COLUMN_ENCRYPTION_KEY = YOUR_COLUMN_ENCRYPTION_KEY) NOT NULL, [FirstName] [nvarchar](50) NULL, [LastName] [nvarchar](50) NULL, [MiddleName] [nvarchar](50) NULL, [Address1] [nvarchar](50) NULL, [Address2] [nvarchar](50) NULL, [Address3] [nvarchar](50) NULL, [City] [nvarchar](50) NULL, [PostalCode] [nvarchar](10) NULL, [State] [char](2) NULL, [BirthDate] [date] ENCRYPTED WITH (ENCRYPTION_TYPE = RANDOMIZED, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256', COLUMN_ENCRYPTION_KEY = YOUR_COLUMN_ENCRYPTION_KEY) NOT NULL PRIMARY KEY CLUSTERED ([CustomerId] ASC) ON [PRIMARY] ); GO
Indexación con Always Encrypted
Las columnas que contienen datos cifrados se pueden usar como columnas clave dentro de los índices, siempre que esas columnas estén cifradas mediante el uso del tipo de cifrado DETERMINISTIC
. Las columnas cifradas mediante el tipo de cifrado RANDOMIZED
devuelven un mensaje de error cuando intenta crear un índice en esas columnas. Las columnas cifradas con cualquier tipo de cifrado se pueden utilizar como columnas INCLUDE
dentro de índices no agrupados.
Debido a que los valores cifrados pueden ser índices, no se requieren medidas de ajuste de rendimiento adicionales para los valores cifrados con Always Encrypted más allá de la indexación y el ajuste que normalmente realiza. El ancho de banda de red adicional y una mayor E/S son los únicos efectos secundarios que resultan del mayor tamaño de los valores que se devuelven.
Rendimiento siempre cifrado
El rendimiento siempre es un factor clave, especialmente en este caso, cuando agregamos una sobrecarga de cifrado al tráfico habitual de la base de datos. El mejor sitio para probar el rendimiento es SQL Performance, que probó la ejecución de consultas y el uso del disco en varios escenarios:
Como hay trabajo de CPU y disco duro que debe realizarse con procesos de cifrado y descifrado, hay un impacto obvio en la cantidad de espacio de almacenamiento utilizado y la duración de las consultas. Como esto influye en su entorno (CPU, RAM y características del disco), debe probar si esto presentará un problema en producción.
Nota: En caso de que desee obtener más información sobre la optimización del rendimiento de Microsoft SQL Server, consulte uno de nuestros artículos anteriores, Cómo ajustar el rendimiento de Microsoft SQL Server.
Cambios en la aplicación
¿Qué debe hacer para implementar correctamente Always Encrypted en el código heredado?
Una de las cosas buenas de la función Always Encrypted de SQL Server 2016 es que las aplicaciones que ya usan procedimientos almacenados, ORM o comandos T-SQL parametrizados no deberían requerir cambios en la aplicación para usar Always Encrypted, a menos que ya se estén usando operaciones de no igualdad. Las aplicaciones que crean declaraciones SQL como SQL dinámico dentro de la aplicación y ejecutan esos comandos en la base de datos directamente deben modificarse para usar la parametrización de sus consultas, una mejor práctica de seguridad recomendada para todas las aplicaciones, antes de que puedan aprovechar la función Always Encrypted.
Otro cambio necesario para que Always Encrypted funcione es la adición de un atributo de cadena de conexión a la cadena de conexión de la aplicación que se conecta a la base de datos: Column Encryption Setting=enabled
.
Con esta configuración agregada a la cadena de conexión, el controlador ADO.NET pregunta al servidor SQL si el comando de ejecución incluye columnas cifradas y, de ser así, qué columnas están cifradas. Para aplicaciones de alta carga, el uso de esta configuración puede no ser la mejor práctica, especialmente si un gran porcentaje de la ejecución de comandos no incluye valores cifrados.
En consecuencia, .NET Framework proporciona un nuevo método en el objeto SqlConnection llamado SqlCommandColumnEncryptionSetting
, que tiene tres valores posibles:
-
Disabled
: no hay columnas o parámetros de Always Encrypted para usar en las consultas que se ejecutan con este objeto de conexión. -
Enabled
: hay columnas y/o parámetros de Always Encrypted en uso para las consultas que se ejecutan mediante este objeto de conexión. -
ResultSet
: no hay parámetros de Always Encrypted. Sin embargo, la ejecución de consultas mediante este objeto de conexión devuelve columnas cifradas mediante el uso de Always Encrypted.
Nota: tenga en cuenta que el uso de este método puede requerir potencialmente una cantidad significativa de cambios en el código de su aplicación. Un enfoque alternativo es refactorizar su aplicación para usar diferentes conexiones.
Para obtener el mejor rendimiento de SQL Server, es aconsejable solicitar solo los metadatos sobre Always Encrypted para aquellas consultas que usan Always Encrypted. Esto significa que en las aplicaciones para las que un gran porcentaje de consultas usan Always Encrypted, la cadena de conexión debe estar habilitada y las consultas específicas dentro de la aplicación deben especificar SqlCommandColumnEncryptionSetting
como Disabled
. Para las aplicaciones para las que la mayoría de las consultas no usan valores de Always Encrypted, la cadena de conexión no debe estar habilitada y SqlCommandColumnEncryptionSetting
debe establecerse en Enabled
o ResultSet
según sea necesario para aquellas consultas que usan columnas de Always Encrypted. En la mayoría de los casos, las aplicaciones pueden simplemente habilitar el atributo de cadena de conexión y el rendimiento de la aplicación permanecerá sin cambios mientras se usan los datos cifrados.
¿Vale la pena el esfuerzo de estar siempre encriptado?
¿Respuesta corta? ¡Sí definitivamente!
No solo ayuda a evitar muchos problemas de seguridad potenciales y brinda a los desarrolladores de SQL funciones de seguridad adicionales, sino que también hace que su sistema sea más compatible, lo cual es vital en múltiples industrias, desde las telecomunicaciones hasta la banca y los seguros. También es importante tener en cuenta que, dados los requisitos técnicos mencionados en el artículo, Always Encrypted se puede implementar con cambios mínimos en las aplicaciones de los sistemas existentes .
Aunque puede usar soluciones personalizadas para obtener el mismo efecto, esta tecnología se incluye con la nueva versión de SQL Server y se puede usar de inmediato. También es importante tener en cuenta que, dado que se trata de una nueva tecnología, todavía existen algunas limitaciones en su uso y agrega algunas demandas de hardware adicionales.
Sin embargo, a menos que sean un factor decisivo para su entorno y tenga una aplicación que se distribuya fuera de la intranet de su empresa, prácticamente no hay razón para no usar Always Encrypted.