Esta página foi traduzida por máquina. Leia o original em inglês. English

Biblioteca IBSurgeon

Como funciona a criptografia do banco de dados Firebird

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

O artigo é baseado nos materiais do workshop “Database Encryption” na Firebird Conference 2019 em Berlim, Alemanha. Ele descreve como funciona a criptografia de banco de dados Firebird, no nível do servidor, no lado do cliente, como configurar a criptografia de banco de dados, como usá-la a partir dos vários tipos de aplicativos (Delphi, Java, .NET). Os exemplos do artigo são baseados no IBSurgeon Firebird Framework de Cryptografia (FEPF), mas podem ser adaptados para a maioria das implementações de plugins de criptografia atualmente disponíveis.

Conteúdo:

  1. Por que precisamos de criptografia de banco de dados (e quando não precisamos)?
  2. Como a criptografia de banco de dados Firebird funciona no lado do servidor
  3. Qual parte do banco de dados é criptografada?
  4. Quando as páginas de dados são criptografadas?
  5. Como proteger a transferência de chaves?
  6. Como a criptografia Firebird funciona no lado do cliente
  7. Aplicativos nativos
  8. Aplicativos Java
  9. Aplicativos .NET
  10. Instalação e Configuração
  11. Como acompanhar o progresso da criptografia
  12. Resumo

1. Por que precisamos de criptografia de banco de dados (e quando não precisamos)?

A criptografia de banco de dados Firebird foi introduzida na versão Firebird 3.0 (juntamente com a criptografia do protocolo de transferência, que muitas vezes é confundida com o assunto discutido) e aumentou muito as capacidades de proteger dados contra acesso não autorizado. No entanto, não é uma panaceia, e é necessário entender seus pontos fortes e fracos para usá-la adequadamente.

Neste artigo, consideramos os detalhes internos da criptografia de banco de dados em nível básico, para dar aos desenvolvedores de aplicativos Firebird uma melhor compreensão de como funciona a criptografia de banco de dados.

Então, por que precisamos de criptografia de banco de dados?

  1. Para proteger bancos de dados com dados sensíveis/valiosos contra roubo “físico”. Se um intruso roubar o disco com uma cópia do banco de dados criptografado ou de alguma forma obtiver uma cópia do arquivo do banco de dados, não será possível ler dados dele sem uma chave apropriada, assim como não será possível usar software de recuperação como o FirstAID para extrair os dados. Claro, isso depende do algoritmo de criptografia e do poder computacional, mas quebrar AES256 exigirá muito tempo ou recursos computacionais muito caros.
  2. Para proteger o banco de dados contra acesso de aplicativos não autorizados sem chaves de criptografia. Exemplos são:
    • acesso direto com uma ferramenta de desenvolvedor por uma pessoa não autorizada, para alterar informações sensíveis (por exemplo, transações monetárias),
    • alterar ou roubar lógica de negócios (textos de procedimentos armazenados e triggers).
  3. Proteger bancos de dados com dados pré-preenchidos contra exportação ou acesso por aplicativos não autorizados.
  4. Governos recentemente introduziram leis de proteção de dados (GDPR/DSVGO na Europa, LGPD no Brasil, etc.) que exigem, entre outras coisas, um nível mais alto de proteção para dados pessoais e outros dados sensíveis, e a criptografia é mencionada como uma das medidas de proteção adequadas.

Quando a criptografia de banco de dados não é útil?

Em alguns casos, é melhor usar os recursos de segurança e configuração do Firebird em vez de criptografia de banco de dados:

  • Para proteger o banco de dados contra acesso físico pela rede, é necessário configurar o acesso à rede: ou seja, fechar pastas compartilhadas de rede, porque o Firebird não requer acesso compartilhado de rede aos arquivos do banco de dados, e reforçar as permissões de segurança (para Linux, por exemplo, os arquivos do banco de dados devem ter acesso de leitura e gravação apenas para o usuário “firebird”).
  • Para restringir o acesso ao banco de dados específico para um subconjunto específico de usuários, a solução mais fácil será configurar um banco de dados de segurança separado.
  • Para restringir o acesso aos objetos do banco de dados (tabelas, procedimentos armazenados), é necessário usar os mecanismos de segurança do Firebird: usuários, papéis, etc.

