Esta página fue traducida automáticamente. Lee el original en inglés. English

Biblioteca de IBSurgeon

Cómo funciona el cifrado de bases de datos Firebird

(c) Alexey Kovyazin, IBSurgeon, Alex Peshkoff, Firebird Project, 2021

El artículo se basa en los materiales del taller “Cifrado de bases de datos” en la Firebird Conference 2019 en Berlín, Alemania. Describe cómo funciona el cifrado de bases de datos Firebird, a nivel de servidor, en el lado del cliente, cómo configurar el cifrado de bases de datos, cómo usarlo desde varios tipos de aplicaciones (Delphi, Java, .NET). Los ejemplos del artículo se basan en IBSurgeon Firebird Encryption Framework (FEPF), pero pueden adaptarse a la mayoría de las implementaciones de plugins de cifrado disponibles actualmente.

Contenido:

  1. ¿Por qué necesitamos cifrado de bases de datos (y cuándo no)?
  2. Cómo funciona el cifrado de bases de datos Firebird en el lado del servidor
  3. ¿Qué parte de la base de datos se cifra?
  4. ¿Cuándo se cifran las páginas de datos?
  5. ¿Cómo proteger la transferencia de claves?
  6. Cómo funciona el cifrado Firebird en el lado del cliente
  7. Aplicaciones nativas
  8. Aplicaciones Java
  9. Aplicaciones .NET
  10. Instalación y configuración
  11. Cómo rastrear el progreso del cifrado
  12. Resumen

1. ¿Por qué necesitamos cifrado de bases de datos (y cuándo no)?

El cifrado de bases de datos Firebird se introdujo en la versión Firebird 3.0 (junto con el cifrado del protocolo de transferencia, que a menudo se confunde con el tema tratado), y aumentó enormemente las capacidades para proteger los datos del acceso no autorizado. Sin embargo, no es una panacea, y es necesario comprender sus fortalezas y debilidades para usarlo correctamente.

En este artículo, consideramos los detalles internos del cifrado de bases de datos a nivel básico, para dar a los desarrolladores de aplicaciones Firebird una mejor comprensión de cómo funciona el cifrado de bases de datos.

Entonces, ¿por qué necesitamos cifrado de bases de datos?

  1. Para proteger bases de datos con datos sensibles/valiosos del robo “físico”. Si un intruso roba el disco con una copia de la base de datos cifrada o de alguna manera obtiene una copia del archivo de la base de datos, no será posible leer los datos sin una clave apropiada, así como no será posible usar software de recuperación como FirstAID para extraer los datos. Por supuesto, depende del algoritmo de cifrado y la potencia informática, pero descifrar AES256 requerirá demasiado tiempo o recursos informáticos demasiado costosos.
  2. Para proteger la base de datos del acceso de aplicaciones no autorizadas sin claves de cifrado. Ejemplos son:
    • acceso directo con una herramienta de desarrollo por una persona no autorizada, para cambiar información sensible (por ejemplo, transacciones de dinero),
    • cambiar o robar lógica de negocio (textos de procedimientos almacenados y disparadores).
  3. Proteger bases de datos con datos precargados de la exportación o acceso por aplicaciones no autorizadas.
  4. Los gobiernos han introducido recientemente leyes de protección de datos (GDPR/DSVGO en Europa, LGPD en Brasil, etc.) que requieren, entre otras cosas, un mayor nivel de protección para datos personales y otros datos sensibles, y el cifrado se menciona como una de las medidas de protección adecuadas.

¿Cuándo no es útil el cifrado de bases de datos?

