Cette page a été traduite automatiquement. Lisez l'original en anglais. English

Bibliothèque IBSurgeon

Comment fonctionne le chiffrement de la base de données Firebird

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

L’article est basé sur les matériaux de l’atelier « Chiffrement de base de données » lors de la conférence Firebird 2019 à Berlin, en Allemagne. Il décrit comment fonctionne le chiffrement des bases de données Firebird, au niveau du serveur, côté client, comment configurer le chiffrement de la base de données, et comment l’utiliser depuis différents types d’applications (Delphi, Java, .NET). Les exemples de l’article sont basés sur IBSurgeon Firebird Encryption Framework (FEPF) mais peuvent être adaptés à la majorité des implémentations de plugins de chiffrement actuellement disponibles.

Sommaire :

  1. Pourquoi avons-nous besoin du chiffrement de base de données (et quand n’en avons-nous pas besoin) ?
  2. Comment fonctionne le chiffrement des bases de données Firebird côté serveur
  3. Quelle partie de la base de données est chiffrée ?
  4. Quand les pages de données sont-elles chiffrées ?
  5. Comment protéger le transfert des clés ?
  6. Comment fonctionne le chiffrement Firebird côté client
  7. Applications natives
  8. Applications Java
  9. Applications .NET
  10. Installation et configuration
  11. Comment suivre la progression du chiffrement
  12. Résumé

1. Pourquoi avons-nous besoin du chiffrement de base de données (et quand n’en avons-nous pas besoin) ?

Le chiffrement des bases de données Firebird a été introduit dans la version Firebird 3.0 (avec le chiffrement du protocole de transfert, souvent confondu avec le sujet abordé), et a considérablement augmenté les capacités de protection des données contre les accès non autorisés. Cependant, ce n’est pas une panacée, et il est nécessaire de comprendre ses forces et ses faiblesses pour l’utiliser correctement.

Dans cet article, nous examinons les mécanismes internes du chiffrement de base de données à un niveau de base, afin de donner aux développeurs d’applications Firebird une meilleure compréhension du fonctionnement du chiffrement des bases de données.

Alors, pourquoi avons-nous besoin du chiffrement de base de données ?

  1. Pour protéger les bases de données contenant des données sensibles/précieuses contre le vol « physique ». Si un intrus vole le disque contenant une copie de la base de données chiffrée ou obtient d’une manière ou d’une autre une copie du fichier de base de données, il ne sera pas possible de lire les données sans une clé appropriée, et il ne sera pas non plus possible d’utiliser un logiciel de récupération comme FirstAID pour extraire les données. Bien sûr, cela dépend de l’algorithme de chiffrement et de la puissance de calcul, mais casser AES256 demandera trop de temps ou des ressources de calcul trop coûteuses.
  2. Pour protéger la base de données contre l’accès par des applications non autorisées sans clés de chiffrement. Les exemples sont :
    • l’accès direct avec un outil de développement par une personne non autorisée, pour modifier des informations sensibles (par exemple, des transactions monétaires),
    • la modification ou le vol de la logique métier (textes des procédures stockées et des déclencheurs).
  3. Protéger les bases de données pré-remplies contre l’exportation vers ou l’accès par des applications non autorisées.
  4. Les gouvernements ont récemment introduit des lois sur la protection des données (GDPR/DSVGO en Europe, LGPD au Brésil, etc.) qui exigent, entre autres, un niveau plus élevé de protection des données personnelles et autres données sensibles, et le chiffrement est mentionné comme l’une des mesures de protection adéquates.

Quand le chiffrement de base de données n’est-il pas utile ?