Claro, ambas as listas acima estão incompletas, mas dão uma ideia de quando você precisa ou não de criptografia de banco de dados.

2. Como a criptografia de banco de dados Firebird funciona no lado do servidor

Vamos passar pelos detalhes internos da criptografia de banco de dados Firebird, e começar com a parte do servidor.

2.1. Qual parte do banco de dados é criptografada?

A primeira coisa que precisamos considerar é qual parte do banco de dados é criptografada? Como você provavelmente sabe, o banco de dados Firebird consiste em partes de tamanho igual, chamadas “páginas de banco de dados”. Existem vários tipos dessas páginas, cada tipo serve a um propósito específico.

Abaixo você pode ver a figura com os principais tipos de dados:

Figura 1. Tipos de páginas de banco de dados

Algumas páginas são projetadas para armazenar dados dos usuários, e outras são necessárias para armazenar informações do sistema, como transações e páginas de inventário de páginas (mais detalhes sobre páginas de banco de dados estão disponíveis aqui).

Quando o banco de dados Firebird é criptografado, apenas páginas com dados de usuário são criptografadas: páginas de dados, índices, geradores e BLOBs:

Figura 2. Apenas páginas de banco de dados com dados de usuários são criptografadas

Observe que os metadados do banco de dados (procedimentos armazenados, tabelas, visões, triggers, nomes de geradores, etc.) não diferem dos “dados de usuários” dentro da parte do mecanismo responsável pela criptografia, e eles são criptografados.

Por que as páginas do sistema não são criptografadas? Por razões de desempenho, principalmente, e devido ao fato de que elas não contêm dados sensíveis que exigem proteção.

A página de cabeçalho do banco de dados não é criptografada, porque contém informações necessárias para a criptografia (por exemplo, o nome da chave).

2.2. Quando as páginas de dados são criptografadas?

Quando um usuário executa SELECT em um banco de dados criptografado, os dados são lidos do arquivo criptografado, mas chegam à grade de resultados do aplicativo em forma não criptografada.

Vamos considerar os detalhes desse processo:

Figura 3. Quando as páginas de banco de dados são criptografadas?

Normalmente, o processo começa com uma série de leituras de páginas de banco de dados de um arquivo de banco de dados, e elas são armazenadas em cache no cache de arquivos do sistema operacional.

O Firebird também pode ser configurado para ignorar o cache de arquivos e usar apenas seu próprio cache, mas por padrão, o cache de arquivos é usado.

Depois disso, o Firebird lê as páginas e as coloca no cache de páginas do Firebird (definido pelo parâmetro DefaultDBCachePages no firebird.conf e/ou databases.conf ou na página de cabeçalho do banco de dados).

Então, as páginas do cache são selecionadas para o conjunto de resultados da instrução SQL específica (SELECT no nosso exemplo).

A figura abaixo mostra os detalhes:

Figura 4. As páginas são criptografadas entre o cache do Firebird e o cache de arquivos do SO

Então, as páginas de banco de dados são criptografadas no cache de arquivos do SO, mas chegam ao cache de páginas do Firebird não criptografadas, e vice-versa.

A parte do software Firebird responsável pela criptografia/descriptografia é chamada de “plugin de criptografia”. Como a maioria das implementações de plugins (conhecidas pelos autores) é chamada de DbCrypt, nos referiremos a ela como DbCrypt.

Na figura abaixo você pode ver variantes para Windows (DbCrypt.dll) e Linux (libDbCrypt.so):

Figura 5. O plugin de criptografia (DbCrypt) está fazendo criptografia/descriptografia

Se você olhar para esta imagem por tempo suficiente, a próxima pergunta aparecerá rapidamente: como o DbCrypt obtém a chave adequada para criptografar/descriptografar páginas de banco de dados?

A resposta - existe outro plugin para gerenciamento de chaves.

O nome típico para gerenciamento de chaves é KeyHolder, que serve como uma instalação de armazenamento/gerenciamento de chaves para o plugin de criptografia (DbCrypt). O KeyHolder implementa a interface para gerenciamento de chaves que é usada pelo DbCrypt.

Figura 6. DbCrypt e KeyHolder

O que significa “gerenciamento de chaves”?