En algunos casos, es mejor usar las capacidades de seguridad y configuración de Firebird en lugar del cifrado de bases de datos:

  • Para proteger la base de datos del acceso físico a través de la red, es necesario configurar el acceso de red: es decir, cerrar carpetas compartidas de red, porque Firebird no requiere acceso compartido de red a los archivos de la base de datos, y reforzar los permisos de seguridad (para Linux, por ejemplo, los archivos de la base de datos deben tener acceso de lectura-escritura solo para el usuario “firebird”).
  • Para restringir el acceso a la base de datos específica para un subconjunto específico de usuarios, la solución más fácil será configurar una base de datos de seguridad separada.
  • Para restringir el acceso a los objetos de la base de datos (tablas, procedimientos almacenados), es necesario usar los mecanismos de seguridad de Firebird: usuarios, roles, etc.

Por supuesto, ambas listas anteriores están incompletas, pero le dan una impresión de cuándo necesita o no necesita cifrado de bases de datos.

2. Cómo funciona el cifrado de bases de datos Firebird en el lado del servidor

Repasemos los detalles internos del cifrado de bases de datos Firebird, y comencemos con la parte del servidor.

2.1. ¿Qué parte de la base de datos se cifra?

Lo primero que debemos considerar es ¿qué parte de la base de datos se cifra? Como probablemente sepa, la base de datos Firebird consiste en partes de igual tamaño, llamadas “páginas de base de datos”. Hay varios tipos de tales páginas, cada tipo sirve para un propósito específico.

A continuación, puede ver la figura con los principales tipos de datos:

Figura 1. Tipos de páginas de base de datos

Algunas páginas están diseñadas para almacenar datos de usuarios, y otras son necesarias para almacenar información del sistema, como transacciones y páginas de inventario de páginas (más detalles sobre las páginas de base de datos están disponibles aquí).

Cuando la base de datos Firebird se cifra, solo las páginas con datos de usuario se cifran: páginas de datos, índices, generadores y BLOBs:

Figura 2. Solo las páginas de base de datos con datos de usuarios se cifran

Tenga en cuenta que los metadatos de la base de datos (procedimientos almacenados, tablas, vistas, disparadores, nombres de generadores, etc.) no difieren de los “datos de usuarios” dentro de la parte del motor responsable del cifrado, y se cifran.

¿Por qué las páginas del sistema no se cifran? Por razones de rendimiento, principalmente, y debido al hecho de que no contienen datos sensibles que requieran protección.

La página de cabecera de la base de datos no se cifra, porque contiene información necesaria para el cifrado (por ejemplo, el nombre de la clave).

2.2. ¿Cuándo se cifran las páginas de datos?

Cuando un usuario ejecuta SELECT desde la base de datos cifrada, los datos se leen del archivo cifrado pero llegan a la cuadrícula de la aplicación con el conjunto de resultados en forma no cifrada.

Consideremos los detalles de este proceso:

Figura 3. ¿Cuándo se cifran las páginas de base de datos?

Normalmente, el proceso comienza con una serie de lecturas de páginas de base de datos desde un archivo de base de datos, y se almacenan en caché en la caché de archivos del sistema operativo.

Firebird también se puede configurar para omitir la caché de archivos y usar solo su propia caché, pero por defecto, se usa la caché de archivos.

Después de eso, Firebird lee las páginas y las coloca en la caché de páginas de Firebird (se define por el parámetro DefaultDBCachePages en firebird.conf y/o databases.conf o en la página de cabecera de la base de datos).

Luego, las páginas de la caché se seleccionan para el conjunto de resultados de la declaración SQL particular (SELECT en nuestro ejemplo).

La figura a continuación muestra los detalles:

Figura 4. Las páginas se cifran entre la caché de Firebird y la caché de archivos del SO

Entonces, las páginas de base de datos se cifran en la caché de archivos del SO pero llegan a la caché de páginas de Firebird sin cifrar, y viceversa.

La parte del software Firebird responsable del cifrado/descifrado se llama “plugin de cifrado”. Dado que la mayoría de las implementaciones de plugins (conocidas por los autores) se llaman DbCrypt, nos referiremos a él como DbCrypt.

En la figura a continuación, puede ver variantes para Windows (DbCrypt.dll) y Linux (libDbCrypt.so):