Dans certains cas, il est préférable d’utiliser les capacités de sécurité et de configuration de Firebird plutôt que le chiffrement de base de données :

  • Pour protéger la base de données contre l’accès physique via le réseau, il est nécessaire de configurer l’accès réseau : c’est-à-dire fermer les dossiers partagés réseau, car Firebird n’exige pas d’accès partagé réseau aux fichiers de base de données, et renforcer les permissions de sécurité (pour Linux, par exemple, les fichiers de base de données doivent avoir un accès en lecture-écriture uniquement pour l’utilisateur « firebird »).
  • Pour restreindre l’accès à une base de données spécifique pour un sous-ensemble spécifique d’utilisateurs, la solution la plus simple sera de configurer une base de sécurité distincte.
  • Pour restreindre l’accès aux objets de la base de données (tables, procédures stockées), il est nécessaire d’utiliser les mécanismes de sécurité de Firebird : utilisateurs, rôles, etc.

Bien sûr, les deux listes ci-dessus sont incomplètes, mais elles vous donnent une idée de quand vous avez besoin ou non du chiffrement de base de données.

2. Comment fonctionne le chiffrement des bases de données Firebird côté serveur

Examinons les détails internes du chiffrement des bases de données Firebird, en commençant par la partie serveur.

2.1. Quelle partie de la base de données est chiffrée ?

La première chose à considérer est : quelle partie de la base de données est chiffrée ? Comme vous le savez probablement, une base de données Firebird se compose de parties de taille égale, appelées « pages de base de données ». Il existe plusieurs types de ces pages, chacun servant à un objectif spécifique.

Ci-dessous, vous pouvez voir la figure avec les principaux types de données :

Figure 1. Types de pages de base de données

Certaines pages sont conçues pour stocker les données des utilisateurs, et d’autres sont nécessaires pour stocker des informations système, comme les transactions et les pages d’inventaire de pages (plus de détails sur les pages de base de données sont disponibles ici).

Lorsqu’une base de données Firebird est chiffrée, seules les pages contenant des données utilisateur sont chiffrées : pages de données, index, générateurs et BLOBs :

Figure 2. Seules les pages de base de données contenant les données des utilisateurs sont chiffrées

Veuillez noter que les métadonnées de la base de données (procédures stockées, tables, vues, déclencheurs, noms de générateurs, etc.) ne diffèrent pas des « données utilisateur » dans la partie du moteur responsable du chiffrement, et elles sont chiffrées.

Pourquoi les pages système ne sont-elles pas chiffrées ? Principalement pour des raisons de performance, et en raison du fait qu’elles ne contiennent pas de données sensibles nécessitant une protection.

La page d’en-tête de la base de données n’est pas chiffrée, car elle contient les informations nécessaires au chiffrement (par exemple, le nom de la clé).

2.2. Quand les pages de données sont-elles chiffrées ?

Lorsqu’un utilisateur exécute un SELECT sur une base de données chiffrée, les données sont lues depuis le fichier chiffré mais arrivent dans la grille de résultats de l’application sous forme non chiffrée.

Examinons les détails de ce processus :

Figure 3. Quand les pages de base de données sont-elles chiffrées ?

Habituellement, le processus commence par une série de lectures de pages de base de données depuis un fichier de base de données, et elles sont mises en cache dans le cache de fichiers du système d’exploitation.

Firebird peut également être configuré pour contourner le cache de fichiers et utiliser uniquement son propre cache, mais par défaut, le cache de fichiers est utilisé.

Ensuite, Firebird lit les pages et les place dans le cache de pages Firebird (défini par le paramètre DefaultDBCachePages dans firebird.conf et/ou databases.conf ou dans la page d’en-tête de la base de données).

Ensuite, les pages du cache sont sélectionnées pour le jeu de résultats de la requête SQL particulière (SELECT dans notre exemple).

La figure ci-dessous montre les détails :

Figure 4. Les pages sont chiffrées entre le cache Firebird et le cache de fichiers du système d’exploitation

Ainsi, les pages de base de données sont chiffrées dans le cache de fichiers du système d’exploitation mais arrivent dans le cache de pages Firebird non chiffrées, et vice versa.