No caso mais simples, o DbCrypt pode ler chaves do arquivo no servidor. O arquivo pode ser um simples arquivo de texto simples, que pode ser escondido em um lugar “secreto” ou em um pendrive USB, ou pode ser um arquivo criptografado (usando Windows Crypto API, por exemplo, ou com uma chave interna embutida).

O arquivo de chaves pode conter várias chaves, armazenadas, por conveniência, como uma lista nomeada, e pode parecer assim (o exemplo abaixo é retirado do Framework de Cryptografia da 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,

Quando o banco de dados é criptografado, suas páginas de cabeçalho permanecem não criptografadas para armazenar informações sobre o plugin de criptografia e o nome da chave, e você pode ver essas informações com o comando “gstat -h nomedobanco”:

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*

O DbCrypt pode processar páginas para vários bancos de dados e várias chaves:

Figura 7. Múltiplas chaves para múltiplos bancos de dados no mesmo servidor (ou seja, instância Firebird)

Escolhendo a chave correta

Muitas vezes os desenvolvedores fazem a pergunta “Como o plugin reconhece qual chave é para qual banco de dados?” A resposta é bem simples: pelo nome da chave, que está armazenado na página de cabeçalho do banco de dados.

Menos frequente, mas ainda importante, é a pergunta - e se o nome da chave for como está registrado no cabeçalho, mas o valor da chave for diferente? Para evitar erros de leitura de página devido à chave errada, o plugin DbCrypt armazena a sequência de teste criptografada (dígitos 0…F) no cabeçalho, e então a chave é ativada, o plugin tenta criptografar os dados de amostra com uma chave e comparar seu hash com o resultado armazenado, para garantir que o valor da chave passado está realmente correto para este banco de dados específico.

A abordagem em que o plugin de criptografia lê chaves diretamente é simples e benéfica para depuração, testes de desempenho, etc., porque implementa a criptografia de forma transparente: ou seja, aplicativos clientes e ferramentas de desenvolvedores não sabem que o banco de dados está criptografado.

No entanto, na realidade, precisamos restringir o acesso de aplicativos ao banco de dados: apenas o aplicativo cliente que tem uma chave deve ser capaz de se conectar ao banco de dados criptografado.

Para isso, precisamos do plugin KeyHolder, para obter a chave do aplicativo cliente (que geralmente está em outro computador) através do protocolo de rede do Firebird.

2.3. Como proteger a transferência de chaves?

É possível que queiramos proteger o banco de dados na situação em que o cliente decide obter acesso direto ao banco de dados criptografado, ignorando os aplicativos autorizados (muitos fornecedores querem restringir dados do acesso direto, seja somente leitura ou leitura e escrita).

Isso é equivalente à situação em que um intruso tem acesso ao servidor, mas não tem as chaves.

Vamos considerar os seguintes cenários de ataque para interceptar chaves no lado do servidor:

  1. Quando o intruso cria o plugin de criptografia falso (DBCrypt.dll) e o coloca no servidor, e quando o KeyHolder passa a chave, o DbCrypt falso faz o dump da chave:

Figura 8. Ataque com DbCrypt.dll falso

  1. Quando o intruso cria o arquivo firebird.exe falso e faz o dump com ele:

Figura 9. Ataque com firebird.exe falso

Para se proteger contra tais ataques, a boa implementação de plugins de criptografia e gerenciamento de chaves precisa proteger a troca de chaves.

A troca de chaves pode ser protegida com criptografia assimétrica com o par de chaves pública/privada.

Essas chaves são geradas durante o processo de build e incorporadas para o par específico de plugins de criptografia e gerenciamento de chaves. Para a melhor proteção, é necessário usar pares especialmente construídos de DbCrypt/KeyHolder.

Quando DbCrypt e KeyHolder trocam as chaves, eles usam o seguinte protocolo (é simplificado, mas a ideia é clara, eu acho):

Code
DbCrypt → KeyHolder:
	Me Dê a Chave do Banco de Dados Com este Salt
KeyHolder:
	Criptografa DbKey Com a chave pública usando salt do DbCrypt
	Transfere DbKey Criptografada para DbCrypt
DbCrypt:
	Descriptografa DbKey Com a Chave Privada
	Valida a correção do salt
	Pronto Para Trabalhar

Mais ou menos o mesmo protocolo é usado para trocar chaves entre instâncias do KeyHolder, e para troca de chaves entre uma aplicação cliente e o KeyHolder.

Observe que a criptografia e a correção das chaves transferidas dependem da implementação do plugin; o mecanismo Firebird fornece apenas o serviço básico de transferência de baixo nível “enviar N bytes desta instância de plugin para aquela instância de plugin”.

Resumo para a parte do servidor da criptografia

  • A criptografia/descriptografia é feita pelo plugin de criptografia do banco de dados (DbCrypt), página por página, durante a troca de dados entre o cache de arquivos do Sistema Operacional e o cache de páginas do Firebird
  • O gerenciamento de chaves pode ser implementado de forma simples quando o DbCrypt lê as chaves diretamente, mas geralmente é feito com o plugin de gerenciamento de chaves (KeyHolder)

Agora vamos descobrir como as aplicações cliente trabalham com bancos de dados criptografados.

3. Como a criptografia do Firebird funciona no lado do cliente

3.1. Aplicações nativas

Para entender o que acontece quando uma aplicação cliente se conecta ao banco de dados criptografado, vamos considerar o processo de conexão regular ao banco de dados não criptografado para aplicações nativas.

Observe: daqui em diante, “nativo” significa que tal aplicação estabelece uma conexão de rede com o servidor usando fbclient.dll; geralmente, essa aplicação é construída em Delphi, C++, PHP. Diferente das aplicações nativas, Java e .NET implementam sua própria versão do protocolo, eles serão considerados abaixo.

Processo de conexão:

  1. A aplicação cliente carrega a biblioteca do cliente
  2. fbclient.dll - aplicativos nativos Windows
  3. libfbclient.so - aplicativos nativos Linux
  4. A aplicação cliente inicia uma conexão, enviando
  5. Nome de usuário, ex.: SYSDBA
  6. Senha, ex.: masterkey
  7. Caminho/alias do banco de dados

No caso de um banco de dados criptografado, uma etapa adicional é necessária: é necessário passar o nome da chave de criptografia e seu valor.

É importante dizer que passar a chave deve ser feito antes da conexão regular, devido ao fato de que as páginas de dados com metadados, incluindo nome do proprietário do banco de dados, charset, etc., são criptografadas.

Então, isso nos leva ao seguinte:

  1. Uma ida e volta de rede adicional é necessária para passar a chave antes da conexão regular
  2. A transferência de chave da aplicação cliente para o Firebird requer codificação com o uso de criptografia assimétrica e implementação de interface de callback, pode ser bastante complexa. Para simplificar essa tarefa, os fornecedores de plugins fornecem um exemplo do código para conectar, ou, como no framework de plugins do IBSurgeon, criam a biblioteca adicional fbcrypt.dll/libfbcrypt.so, que implementa a interface fácil de usar adequada para transferir chaves da aplicação cliente.

Para conectar uma aplicação nativa (que usa fbclient.dll) ao banco de dados criptografado, 3 chamadas devem ser feitas. Abaixo está um exemplo em Delphi (simplificado, sem tratamento de erros):

No manipulador de eventos BeforeConnect:

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

 // Então conecte como de costume
Database1.Active:=True;

Na figura abaixo você pode ver a visão geral do processo de conexão com um banco de dados criptografado na aplicação nativa:

Figura 10. Processo de conexão ao banco de dados criptografado para aplicações nativas

E quanto à segurança de threads no caso de aplicações cliente multi-thread?

Deixe-me lembrá-lo de alguns pontos gerais da implementação de aplicações cliente multi-thread.

Desde o Firebird 2.5, várias threads dentro da aplicação podem usar com segurança o único attachment ao banco de dados, porque toda a sincronização necessária é feita dentro da fbclient.dll.

No entanto, neste caso, as threads poderão trabalhar com o attachment apenas uma por vez.

Isso é aceitável para aplicações que não exigem troca de dados de alto desempenho com o banco de dados - se não for um problema esperar para executar uma consulta SQL de uma thread quando outra thread está executando outro SQL, é mais fácil usar um modelo simples quando 1 attachment é compartilhado entre várias threads.

Se a aplicação exigir executar consultas SQL em paralelo (ou seja, é uma aplicação cliente em escala total), é melhor usar uma thread separada para cada conexão.

A situação com a troca de chaves para os attachments aos bancos de dados criptografados é um pouco mais complexa.

Em cada attachment, a biblioteca do cliente transfere as chaves do cliente, mas isso não está diretamente relacionado às threads na aplicação cliente; a situação depende da API usada.

Como você sabe, a biblioteca do cliente Firebird desde a versão 3.0 oferece 2 tipos de API: nova API Orientada a Objetos, baseada no conceito de providers, e a API legada isc_ API, implementada como uma solução alternativa, para manter compatibilidade com drivers Firebird antigos.

Se a nova API de cliente orientada a objetos for usada, é suficiente criar o provider, fornecê-lo com as chaves necessárias, e então usá-lo para os novos attachments.

Se a isc_ API de cliente for usada, para cada attachment a biblioteca do cliente criará seu próprio provider temporário, que não é diretamente visível ou acessível pelo usuário final.

Neste caso, a chave é transferida exatamente da thread onde isc_attach_database é invocada, e o armazenamento local de thread é usado para armazenar essa chave.

Na prática, como quase todas as bibliotecas de cliente usam a isc_ API (no momento, entre os drivers populares, apenas o driver Python usa a API OO), é necessário invocar fb_database_crypt_callback() em cada thread que se conecta ao banco de dados criptografado.

As chamadas de transferência de chave (chamadas fbcrypt.dll no exemplo FEPF) devem ser feitas antes da conexão, na mesma thread onde a conexão será estabelecida.

Quando trabalhamos com muitos bancos de dados (por exemplo, servidor web SaaS com muitos bancos de dados de clientes), é importante lembrar que cada invocação de fbcrypt_key() adiciona uma chave ao armazenamento do KeyHolder, associada à conexão atual.

Os valores das chaves devem ser definidos antes da conexão; após o attachment, o valor da chave não pode ser alterado.

Em caso de detach, as chaves não são descarregadas; elas serão mantidas na memória até o descarregamento da fbcrypt.dll.

3.2. Aplicações Java

O driver Java (JayBird) tem sua própria implementação (em Java puro) do protocolo de conexão Firebird. Jaybird 4 (e 3.0.4+) adiciona suporte para callbacks de criptografia de banco de dados Firebird 3 na implementação Java pura do protocolo versão 13.

Do Jaybird 4 Readme:

" A implementação atual é simples e só suporta responder com um valor estático de uma propriedade de conexão. Esteja ciente de que uma resposta de valor estático para criptografia de banco de dados não é muito segura, pois pode facilmente levar a ataques de replay ou exposição não intencional de chaves.

Versões futuras do Jaybird (provavelmente 5) introduzirão suporte a plugins para plugins de criptografia de banco de dados que exigem um callback mais complexo."

Na prática, isso significa que precisamos definir o valor para o callback de criptografia (normalmente, é um par nome de chave e valor de chave) na propriedade de conexão dbCryptConfig.

Por exemplo:

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,");

Também é possível especificar string em base64 - do readme:

" Strings prefixadas com base64:: o restante da string é decodificado como base64 para bytes.

Os caracteres de preenchimento = são opcionais, mas quando presentes devem ser válidos (ou seja: se você usar preenchimento, deve usar o número correto de caracteres de preenchimento para o comprimento).

Quando o valor codificado em base64 contém +, ele deve ser escapado como %2B na URL JDBC. Para compatibilidade retroativa com Jaybird 3, não podemos mudar para a variante URL-safe do base64."

Na implementação do IBSurgeon do plugin de gerenciamento de chaves, tal transmissão da chave é considerada mais ou menos insegura: se a criptografia do protocolo de rede não estiver habilitada ( a propósito, para habilitá-la, defina em firebird.conf WireCrypt=Required e não use autenticação legada), a chave pode ser facilmente detectada com um analisador de tráfego de rede como WireShark, então, para habilitar a transmissão de chaves desta forma, é necessário definir UnsafeClient=true no KeyHolder.conf do plugin de gerenciamento de chaves do IBSurgeon.

3.3 Aplicações .NET

O provider Firebird.NET implementa um esquema similar de troca de chaves para bancos de dados criptografados e também exige definir o parâmetro UnsafeClient=true no KeyHolder.conf no FEPF.

Exemplo .NET da string de conexão para bancos de dados criptografados:

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…...;";

Você pode notar que a chave de criptografia parece diferente do exemplo para aplicações nativas e JayBird, isso porque é o resultado da transformação Base64, então para obter a chave para aplicação .NET ou Java, é necessário calcular base64 da string:

“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,”

e usá-la como parâmetro para “cryptkey=xxx;” com “;” no final da string de conexão.

4. Instalação e Configuração

Para habilitar o plugin de criptografia de banco de dados e gerenciamento de chaves para ser usado, é necessário especificar o nome do plugin de criptografia no arquivo de configuração do Firebird firebird.conf:

Code
 KeyHolderPlugin = KeyHolder

Ou, alternativamente, em databases.conf, para o alias do banco de dados criptografado:

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

Então, é necessário verificar se todos os arquivos necessários para o plugin estão no servidor.

O exemplo abaixo é para o FEPF do IBSurgeon, mas outros plugins são mais ou menos similares:

em %FirebirdFolder$\plugins

Code
    • DbCrypt.dll
    • DbCrypt.conf
    • KeyHolder.dll
    • KeyHolder.conf - apenas para modo de depuração!

Em %FirebirdFolder$

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

Depois disso, podemos realizar a criptografia de teste no servidor. Para isso, no 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

Se você estiver no Linux, lembre-se de que maiúsculas e minúsculas são importantes, então o comando será:

Code
alter database encrypt with "DbCrypt" key Red;

Agora, podemos testar o acesso do cliente ao banco de dados criptografado. Para isso, removeremos (ou renomearemos ou editaremos) o arquivo de configuração KeyHolder.conf e tentaremos conectar ao banco de dados criptografado com o aplicativo de teste simples.

Para isso, devemos colocar na pasta do aplicativo cliente os seguintes arquivos:

  • Aplicativo de demonstração do FEPF- CryptTest.exe (32 bits)
  • Arquivos obrigatórios:
    • fbclient.dll
    • fbcrypt.dll
    • libcrypto-1.1.dll
    • libssl-1.1-x64.dll
  • Arquivos opcionais:
    • firebird.conf
    • em plugins
    • ◦ KeyHolder.conf
    • ◦ keyhodler.dll

Em algumas implementações de plugins de gerenciamento de chaves, é possível carregar as chaves na biblioteca do cliente (fbclient.dll), sem modificação do software cliente.

Isso permite o funcionamento transparente das ferramentas de desenvolvimento Firebird (como Firebird SQL Studio, DatabaseWorkbench, IBExpert, FlameRobin, RedExpert, etc.) e o uso transparente das ferramentas de linha de comando do Firebird (gfix.exe, nbackup.exe, etc.).

5. Como acompanhar o progresso da criptografia

O Firebird criptografa um banco de dados apenas quando há conexões ativas. O processo de criptografia é executado em uma thread paralela separada e, para bancos de dados grandes, a criptografia completa pode levar um tempo significativo.

Para acompanhar o processo de criptografia, execute uma consulta SQL do MON$:

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

ou execute a ferramenta gstat com a opção 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

Observe que a execução do gstat pode ser um processo demorado.

6. Resumo

  1. A criptografia de banco de dados Firebird é um recurso poderoso para proteger as informações nos bancos de dados contra acesso não autorizado.
  2. O processo de criptografia requer uma biblioteca dinâmica no servidor - o plugin de criptografia (geralmente chamado DbCrypt) e, na grande maioria das situações, o plugin de gerenciamento de chaves (geralmente chamado KeyHolder).
  3. A implementação segura e confiável dos plugins DbCrypt e KeyHolder deve ser feita considerando os tipos de ataque mais populares.
  4. Para trabalhar com o banco de dados criptografado, os aplicativos cliente devem transferir a chave de criptografia.
  5. A instalação e configuração do plugin de criptografia no servidor é trivial, exigindo 1 parâmetro no firebird.conf/databases.conf e vários arquivos.
  6. O processo de criptografia pode ser demorado, é feito em uma thread de segundo plano separada, e o progresso pode ser acompanhado com a chamada MON$ ou gstat.

O que vem a seguir?

Estamos trabalhando em um teste detalhado de desempenho da criptografia de banco de dados Firebird. Em geral, o desempenho é 4-8% menor, mas depende do hardware e das configurações do Firebird. Fique atento!

Fale conosco:

Envie suas sugestões, erros de digitação, erros, etc., e quaisquer perguntas por e-mail: [email protected]