Figura 5. El plugin de cifrado (DbCrypt) realiza el cifrado/descifrado

Si mira esta imagen el tiempo suficiente, la siguiente pregunta aparecerá bastante rápido: ¿cómo obtiene DbCrypt la clave adecuada para cifrar/descifrar las páginas de base de datos?

La respuesta: hay otro plugin para la gestión de claves.

El nombre típico para la gestión de claves es KeyHolder, que sirve como instalación de almacenamiento/gestión de claves para el plugin de cifrado (DbCrypt). KeyHolder implementa la interfaz para la gestión de claves que utiliza DbCrypt.

Figura 6. DbCrypt y KeyHolder

¿Qué significa “gestión de claves”?

En el caso más simple, DbCrypt puede leer claves del archivo en el servidor. El archivo puede ser un simple archivo de texto plano, que puede estar oculto en un lugar “secreto” o en una memoria USB, o puede ser un archivo cifrado (usando Windows Crypto API, por ejemplo, o con una clave interna incorporada).

El archivo de claves puede contener varias claves, almacenadas, por conveniencia, como una lista con nombre, y puede verse así (el ejemplo a continuación se toma del marco de plugin de cifrado de IBSurgeon):

Code
Key=Red 0xec,0xa1,0x52,0xf6,0x4d,0x27,0xda,0x93,0x53,0xe5,0x48,0x86,0xb9,0x7d,0xe2,0x8f,0x3b,0xfa,0xb7,0x91,0x22,0x5b,0x59,0x15,0x82,0x35,0xf5,0x30,0x1f,0x04,0xdc,0x75,
Key=Green 0xab,0xd7,0x34,0x63,0xae,0x19,0x52,0x00,0xb8,0x84,0xa3,0x44,0xbd,0x11,0x9f,0x72,0xe0,0x04,0x68,0x4f,0xc4,0x89,0x3b,0x20,0x8d,0x2a,0xa7,0x07,0x32,0x3b,0x5e,0x74,

Cuando la base de datos se cifra, sus páginas de cabecera permanecen sin cifrar para almacenar información sobre el plugin de cifrado y el nombre de la clave, y puede ver esta información con el comando “gstat -h nombredatabase”:

Code
Database header page information:
....
Creation date    Jan 11, 2017 15:12:20
Attributes       force write, encrypted, plugin DBCRYPT

Variable header data:
 Crypt checksum: MUB2NTJqchh9RshmP6xFAiIc2iI=
 Key hash:       ask88tfWbinvC6b1JvS9Mfuh47c=
 Encryption key name:    RED
 Sweep interval:         0
*END*

DbCrypt puede procesar páginas para varias bases de datos y varias claves:

Figura 7. Múltiples claves para múltiples bases de datos en el mismo servidor (es decir, instancia de Firebird)

Elegir la clave correcta

A menudo los desarrolladores hacen la pregunta “¿Cómo reconoce el plugin qué clave es para qué base de datos?” La respuesta es bastante simple: por el nombre de la clave, que se almacena en la página de cabecera de la base de datos.

Menos frecuente, pero aún importante, la pregunta: ¿qué pasa si el nombre de la clave es como está registrado en la cabecera, pero el valor de la clave es diferente? Para evitar errores de lectura de páginas debido a la clave incorrecta, el plugin DbCrypt almacena la secuencia de prueba cifrada (dígitos 0…F) en la cabecera, y luego la clave se activa, el plugin intenta cifrar los datos de muestra con una clave y comparar su hash con el resultado almacenado, para asegurar que el valor de clave pasado es realmente correcto para esta base de datos en particular.

El enfoque cuando el plugin de cifrado lee claves directamente es simple y beneficioso para depuración, pruebas de rendimiento, etc., porque implementa el cifrado de manera transparente: es decir, las aplicaciones cliente y las herramientas de desarrolladores no saben que la base de datos está cifrada.