La partie du logiciel Firebird responsable du chiffrement/déchiffrement est appelée « plugin de chiffrement ». Étant donné que la majorité des implémentations de plugins (connues des auteurs) sont appelées DbCrypt, nous y ferons référence sous le nom de DbCrypt.

Sur la figure ci-dessous, vous pouvez voir les variantes pour Windows (DbCrypt.dll) et Linux (libDbCrypt.so) :

Figure 5. Le plugin de chiffrement (DbCrypt) effectue le chiffrement/déchiffrement

Si vous regardez cette image assez longtemps, la question suivante apparaîtra assez rapidement : comment DbCrypt obtient-il la bonne clé pour chiffrer/déchiffrer les pages de base de données ?

La réponse - il existe un autre plugin pour la gestion des clés.

Le nom typique pour la gestion des clés est KeyHolder, qui sert de dispositif de stockage/gestion des clés pour le plugin de chiffrement (DbCrypt). KeyHolder implémente l’interface de gestion des clés utilisée par DbCrypt.

Figure 6. DbCrypt et KeyHolder

Que signifie « gestion des clés » ?

Dans le cas le plus simple, DbCrypt peut lire les clés depuis un fichier sur le serveur. Le fichier peut être un simple fichier texte brut, qui peut être caché dans un endroit « secret » ou sur une clé USB, ou peut être un fichier chiffré (en utilisant l’API Crypto de Windows, par exemple, ou avec une clé interne intégrée).