Sin embargo, en realidad, necesitamos restringir el acceso de las aplicaciones a la base de datos: solo la aplicación cliente que tiene una clave debería poder conectarse a la base de datos cifrada.

Para esto, necesitamos el plugin KeyHolder, para obtener la clave de la aplicación cliente (que generalmente está en otra computadora) a través del protocolo de red de Firebird.

2.3. ¿Cómo proteger la transferencia de claves?

Es posible que queramos proteger la base de datos en la situación cuando el cliente decide obtener acceso directo a la base de datos cifrada, evitando las aplicaciones autorizadas (muchos proveedores quieren restringir los datos del acceso directo, ya sea de solo lectura o lectura-escritura).

Esto es equivalente a la situación cuando un intruso tiene acceso al servidor pero no tiene las claves.

Consideremos los siguientes escenarios de ataque para interceptar claves en el lado del servidor:

  1. Cuando el intruso crea un plugin de cifrado falso (DBCrypt.dll) y lo coloca en el servidor, y cuando KeyHolder pasa la clave, el DbCrypt falso hace un volcado de la clave:

Figura 8. Ataque con DbCrypt.dll falso

  1. Cuando el intruso crea un archivo firebird.exe falso y hace el volcado con él:

Figura 9. Ataque con firebird.exe falso

Para protegerse de tales ataques, una buena implementación de los plugins de cifrado y gestión de claves necesita proteger el intercambio de claves.

El intercambio de claves puede protegerse con cifrado asimétrico con un par de claves pública/privada.

Estas claves se generan durante el proceso de compilación y están integradas para el par específico de plugins de cifrado y gestión de claves. Para una mejor protección, es necesario usar pares especialmente construidos de DbCrypt/KeyHolder.

Cuando DbCrypt y KeyHolder intercambian las claves, usan el siguiente protocolo (está simplificado, pero la idea es clara, supongo):

Code
DbCrypt → KeyHolder:
	Dame la clave de la base de datos con esta sal
KeyHolder:
	Cifra DbKey con la clave pública usando la sal de DbCrypt
	Transfiere DbKey cifrada a DbCrypt
DbCrypt:
	Descifra DbKey con la clave privada
	Valida la corrección de la sal
	Listo para trabajar

Más o menos el mismo protocolo se usa para intercambiar claves entre instancias de KeyHolder, y para el intercambio de claves entre una aplicación cliente y KeyHolder.

Tenga en cuenta que el cifrado y la corrección de las claves transferidas dependen de la implementación del plugin; el motor Firebird proporciona solo un servicio básico de transferencia de bajo nivel “enviar N bytes de esta instancia de plugin a esa instancia de plugin”.

Resumen para la parte del lado del servidor del cifrado

  • El cifrado/descifrado lo realiza el plugin de cifrado de base de datos (DbCrypt), página por página, durante el intercambio de datos entre la caché de archivos del sistema operativo y la caché de páginas de Firebird
  • La gestión de claves puede implementarse de manera simple cuando DbCrypt lee las claves directamente, pero generalmente se hace con el plugin de gestión de claves (KeyHolder)

Ahora descubramos cómo funcionan las aplicaciones cliente con bases de datos cifradas.

3. Cómo funciona el cifrado de Firebird en el lado del cliente

3.1. Aplicaciones nativas

Para entender qué sucede cuando una aplicación cliente se conecta a una base de datos cifrada, consideremos el proceso de conexión regular a una base de datos no cifrada para aplicaciones nativas.

Tenga en cuenta: de aquí en adelante, “nativa” significa que dicha aplicación establece una conexión de red con el servidor usando fbclient.dll; generalmente, dicha aplicación está construida en Delphi, C++, PHP. A diferencia de las aplicaciones nativas, Java y .NET implementan su propia versión del protocolo, que se considerarán más adelante.

Proceso de conexión:

  1. La aplicación cliente carga la biblioteca del cliente
  2. fbclient.dll - aplicaciones nativas de Windows
  3. libfbclient.so - aplicaciones nativas de Linux
  4. La aplicación cliente inicia una conexión, enviando
  5. Nombre de usuario, p. ej., SYSDBA
  6. Contraseña, p. ej., masterkey
  7. Ruta/alias de la base de datos

En el caso de una base de datos cifrada, se requiere un paso adicional: es necesario pasar el nombre de la clave de cifrado y su valor.

Es importante decir que el paso de la clave debe hacerse antes de la conexión regular, debido al hecho de que las páginas de datos con metadatos, incluido el nombre del propietario de la base de datos, juego de caracteres, etc., están cifradas.

Entonces, esto nos lleva a lo siguiente:

  1. Se necesita un viaje de ida y vuelta adicional en la red para pasar la clave antes de la conexión regular
  2. La transferencia de claves desde la aplicación cliente a Firebird requiere codificación con el uso de cifrado asimétrico e implementación de una interfaz de devolución de llamada; puede ser bastante complejo. Para simplificar esta tarea, los proveedores de plugins proporcionan un ejemplo del código para conectarse, o, como en el marco de plugins de IBSurgeon, crean la biblioteca adicional fbcrypt.dll/libfbcrypt.so, que implementa una interfaz fácil de usar adecuada para transferir claves desde la aplicación cliente.

Para conectar una aplicación nativa (que usa fbclient.dll) a la base de datos cifrada, se deben realizar 3 llamadas. A continuación se muestra un ejemplo en Delphi (simplificado, sin manejo de errores):

En el manejador de eventos BeforeConnect:

Code
fbcrypt_init(PAnsiChar(‘C:\Firebird30.bclient.dll’));
fbcrypt_key(‘RED’, ‘0xec,0xa1,0x52,0xf6,...’));
fbcrypt_callback(nil);

 // Luego conectar como de costumbre
Database1.Active:=True;

En la figura siguiente puede ver una descripción general del proceso de conexión con una base de datos cifrada en la aplicación nativa:

Figura 10. Proceso de conexión a la base de datos cifrada para aplicaciones nativas

¿Qué pasa con la seguridad de subprocesos en el caso de aplicaciones cliente multiproceso?

Permítanme recordar algunos momentos generales de la implementación de aplicaciones cliente multiproceso.

Desde Firebird 2.5, varios subprocesos dentro de la aplicación pueden usar de manera segura un único adjunto a la base de datos, porque toda la sincronización necesaria se realiza dentro de fbclient.dll.

Sin embargo, en este caso, los subprocesos podrán trabajar con el adjunto solo uno a la vez.

Esto está bien para las aplicaciones que no requieren intercambio de datos de alto rendimiento con la base de datos: si no es un problema esperar para realizar una consulta SQL desde un subproceso cuando otro subproceso está ejecutando otro SQL, es más fácil usar un modelo simple donde 1 adjunto se comparte entre varios subprocesos.

Si la aplicación requiere ejecutar consultas SQL en paralelo (es decir, es una aplicación cliente a gran escala), es mejor usar un subproceso separado para cada conexión.

La situación con el intercambio de claves para los adjuntos a bases de datos cifradas es un poco más compleja.

En cada adjunto, la biblioteca del cliente transfiere las claves desde el cliente, pero no está directamente relacionado con los subprocesos en la aplicación cliente; la situación depende de la API utilizada.

Como sabe, la biblioteca cliente de Firebird desde 3.0 ofrece 2 tipos de API: nueva API orientada a objetos, basada en el concepto de proveedores, y la API isc_ heredada, implementada como una solución alternativa para mantener la compatibilidad con los controladores antiguos de Firebird.

Si se usa la nueva API de cliente orientada a objetos, es suficiente crear el proveedor, suministrarlo con las claves necesarias y luego usarlo para los nuevos adjuntos.

Si se usa la API de cliente isc_, para cada adjunto la biblioteca del cliente creará su propio proveedor temporal, que no es directamente visible ni accesible para el usuario final.