Le fichier de clés peut contenir plusieurs clés, stockées, pour plus de commodité, sous forme de liste nommée, et peut ressembler à ceci (l’exemple ci-dessous est tiré du Encryption Framework 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,

Lorsque la base de données est chiffrée, ses pages d’en-tête restent non chiffrées pour stocker les informations sur le plugin de chiffrement et le nom de la clé, et vous pouvez voir ces informations avec la commande « gstat -h nomdelabase » :

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 peut traiter les pages de plusieurs bases de données et plusieurs clés :

Figure 7. Plusieurs clés pour plusieurs bases de données sur le même serveur (c’est-à-dire, instance Firebird)

Choix de la clé correcte

Les développeurs posent souvent la question : « Comment le plugin reconnaît-il quelle clé correspond à quelle base de données ? » La réponse est assez simple : par le nom de la clé, stocké sur la page d’en-tête de la base de données.

Moins fréquente, mais toujours importante, la question est : que se passe-t-il si le nom de la clé est tel qu’il est enregistré dans l’en-tête, mais que la valeur de la clé est différente ? Pour éviter les erreurs de lecture de pages dues à une mauvaise clé, le plugin DbCrypt stocke une séquence de test chiffrée (chiffres 0…F) dans l’en-tête, puis lorsque la clé est activée, le plugin essaie de chiffrer les données d’échantillon avec la clé et de comparer son hash avec le résultat stocké, pour s’assurer que la valeur de clé fournie est réellement correcte pour cette base de données particulière.

L’approche où le plugin de chiffrement lit directement les clés est simple et bénéfique pour le débogage, les tests de performance, etc., car elle implémente le chiffrement de manière transparente : c’est-à-dire que les applications clientes et les outils de développement ne savent pas que la base de données est chiffrée.

Cependant, en réalité, nous devons restreindre l’accès des applications à la base de données : seule l’application cliente qui possède une clé devrait pouvoir se connecter à la base de données chiffrée.

Pour cela, nous avons besoin du plugin KeyHolder, pour obtenir la clé depuis l’application cliente (qui se trouve généralement sur un autre ordinateur) via le protocole réseau Firebird.

2.3. Comment protéger le transfert des clés ?

Il est possible que nous voulions protéger la base de données dans la situation où le client décide d’obtenir un accès direct à la base de données chiffrée, en contournant les applications autorisées (de nombreux fournisseurs veulent restreindre les données contre l’accès direct, soit en lecture seule, soit en lecture-écriture).

Cela équivaut à la situation où un intrus a accès au serveur mais ne possède pas les clés.

Examinons les scénarios d’attaque suivants pour intercepter les clés côté serveur :

  1. Lorsque l’intrus crée un faux plugin de chiffrement (DBCrypt.dll) et le place sur le serveur, et lorsque KeyHolder transmet la clé, le faux DbCrypt effectue un dump de la clé :

Figure 8. Attaque avec un faux DbCrypt.dll

  1. Lorsque l’intrus crée un faux fichier firebird.exe et effectue un dump avec celui-ci :

Figure 9. Attaque avec un faux firebird.exe

Afin de se protéger contre de telles attaques, une bonne implémentation des plugins de chiffrement et de gestion des clés doit protéger l’échange de clés.

L’échange de clés peut être protégé par un chiffrement asymétrique avec une paire de clés publique/privée.

Ces clés sont générées lors du processus de compilation et intégrées pour la paire spécifique de plugins de chiffrement et de gestion des clés. Pour une protection optimale, il est nécessaire d’utiliser des paires DbCrypt/KeyHolder spécialement construites.

Lorsque DbCrypt et KeyHolder échangent les clés, ils utilisent le protocole suivant (il est simplifié, mais l’idée est claire, je suppose) :

Code
DbCrypt → KeyHolder :
	Donne-moi la clé de base de données avec ce sel
KeyHolder :
	Chiffre DbKey avec la clé publique en utilisant le sel de DbCrypt
	Transfère la DbKey chiffrée à DbCrypt
DbCrypt :
	Déchiffre DbKey avec la clé privée
	Valide la correctitude du sel
	Prêt à fonctionner

Plus ou moins le même protocole est utilisé pour échanger les clés entre les instances de KeyHolder, et pour l’échange de clés entre une application cliente et KeyHolder.

Veuillez noter que le chiffrement et la correctitude des clés transférées dépendent de l’implémentation du plugin ; le moteur Firebird fournit uniquement un service de transfert de bas niveau de base « envoyer N octets de cette instance de plugin à cette instance de plugin ».

Résumé pour la partie serveur du chiffrement

  • Le chiffrement/déchiffrement est effectué par le plugin de chiffrement de base de données (DbCrypt), page par page, lors de l’échange de données entre le cache de fichiers du système d’exploitation et le cache de pages Firebird
  • La gestion des clés peut être implémentée de manière simple lorsque DbCrypt lit les clés directement, mais elle est généralement effectuée avec le plugin de gestion des clés (KeyHolder)

Découvrons maintenant comment les applications clientes fonctionnent avec des bases de données chiffrées.

3. Comment fonctionne le chiffrement Firebird côté client

3.1. Applications natives

Afin de comprendre ce qui se passe lorsqu’une application cliente se connecte à une base de données chiffrée, examinons le processus de connexion standard à une base de données non chiffrée pour les applications natives.

Veuillez noter : à partir d’ici et ci-dessous, « natif » signifie qu’une telle application établit une connexion réseau avec le serveur en utilisant fbclient.dll ; généralement, une telle application est construite en Delphi, C++, PHP. Contrairement aux applications natives, Java et .NET implémentent leur propre version du protocole, ils seront examinés ci-dessous.

Processus de connexion :

  1. L’application cliente charge la bibliothèque cliente
  2. fbclient.dll - applications Windows natives
  3. libfbclient.so - applications Linux natives
  4. L’application cliente initie une connexion, en envoyant
  5. Le nom d’utilisateur, par ex. SYSDBA
  6. Le mot de passe, par ex. masterkey
  7. Le chemin/alias de la base de données

Dans le cas d’une base de données chiffrée, une étape supplémentaire est requise : il est nécessaire de transmettre le nom de la clé de chiffrement et sa valeur.

Il est important de préciser que la transmission de la clé doit être effectuée avant la connexion régulière, en raison du fait que les pages de données contenant les métadonnées, y compris le nom du propriétaire de la base de données, le jeu de caractères, etc., sont chiffrées.

Cela nous amène donc à ce qui suit :

  1. Un aller-retour réseau supplémentaire est nécessaire pour transmettre la clé avant la connexion régulière
  2. Le transfert de clé de l’application cliente vers Firebird nécessite un codage avec l’utilisation du chiffrement asymétrique et l’implémentation d’une interface de rappel, ce qui peut être assez complexe. Pour simplifier cette tâche, les fournisseurs de plugins fournissent un exemple de code pour se connecter, ou, comme dans le framework de plugins IBSurgeon, créent la bibliothèque supplémentaire fbcrypt.dll/libfbcrypt.so, qui implémente une interface facile à utiliser pour transférer les clés depuis l’application cliente.

Pour connecter une application native (qui utilise fbclient.dll) à une base de données chiffrée, 3 appels doivent être effectués. Voici un exemple Delphi (simplifié, sans gestion des erreurs) :

Dans le gestionnaire d’événements BeforeConnect :

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

 // Ensuite, connectez-vous comme d’habitude
Database1.Active:=True;

Sur la figure ci-dessous, vous pouvez voir l’aperçu du processus de connexion avec une base de données chiffrée dans l’application native :

Figure 10. Processus de connexion à la base de données chiffrée pour les applications natives

Qu’en est-il de la sécurité des threads dans le cas d’applications clientes multi-threadées ?

Permettez-moi de rappeler quelques points généraux sur l’implémentation des applications clientes multi-threadées.

Depuis Firebird 2.5, plusieurs threads à l’intérieur de l’application peuvent utiliser en toute sécurité une seule attache à la base de données, car toute la synchronisation nécessaire est effectuée à l’intérieur de fbclient.dll.

Cependant, dans ce cas, les threads ne pourront travailler avec l’attache qu’un par un.

Cela convient aux applications qui n’exigent pas un échange de données haute performance avec la base de données - si ce n’est pas un problème d’attendre pour exécuter une requête SQL depuis un thread lorsqu’un autre thread exécute un autre SQL, il est plus facile d’utiliser un modèle simple où 1 attache est partagée entre plusieurs threads.

Si l’application nécessite d’exécuter des requêtes SQL en parallèle (c’est-à-dire qu’il s’agit d’une application cliente à grande échelle), il est préférable d’utiliser un thread séparé pour chaque connexion.

La situation avec l’échange de clés pour les attaches aux bases de données chiffrées est un peu plus complexe.

À chaque attache, la bibliothèque cliente transfère les clés depuis le client, mais cela n’est pas directement lié aux threads de l’application cliente ; la situation dépend de l’API utilisée.

Comme vous le savez, la bibliothèque cliente Firebird depuis la version 3.0 offre 2 types d’API : la nouvelle API orientée objet, basée sur le concept de fournisseurs, et l’API isc_ héritée, implémentée comme une solution de contournement pour maintenir la compatibilité avec les anciens pilotes Firebird.

Si la nouvelle API cliente orientée objet est utilisée, il suffit de créer le fournisseur, de lui fournir les clés nécessaires, puis de l’utiliser pour les nouvelles attaches.

Si l’API cliente isc_ est utilisée, pour chaque attache, la bibliothèque cliente créera son propre fournisseur temporaire, qui n’est pas directement visible ou accessible par l’utilisateur final.

Dans ce cas, la clé est transférée exactement depuis le thread où isc_attach_database est invoqué, et le stockage local du thread est utilisé pour stocker cette clé.

En pratique, puisque presque toutes les bibliothèques clientes utilisent l’API isc_ (actuellement, parmi les pilotes populaires, seul le pilote Python utilise l’API OO), il est nécessaire d’invoquer fb_database_crypt_callback() dans chaque thread qui se connecte à la base de données chiffrée.

Les appels de transfert de clé (appels fbcrypt.dll dans l’exemple FEPF) doivent être effectués avant la connexion, dans le même thread où la connexion sera établie.

Lorsque nous travaillons avec de nombreuses bases de données (par exemple, un serveur web SaaS avec de nombreuses bases de données clients), il est important de se rappeler que chaque invocation de fbcrypt_key() ajoute une clé au stockage KeyHolder, associée à la connexion actuelle.

Les valeurs des clés doivent être définies avant la connexion ; après l’attache, la valeur de la clé ne peut pas être modifiée.

En cas de détachement, les clés ne sont pas déchargées ; elles seront conservées en mémoire jusqu’au déchargement de fbcrypt.dll.

3.2. Applications Java

Le pilote Java (JayBird) a sa propre implémentation (en Java pur) du protocole de connexion Firebird. Jaybird 4 (et 3.0.4+) ajoute le support des rappels de chiffrement de base de données Firebird 3 dans l’implémentation Java pure du protocole version 13.

D’après le Readme Jaybird 4 :

« L’implémentation actuelle est simple et ne prend en charge que la réponse avec une valeur statique provenant d’une propriété de connexion. Soyez conscient qu’une réponse de valeur statique pour le chiffrement de base de données n’est pas très sécurisée car elle peut facilement conduire à des attaques par rejeu ou à une exposition involontaire de la clé.

Les futures versions de Jaybird (probablement 5) introduiront un support de plugin pour les plugins de chiffrement de base de données qui nécessitent un rappel plus complexe. »

Concrètement, cela signifie que nous devons définir la valeur du rappel de chiffrement (normalement, il s’agit d’un nom de clé et d’une paire clé-valeur) dans la propriété de connexion dbCryptConfig.

Par exemple :

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

Il est également possible de spécifier une chaîne en base64 - d’après le readme :

« Les chaînes préfixées par base64:: le reste de la chaîne est décodé comme base64 en octets.

Les caractères de remplissage = sont facultatifs, mais lorsqu’ils sont présents, ils doivent être valides (c’est-à-dire : si vous utilisez un remplissage, vous devez utiliser le bon nombre de caractères de remplissage pour la longueur).

Lorsque la valeur encodée en base64 contient +, elle doit être échappée comme %2B dans l’URL JDBC. Pour la compatibilité ascendante avec Jaybird 3, nous ne pouvons pas passer à la variante URL-safe du base64. »

Dans l’implémentation IBSurgeon du plugin de gestion des clés, une telle transmission de la clé est considérée comme plus ou moins non sécurisée : si le chiffrement du protocole réseau n’est pas activé ( d’ailleurs, pour l’activer, définissez WireCrypt=Required dans firebird.conf et n’utilisez pas l’authentification héritée), la clé peut être facilement repérée avec un analyseur de trafic réseau comme WireShark. Par conséquent, pour permettre la transmission des clés de cette manière, il est nécessaire de définir UnsafeClient=true dans KeyHolder.conf du plugin de gestion des clés IBSurgeon.

3.3 Applications .NET

Le fournisseur Firebird.NET implémente un schéma similaire d’échange de clés pour les bases de données chiffrées et nécessite également de définir le paramètre UnsafeClient=true dans KeyHolder.conf dans FEPF.

Exemple .NET de chaîne de connexion pour les bases de données chiffrées :

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

Vous pouvez remarquer que la clé de chiffrement semble différente de celle de l’exemple pour les applications natives et JayBird ; cela est dû au fait qu’il s’agit du résultat d’une transformation Base64. Ainsi, pour obtenir la clé pour une application .NET ou Java, il est nécessaire de calculer le base64 à partir de la chaîne :

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

et de l’utiliser comme paramètre pour “cryptkey=xxx;” avec “;” à la fin de la chaîne de connexion.

4. Installation et configuration

Afin d’activer le chiffrement de base de données et le plugin de gestion des clés à utiliser, il est nécessaire de spécifier le nom du plugin de chiffrement dans le fichier de configuration Firebird firebird.conf :

Code
 KeyHolderPlugin = KeyHolder

Ou, alternativement, dans databases.conf, pour l’alias de la base de données chiffrée :

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

Ensuite, il est nécessaire de vérifier que tous les fichiers nécessaires au plugin sont présents sur le serveur.

L’exemple ci-dessous concerne le FEPF d’IBSurgeon, mais les autres plugins sont plus ou moins similaires :

Dans %FirebirdFolder$\plugins

Code
    • DbCrypt.dll
    • DbCrypt.conf
    • KeyHolder.dll
    • KeyHolder.conf - uniquement pour le mode débogage !

Dans %FirebirdFolder$

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

Après cela, nous pouvons effectuer le chiffrement de test sur le serveur, pour cela, dans 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 vous êtes sous Linux, rappelez-vous que la casse est importante, la commande sera donc :

Code
alter database encrypt with "DbCrypt" key Red;

Maintenant, nous pouvons tester l’accès client à la base de données chiffrée. Pour cela, nous allons supprimer (ou renommer ou modifier) le fichier de configuration KeyHolder.conf, et essayer de nous connecter à la base de données chiffrée avec l’application de test simple.

Pour cela, nous devons placer dans le dossier contenant l’application cliente les fichiers suivants :

  • Application de démonstration de FEPF - CryptTest.exe (32 bits)
  • Fichiers obligatoires :
    • fbclient.dll
    • fbcrypt.dll
    • libcrypto-1.1.dll
    • libssl-1.1-x64.dll
  • Fichiers optionnels :
    • firebird.conf
    • dans plugins
    • ◦ KeyHolder.conf
    • ◦ keyhodler.dll

Dans certaines implémentations de plugins de gestion de clés, il est possible de charger les clés dans la bibliothèque cliente (fbclient.dll), sans modification du logiciel client.

Cela permet le fonctionnement transparent des outils de développement Firebird (comme Firebird SQL Studio, DatabaseWorkbench, IBExpert, FlameRobin, RedExpert, etc.), et l’utilisation transparente des outils en ligne de commande Firebird (gfix.exe, nbackup.exe, etc.).

5. Comment suivre la progression du chiffrement

Firebird ne chiffre une base de données que lorsqu’elle a des connexions actives. Le processus de chiffrement s’exécute dans un thread parallèle séparé, et pour les grandes bases de données, le chiffrement complet peut prendre un temps considérable.

Pour suivre le processus de chiffrement, exécutez soit la requête SQL depuis MON$ :

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

ou exécutez l’outil gstat avec l’option spéciale :

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

Veuillez noter que l’exécution de gstat peut être un processus long.

6. Résumé

  1. Le chiffrement des bases de données Firebird est une fonctionnalité puissante pour protéger les informations des bases de données contre les accès non autorisés.
  2. Le processus de chiffrement nécessite une bibliothèque dynamique côté serveur - le plugin de chiffrement (généralement appelé DbCrypt), et, dans la grande majorité des cas, le plugin de gestion de clés (généralement appelé KeyHolder).
  3. L’implémentation sécurisée et fiable des plugins DbCrypt et KeyHolder doit être réalisée en tenant compte des types d’attaques les plus courants.
  4. Pour travailler avec une base de données chiffrée, les applications clientes doivent transférer la clé de chiffrement.
  5. L’installation et la configuration du plugin de chiffrement côté serveur sont triviales, elles nécessitent 1 paramètre dans firebird.conf/databases.conf, et plusieurs fichiers.
  6. Le processus de chiffrement peut être long, il est effectué dans un thread d’arrière-plan séparé, la progression peut être suivie avec l’appel MON$ ou gstat.

Et ensuite ?

Nous travaillons sur un test de performance détaillé du chiffrement des bases de données Firebird. En général, les performances sont réduites de 4 à 8 %, mais cela dépend du matériel et des paramètres Firebird. Restez à l’écoute !

Contactez-nous :

Veuillez envoyer vos suggestions, fautes de frappe, erreurs, etc., et toutes vos questions par e-mail : [email protected]