En este caso, la clave se transfiere exactamente desde el subproceso donde se invoca isc_attach_database, y se usa almacenamiento local de subprocesos para almacenar esa clave.

En la práctica, dado que casi todas las bibliotecas de clientes usan la API isc_ (en este momento, entre los controladores populares, solo el controlador de Python usa la API OO), es necesario invocar fb_database_crypt_callback() en cada subproceso que se conecte a la base de datos cifrada.

Las llamadas de transferencia de claves (llamadas de fbcrypt.dll en el ejemplo FEPF) deben realizarse antes de la conexión, en el mismo subproceso donde se establecerá la conexión.

Cuando trabajamos con muchas bases de datos (por ejemplo, un servidor web SaaS con muchas bases de datos de clientes), es importante recordar que cada invocación de fbcrypt_key() agrega una clave al almacenamiento de KeyHolder, asociada con la conexión actual.

Los valores de las claves deben establecerse antes de la conexión; después del adjunto, el valor de la clave no se puede cambiar.

En caso de desconexión, las claves no se descargan; se mantendrán en memoria hasta la descarga de fbcrypt.dll.

3.2. Aplicaciones Java

El controlador Java (JayBird) tiene su propia implementación (en Java puro) del protocolo de conexión de Firebird. Jaybird 4 (y 3.0.4+) agrega soporte para las devoluciones de llamada de cifrado de base de datos de Firebird 3 en la implementación de Java puro del protocolo versión 13.

Del Readme de Jaybird 4:

" La implementación actual es simple y solo admite responder con un valor estático de una propiedad de conexión. Tenga en cuenta que una respuesta de valor estático para el cifrado de base de datos no es muy segura, ya que puede conducir fácilmente a ataques de repetición o exposición no intencionada de claves.

Las versiones futuras de Jaybird (probablemente 5) introducirán soporte de plugins para plugins de cifrado de base de datos que requieran una devolución de llamada más compleja."

Prácticamente, esto significa que necesitamos establecer el valor para la devolución de llamada de cifrado (normalmente, es un nombre de clave y un par clave-valor) en la propiedad de conexión dbCryptConfig.

Por ejemplo:

Code
 edConnectionString.setText("jdbc:firebirdsql://localhost/g:/Databases/ODS12/crypt.fdb?lc_ctype=utf8&dbCryptConfig=MyKey:0xec,0xa1,0x52,0xf6,0x4d,0x27,0xda,0x93,0x53,0xe5,0x48,0x86,0xb9,0x7d,0xe2,0x8f,0x3b,0xfa,0xb7,0x91,0x22,0x5b,0x59,0x15,0x82,0x35,0xf5,0x30,0x1f,0x04,0xdc,0x75,");

También es posible especificar una cadena en base64 - del readme:

" Las cadenas con prefijo base64:: el resto de la cadena se decodifica como base64 a bytes.

Los caracteres de relleno = son opcionales, pero cuando están presentes deben ser válidos (es decir: si usa relleno, debe usar el número correcto de caracteres de relleno para la longitud).

Cuando el valor codificado en base64 contiene +, debe escaparse como %2B en la URL JDBC. Por compatibilidad hacia atrás con Jaybird 3, no podemos cambiar a la variante segura para URL de base64."

En la implementación de IBSurgeon del plugin de gestión de claves, dicha transmisión de la clave se considera más o menos insegura: si el cifrado del protocolo de red no está habilitado ( por cierto, para habilitarlo, establezca WireCrypt=Required en firebird.conf y no use autenticación heredada), la clave puede detectarse fácilmente con un analizador de tráfico de red como WireShark, por lo tanto, para habilitar la transmisión de claves de esta manera, es necesario establecer UnsafeClient=true en KeyHolder.conf del plugin de gestión de claves de IBSurgeon.

3.3 Aplicaciones .NET

El proveedor Firebird.NET implementa un esquema similar de intercambio de claves para bases de datos cifradas y también requiere establecer el parámetro UnsafeClient=true en KeyHolder.conf en FEPF.

Ejemplo de .NET de la cadena de conexión para bases de datos cifradas:

Code
string connectionString =
                "User=SYSDBA;" +
                "Password=masterkey;" +
                "Database=G:\\Databases\\ODS12.RYPT.FDB;" +
                "DataSource=localhost;" +
                "Port=3053;" +
                "Dialect=3;" +
                "Charset=NONE;" +
                "Role=;" +
                "Connection lifetime=15;" +
                "Pooling=true;" +
                "MinPoolSize=0;" +
                "MaxPoolSize=50;" +
                "Packet Size=8192;" +
                "ServerType=0;" +
                 "cryptkey = TXlLZXk6MHhlYywweG…...;";

Puede notar que la clave de cifrado se ve diferente que en el ejemplo para aplicaciones nativas y JayBird, esto se debe a que es el resultado de la transformación Base64, por lo que para obtener la clave para aplicaciones .NET o Java, es necesario calcular base64 de la cadena:

“MyKey:0xec,0xa1,0x52,0xf6,0x4d,0x27,0xda,0x93,0x53,0xe5,0x48,0x86,0xb9,0x7d,0xe2,0x8f,0x3b,0xfa,0xb7,0x91,0x22,0x5b,0x59,0x15,0x82,0x35,0xf5,0x30,0x1f,0x04,0xdc,0x75,”

y usarla como parámetro para “cryptkey=xxx;” con “;” al final de la cadena de conexión.

4. Instalación y configuración

Para habilitar el cifrado de base de datos y el plugin de gestión de claves para que se usen, es necesario especificar el nombre del plugin de cifrado en el archivo de configuración de Firebird firebird.conf:

Code
 KeyHolderPlugin = KeyHolder

O, alternativamente, en databases.conf, para el alias de la base de datos cifrada:

Code
myencrypted = C:\Temp\EMPLOYEE30.MPLOYEE30.FDB { KeyHolderPlugin = KeyHolder }

Luego, es necesario verificar que todos los archivos necesarios para el plugin estén en el servidor.

El ejemplo a continuación es para FEPF de IBSurgeon, pero otros plugins son más o menos similares:

en %FirebirdFolder$\plugins

Code
    • DbCrypt.dll
    • DbCrypt.conf
    • KeyHolder.dll
    • KeyHolder.conf - ¡solo para modo depuración!

En %FirebirdFolder$

Code
    • fbcrypt.dll
    • libcrypto-1_1-x64.dll
    • libssl-1_1-x64.dll
    • firebird.msg

Después de eso, podemos realizar el cifrado de prueba en el servidor, para ello, en isql:

Code
isql.exe localhost:C:\Temp\EMPLOYEE30.MPLOYEE30.FDB -user SYSDBA -pass masterkey
SQL>alter database encrypt with dbcrypt key red;
SQL> show database;
Database: localhost:C:\Temp\EMPLOYEE30.MPLOYEE30.FDB
….
ODS = 12.0
Database encrypted
Default Character set: NONE

Si estás en Linux, recuerda que las mayúsculas y minúsculas son importantes, por lo que el comando será:

Code
alter database encrypt with "DbCrypt" key Red;

Ahora, podemos probar el acceso del cliente a la base de datos cifrada. Para ello, eliminaremos (o renombraremos o editaremos) el archivo de configuración KeyHolder.conf, e intentaremos conectarnos a la base de datos cifrada con la aplicación de prueba simple.

Para esto, debemos colocar en la carpeta con la aplicación cliente los siguientes archivos:

  • Aplicación demo de FEPF- CryptTest.exe (32bit)
  • Archivos obligatorios:
    • fbclient.dll
    • fbcrypt.dll
    • libcrypto-1.1.dll
    • libssl-1.1-x64.dll
  • Archivos opcionales:
    • firebird.conf
    • en plugins
    • ◦ KeyHolder.conf
    • ◦ keyhodler.dll

En algunas implementaciones de plugins de gestión de claves, es posible cargar claves en la biblioteca del cliente (fbclient.dll), sin modificar el software del cliente.

Esto permite el trabajo transparente de las herramientas de desarrollo de Firebird (como Firebird SQL Studio, DatabaseWorkbench, IBExpert, FlameRobin, RedExpert, etc.), y el uso transparente de las herramientas de línea de comandos de Firebird (gfix.exe, nbackup.exe, etc.).

5. Cómo rastrear el progreso del cifrado

Firebird cifra una base de datos solo cuando tiene conexiones activas. El proceso de cifrado se ejecuta en un hilo paralelo separado, y para bases de datos grandes, el cifrado completo puede llevar un tiempo significativo.

Para rastrear el proceso de cifrado, ejecute una consulta SQL de MON$:

Code
select mon$crypt_page * 100.0 / mon$pages as Percent from mon$database;
commit;

o ejecute la herramienta gstat con el interruptor especial:

Code
gstat -e dbname

Database "D:\ENCDB\TESTENCRYPT.FDB"
Gstat execution time Tue Mar 16 11:45:11 2021

Database header page information:
        Flags                   0
        Generation              10697
        System Change Number    3
        Page size               8192
        ODS version             12.0
        Oldest transaction      7053
        Oldest active           7054
        Oldest snapshot         7054
        Next transaction        7054
        Sequence number         0
        Next attachment ID      17834
        Implementation          HW=Intel/i386 little-endian OS=Windows CC=MSVC
        Shadow count            0
        Page buffers            0
        Next header page        0
        Database dialect        3
        Creation date           Oct 9, 2019 6:42:31
        Attributes              encrypted, plugin DBCRYPT

    Variable header data:
        Database backup GUID:   {866B4967-ED58-427E-A481-DB9206CEA2ED}
        Crypt checksum: MUB2NTJqchh9RshmP6xFAiIc2iI=
        Key hash:       ask88tfWbinvC6b1JvS9Mfuh47c=
        Encryption key name:    RED
        Database GUID:  {323FE494-1771-4608-E99D-C1B69C84578B}
        *END*

Data pages: total 105, encrypted 105, non-crypted 0
Index pages: total 95, encrypted 95, non-crypted 0
Blob pages: total 0, encrypted 0, non-crypted 0
Generator pages: total 1, encrypted 1, non-crypted 0
Gstat completion time Tue Mar 16 11:45:11 2021

Tenga en cuenta que la ejecución de gstat puede ser un proceso largo.

6. Resumen

  1. El cifrado de bases de datos Firebird es una característica potente para proteger la información en las bases de datos contra accesos no autorizados.
  2. El proceso de cifrado requiere una biblioteca dinámica del lado del servidor: el plugin de cifrado (generalmente llamado DbCrypt), y, en la gran mayoría de las situaciones, el plugin de gestión de claves (generalmente llamado KeyHolder).
  3. La implementación segura y confiable de los plugins DbCrypt y KeyHolder debe realizarse teniendo en cuenta los tipos de ataques más populares.
  4. Para trabajar con la base de datos cifrada, las aplicaciones cliente deben transferir la clave de cifrado.
  5. La instalación y configuración del plugin de cifrado en el lado del servidor es trivial, requiere 1 parámetro en firebird.conf/databases.conf, y varios archivos.
  6. El proceso de cifrado puede ser largo, se realiza en un hilo de fondo separado, el progreso se puede rastrear con la llamada MON$ o gstat.

¿Qué sigue?

Estamos trabajando en una prueba de rendimiento detallada del cifrado de bases de datos Firebird. En general, el rendimiento es un 4-8% menor, pero depende del hardware y la configuración de Firebird. ¡Manténgase atento!

Contáctenos:

Envíe sus sugerencias, errores tipográficos, errores, etc., y cualquier pregunta por correo electrónico: [email protected]