Deze pagina is automatisch vertaald. Lees het Engelse origineel. English

IBSurgeon-bibliotheek

Hoe Firebird Database Encryptie Werkt

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

Het artikel is gebaseerd op de materialen van de workshop “Database Encryption” op de Firebird Conference 2019 in Berlijn, Duitsland. Het beschrijft hoe Firebird database-encryptie werkt, op serverniveau, aan de clientzijde, hoe database-encryptie te configureren, en hoe het te gebruiken vanuit verschillende soorten applicaties (Delphi, Java, .NET). De voorbeelden in het artikel zijn gebaseerd op IBSurgeon Firebird Encryption Framework (FEPF), maar kunnen worden aangepast aan de meeste momenteel beschikbare implementaties van encryptie-plugins.

Inhoud:

  1. Waarom hebben we database-encryptie nodig (en wanneer niet)?
  2. Hoe Firebird database-encryptie werkt aan de serverzijde
  3. Welk deel van de database wordt versleuteld?
  4. Wanneer worden datapagina’s versleuteld?
  5. Hoe de sleuteloverdracht te beschermen?
  6. Hoe Firebird-encryptie werkt aan de clientzijde
  7. Native applicaties
  8. Java-applicaties
  9. .NET-applicaties
  10. Installatie en configuratie
  11. Hoe de voortgang van encryptie te volgen
  12. Samenvatting

1. Waarom hebben we database-encryptie nodig (en wanneer niet)?

Firebird database-encryptie werd geïntroduceerd in Firebird 3.0 (samen met protocol-encryptie voor overdracht, die vaak wordt verward met het besproken onderwerp) en vergrootte de mogelijkheden om gegevens te beschermen tegen ongeautoriseerde toegang aanzienlijk. Het is echter geen wondermiddel, en het is noodzakelijk om de sterke en zwakke punten ervan te begrijpen om het correct te gebruiken.

In dit artikel beschouwen we de interne werking van database-encryptie op basisniveau, om ontwikkelaars van Firebird-applicaties een beter begrip te geven van hoe database-encryptie werkt.

Dus, waarom hebben we database-encryptie nodig?

  1. Om databases met gevoelige/waardevolle gegevens te beschermen tegen “fysieke” diefstal. Als een indringer de schijf steelt met een kopie van de versleutelde database of op de een of andere manier een kopie van een databasebestand verkrijgt, zal het niet mogelijk zijn om er gegevens uit te lezen zonder de juiste sleutel, en zal het ook niet mogelijk zijn om herstelsoftware zoals FirstAID te gebruiken om de gegevens te extraheren. Natuurlijk hangt dit af van het encryptie-algoritme en de rekenkracht, maar het kraken van AES256 zal te veel tijd of te dure rekenkracht vereisen.
  2. Om de database te beschermen tegen toegang door niet-geautoriseerde applicaties zonder encryptiesleutels. Voorbeelden zijn:
    • directe toegang met een ontwikkeltool door een niet-geautoriseerd persoon, om gevoelige informatie te wijzigen (bijv. geldtransacties),
    • het wijzigen of stelen van bedrijfslogica (teksten van opgeslagen procedures en triggers).
  3. Databases met vooraf ingevulde gegevens beschermen tegen exporteren naar of toegang door niet-geautoriseerde applicaties.
  4. Overheden hebben recentelijk wetten voor gegevensbescherming ingevoerd (GDPR/DSVGO in Europa, LGPD in Brazilië, enz.) die onder andere een hoger beschermingsniveau voor persoonlijke en andere gevoelige gegevens vereisen, en encryptie wordt genoemd als een van de adequate beschermingsmaatregelen.

Wanneer is database-encryptie niet nuttig?

In sommige gevallen is het beter om de beveiligings- en configuratiemogelijkheden van Firebird te gebruiken in plaats van database-encryptie:

  • Om de database te beschermen tegen fysieke toegang via het netwerk, is het noodzakelijk om netwerktoegang te configureren: d.w.z. gedeelde netwerkmappen sluiten, omdat Firebird geen gedeelde netwerktoegang tot databasebestanden vereist, en beveiligingsmachtigingen aanscherpen (voor Linux bijvoorbeeld moeten databasebestanden lees-/schrijftoegang hebben alleen voor gebruiker “firebird”).
  • Om toegang tot de specifieke database voor een specifieke subset van gebruikers te beperken, is de eenvoudigere oplossing het configureren van een aparte beveiligingsdatabase.
  • Om toegang tot databaseobjecten (tabellen, opgeslagen procedures) te beperken, is het noodzakelijk om Firebird-beveiligingsmechanismen te gebruiken: gebruikers, rollen, enz.

Natuurlijk zijn beide bovenstaande lijsten onvolledig, maar ze geven u een indruk van wanneer u database-encryptie nodig heeft of niet.

2. Hoe Firebird database-encryptie werkt aan de serverzijde

Laten we de interne details van Firebird database-encryptie doornemen en beginnen met het servergedeelte.

2.1. Welk deel van de database wordt versleuteld?

Het eerste wat we moeten overwegen is welk deel van de database wordt versleuteld? Zoals u waarschijnlijk weet, bestaat een Firebird-database uit delen van gelijke grootte, “databasepagina’s” genoemd. Er zijn verschillende soorten van dergelijke pagina’s, elk type dient een specifiek doel.

Hieronder ziet u de figuur met de belangrijkste gegevenstypen:

Figuur 1. Typen databasepagina’s

Sommige pagina’s zijn ontworpen om gebruikersgegevens op te slaan, en andere zijn nodig om systeeminformatie op te slaan, zoals transacties en pagina-inventarispagina’s (meer details over databasepagina’s zijn hier beschikbaar).

Wanneer een Firebird-database wordt versleuteld, worden alleen pagina’s met gebruikersgegevens versleuteld: datapagina’s, indexen, generatoren en BLOBs:

Figuur 2. Alleen databasepagina’s met gebruikersgegevens worden versleuteld

Houd er rekening mee dat databasemetadata (opgeslagen procedures, tabellen, views, triggers, generatornamen, enz.) niet verschillen van “gebruikersgegevens” binnen het deel van de engine dat verantwoordelijk is voor de encryptie, en ze worden versleuteld.

Waarom worden systeempagina’s niet versleuteld? Voornamelijk om prestatieregels, en vanwege het feit dat ze geen gevoelige gegevens bevatten die bescherming vereisen.

De databasekoptekstpagina wordt niet versleuteld, omdat deze informatie bevat die nodig is voor encryptie (bijvoorbeeld de sleutelnaam).

2.2. Wanneer worden datapagina’s versleuteld?

Wanneer een gebruiker een SELECT uitvoert op de versleutelde database, worden de gegevens uit het versleutelde bestand gelezen, maar komen ze bij het raster van de applicatie met de resultatenset in niet-versleutelde vorm aan.

Laten we de details van dit proces bekijken:

Figuur 3. Wanneer worden databasepagina’s versleuteld?

Gewoonlijk begint het proces met een reeks leesbewerkingen van databasepagina’s uit een databasebestand, en ze worden in de bestandscache van het besturingssysteem opgeslagen.

Firebird kan ook worden geconfigureerd om de bestandscache te omzeilen en alleen de eigen cache te gebruiken, maar standaard wordt de bestandscache gebruikt.

Daarna leest Firebird pagina’s en plaatst ze in de Firebird-paginacache (gedefinieerd door de parameter DefaultDBCachePages in firebird.conf en/of databases.conf of in de databasekoptekstpagina).

Vervolgens worden pagina’s uit de cache geselecteerd voor de resultatenset van de specifieke SQL-instructie (SELECT in ons voorbeeld).

De figuur hieronder toont de details:

Figuur 4. Pagina’s worden versleuteld tussen de Firebird-cache en de bestandscache van het besturingssysteem

Dus databasepagina’s worden versleuteld in de bestandscache van het besturingssysteem, maar komen niet-versleuteld aan in de Firebird-paginacache, en vice versa.

Het deel van de Firebird-software dat verantwoordelijk is voor encryptie/decryptie wordt de “encryptie-plugin” genoemd. Aangezien de meeste plugin-implementaties (bekend bij de auteurs) DbCrypt worden genoemd, verwijzen we hiernaar als DbCrypt.

In de figuur hieronder ziet u varianten voor Windows (DbCrypt.dll) en Linux (libDbCrypt.so):

Figuur 5. Encryptie-plugin (DbCrypt) voert encryptie/decryptie uit

Als u lang genoeg naar deze afbeelding kijkt, zal de volgende vraag vrij snel opkomen: hoe krijgt DbCrypt de juiste sleutel om databasepagina’s te versleutelen/ontsleutelen?

Het antwoord: er is nog een plugin voor sleutelbeheer.

De typische naam voor sleutelbeheer is KeyHolder, die fungeert als een sleutelopslag-/beheerfaciliteit voor de encryptie-plugin (DbCrypt). KeyHolder implementeert de interface voor sleutelbeheer die door DbCrypt wordt gebruikt.

Figuur 6. DbCrypt en KeyHolder

Wat betekent “sleutelbeheer”?

In het eenvoudigste geval kan DbCrypt sleutels uit een bestand op de server lezen. Het bestand kan een eenvoudig plat tekstbestand zijn, dat op een “geheime” plaats of op een USB-stick kan worden verborgen, of het kan een versleuteld bestand zijn (bijvoorbeeld met Windows Crypto API of met een ingebouwde interne sleutel).

Het sleutelbestand kan verschillende sleutels bevatten, voor het gemak opgeslagen als een benoemde lijst, en kan er als volgt uitzien (het onderstaande voorbeeld is afkomstig uit het IBSurgeon-encryptie-pluginframework):

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,

Wanneer de database wordt versleuteld, blijven de koptekstpagina’s niet-versleuteld om informatie over de encryptie-plugin en de naam van de sleutel op te slaan, en u kunt deze informatie zien met de opdracht “gstat -h databasenaam”:

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 kan pagina’s verwerken voor verschillende databases en verschillende sleutels:

Figuur 7. Meerdere sleutels voor meerdere databases op dezelfde server (d.w.z. Firebird-instantie)

De juiste sleutel kiezen

Ontwikkelaars stellen vaak de vraag: “Hoe herkent de plugin welke sleutel voor welke database is?” Het antwoord is vrij eenvoudig: via de sleutelnaam, die op de koptekstpagina van de database is opgeslagen.

Minder vaak, maar nog steeds een belangrijke vraag: wat als de sleutelnaam is zoals vastgelegd in de koptekst, maar de sleutelwaarde anders is? Om paginaleesfouten door de verkeerde sleutel te voorkomen, slaat de DbCrypt-plugin een versleutelde testreeks (cijfers 0…F) op in de koptekst, en wanneer de sleutel wordt geactiveerd, probeert de plugin de voorbeeldgegevens met een sleutel te versleutelen en de hash ervan te vergelijken met het opgeslagen resultaat, om ervoor te zorgen dat de doorgegeven sleutelwaarde daadwerkelijk correct is voor deze specifieke database.

De aanpak waarbij de encryptie-plugin sleutels rechtstreeks leest, is eenvoudig en gunstig voor debugging, prestatietests, enz., omdat het encryptie op een transparante manier implementeert: d.w.z. clientapplicaties en ontwikkeltools weten niet dat de database is versleuteld.

In werkelijkheid moeten we echter de toegang van applicaties tot de database beperken: alleen een clientapplicatie die een sleutel heeft, moet verbinding kunnen maken met de versleutelde database.

Hiervoor hebben we de KeyHolder-plugin nodig, om de sleutel van de clientapplicatie (die zich meestal op een andere computer bevindt) via het Firebird-netwerkprotocol te verkrijgen.

2.3. Hoe de sleuteloverdracht te beschermen?

Het is mogelijk dat we de database willen beschermen in de situatie waarin de klant besluit directe toegang tot de versleutelde database te krijgen, waarbij de geautoriseerde applicaties worden omzeild (veel leveranciers willen gegevens beperken tegen directe toegang, zowel alleen-lezen als lezen-schrijven).

Dit is gelijkwaardig aan de situatie waarin een indringer toegang heeft tot de server maar geen sleutels heeft.

Laten we de volgende aanvalsscenario’s bekijken om sleutels aan de serverzijde te onderscheppen:

  1. Wanneer de indringer het neppe encryptieplugin (DBCrypt.dll) maakt en op de server plaatst, en wanneer KeyHolder de sleutel doorgeeft, maakt neppe DbCrypt een dump van de sleutel:

Figuur 8. Aanval met neppe DbCrypt.dll

  1. Wanneer de indringer een neppe firebird.exe maakt en daarmee een dump maakt:

Figuur 9. Aanval met neppe firebird.exe

Om tegen dergelijke aanvallen te beschermen, moeten goede implementaties van encryptie- en sleutelbeheerplugins de sleuteluitwisseling beschermen.

Sleuteluitwisseling kan worden beschermd met asymmetrische encryptie met een paar publieke/private sleutels.

Deze sleutels worden gegenereerd tijdens het buildproces en ingebouwd voor het specifieke paar van encryptie- en sleutelbeheerplugins. Voor de beste bescherming is het noodzakelijk om speciaal gebouwde paren van DbCrypt/KeyHolder te gebruiken.

Wanneer DbCrypt en KeyHolder sleutels uitwisselen, gebruiken ze het volgende protocol (het is vereenvoudigd, maar de bedoeling is duidelijk, denk ik):

Code
DbCrypt → KeyHolder:
	Geef Me De Databasesleutel Met Dit Salt
KeyHolder:
	Versleutelt DbKey Met Publieke sleutel met salt van DbCrypt
	Draagt Versleutelde DbKey over aan DbCrypt
DbCrypt:
	Ontsleutelt DbKey Met Private Sleutel
	Valideert de juistheid van salt
	Klaar Om Te Werken

Min of meer hetzelfde protocol wordt gebruikt om sleutels uit te wisselen tussen instanties van KeyHolder, en voor sleuteluitwisseling tussen een clientapplicatie en KeyHolder.

Houd er rekening mee dat encryptie en de juistheid van overgedragen sleutels afhangen van de pluginimplementatie; de Firebird-engine biedt alleen een basale low-level overdrachtservice “verstuur N bytes van deze plugininstantie naar die plugininstantie”.

Samenvatting voor het server-side deel van de encryptie

  • Encryptie/decryptie wordt gedaan door het database-encryptieplugin (DbCrypt), pagina voor pagina, tijdens gegevensuitwisseling tussen de bestandscache van het besturingssysteem en de Firebird-paginacache
  • Sleutelbeheer kan op een eenvoudige manier worden geïmplementeerd wanneer DbCrypt sleutels direct leest, maar meestal gebeurt dit met een sleutelbeheerplugin (KeyHolder)

Laten we nu ontdekken hoe clientapplicaties werken met versleutelde databases.

3. Hoe Firebird-encryptie aan de clientzijde werkt

3.1. Native applicaties

Om te begrijpen wat er gebeurt wanneer een clientapplicatie verbinding maakt met de versleutelde database, bekijken we het reguliere verbindingsproces met de niet-versleutelde database voor native applicaties.

Houd er rekening mee: vanaf hier en verder betekent “native” dat een dergelijke applicatie een netwerkverbinding met de server tot stand brengt met behulp van fbclient.dll; meestal is zo’n app gebouwd in Delphi, C++, PHP. In tegenstelling tot native applicaties implementeren Java en .NET hun eigen versie van het protocol; deze worden hieronder besproken.

Verbindingsproces:

  1. Clientapplicatie laadt de clientbibliotheek
  2. fbclient.dll - native Windows-apps
  3. libfbclient.so - native Linux-apps
  4. Clientapplicatie initieert een verbinding en verstuurt
  5. Gebruikersnaam, bijv. SYSDBA
  6. Wachtwoord, bijv. masterkey
  7. Pad/alias van de database

In het geval van een versleutelde database is een extra stap vereist: het is noodzakelijk om de naam van de encryptiesleutel en de waarde ervan door te geven.

Het is belangrijk om te zeggen dat het doorgeven van de sleutel vóór de reguliere verbinding moet gebeuren, vanwege het feit dat gegevenspagina’s met metadata, inclusief de naam van de database-eigenaar, tekenset, enz., versleuteld zijn.

Dit leidt ons dus tot het volgende:

  1. Een extra netwerkroundtrip is nodig om de sleutel vóór de reguliere verbinding door te geven
  2. Sleuteloverdracht van de clientapplicatie naar Firebird vereist codering met het gebruik van asymmetrische encryptie en implementatie van een callback-interface; dit kan behoorlijk complex zijn. Om deze taak te vereenvoudigen, bieden pluginleveranciers een voorbeeld van de code om verbinding te maken, of, zoals in het IBSurgeon-pluginframework, maken ze een extra bibliotheek fbcrypt.dll/libfbcrypt.so, die een eenvoudig te gebruiken geschikte interface implementeert om sleutels van de clientapplicatie over te dragen.

Om een native applicatie (die fbclient.dll gebruikt) te verbinden met de versleutelde database, moeten 3 aanroepen worden gedaan. Hieronder staat een Delphi-voorbeeld (vereenvoudigd, zonder foutafhandeling):

In de BeforeConnect-gebeurtenishandler:

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

 // Verbind dan zoals gebruikelijk
Database1.Active:=True;

Op de onderstaande figuur ziet u een overzicht van het verbindingsproces met een versleutelde database in de native applicatie:

Figuur 10. Verbindingsproces met de versleutelde database voor native applicaties

Hoe zit het met threadveiligheid in het geval van multi-thread clientapplicaties?

Laat me enkele algemene punten over de implementatie van multi-thread clientapplicaties in herinnering brengen.

Sinds Firebird 2.5 kunnen meerdere threads binnen de applicatie veilig de enkele attachment aan de database gebruiken, omdat alle noodzakelijke synchronisatie binnen fbclient.dll wordt gedaan.

In dit geval kunnen threads echter slechts één voor één met de attachment werken.

Dit is prima voor applicaties die geen hoogwaardige gegevensuitwisseling met de database vereisen - als het geen probleem is om te wachten op het uitvoeren van een SQL-query vanuit de ene thread wanneer een andere thread een andere SQL uitvoert, is het eenvoudiger om een eenvoudig model te gebruiken waarbij 1 attachment wordt gedeeld tussen meerdere threads.

Als de applicatie vereist dat SQL-query’s parallel worden uitgevoerd (d.w.z. het is een volwaardige clientapplicatie), is het beter om een aparte thread per verbinding te gebruiken.

De situatie met de sleuteluitwisseling voor de attachments aan de versleutelde databases is iets complexer.

Bij elke attachment draagt de clientbibliotheek de sleutels van de client over, maar dit is niet direct gerelateerd aan de threads in de clientapplicatie; de situatie hangt af van de gebruikte API.

Zoals u weet, biedt de Firebird-clientbibliotheek sinds 3.0 twee soorten API’s: nieuwe objectgeoriënteerde API, gebaseerd op het concept van providers, en legacy isc_ API, geïmplementeerd als een workaround om compatibiliteit met oude Firebird-stuurprogramma’s te behouden.

Als de nieuwe objectgeoriënteerde client-API wordt gebruikt, is het voldoende om een provider te maken, deze van de nodige sleutels te voorzien en deze vervolgens te gebruiken voor de nieuwe attachments.

Als isc_ client-API wordt gebruikt, maakt de clientbibliotheek voor elke attachment zijn eigen tijdelijke provider, die niet direct zichtbaar of toegankelijk is voor de eindgebruiker.

In dit geval wordt de sleutel exact overgedragen vanuit de thread waar isc_attach_database wordt aangeroepen, en wordt thread local storage gebruikt om die sleutel op te slaan.

In de praktijk, aangezien bijna alle clientbibliotheken isc_ API gebruiken (op dit moment gebruikt onder populaire stuurprogramma’s alleen het Python-stuurprogramma OO-API), is het noodzakelijk om fb_database_crypt_callback() aan te roepen in elke thread die verbinding maakt met de versleutelde database.

Sleuteloverdrachtsaanroepen (fbcrypt.dll-aanroepen in het FEPF voorbeeld) moeten vóór de verbinding worden gedaan, in dezelfde thread waar de verbinding tot stand zal worden gebracht.

Wanneer we met veel databases werken (bijvoorbeeld een SaaS-webserver met veel clientdatabases), is het belangrijk om te onthouden dat elke aanroep van fbcrypt_key() een sleutel toevoegt aan de KeyHolder-opslag, gekoppeld aan de huidige verbinding.

Sleutelwaarden moeten vóór de verbinding worden ingesteld; na de attachment kan de sleutelwaarde niet worden gewijzigd.

In geval van detaching worden sleutels niet verwijderd; ze worden in het geheugen bewaard tot het lossen van fbcrypt.dll.

3.2. Java-applicaties

Het Java-stuurprogramma (JayBird) heeft zijn eigen implementatie (in pure Java) van het Firebird-verbindingsprotocol. Jaybird 4 (en 3.0.4+) voegt ondersteuning toe voor Firebird 3 database-encryptie-callbacks in de pure Java-implementatie van het versie 13-protocol.

Uit Jaybird 4 Readme:

De huidige implementatie is eenvoudig en ondersteunt alleen het antwoorden met een statische waarde uit een verbindingseigenschap. Wees u ervan bewust dat een statische waarde-respons voor database-encryptie niet erg veilig is, omdat dit gemakkelijk kan leiden tot replay-aanvallen of onbedoelde sleutelblootstelling.

Toekomstige versies van Jaybird (waarschijnlijk 5) zullen pluginondersteuning introduceren voor database-encryptieplugins die een complexere callback vereisen.

Praktisch betekent dit dat we de waarde voor de encryptie-callback (normaal gesproken een sleutelnaam en sleutel-waardepaar) moeten instellen in de verbindingseigenschap dbCryptConfig.

Bijvoorbeeld:

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

Het is ook mogelijk om een string in base64 op te geven - uit de readme:

Strings voorafgegaan door base64:: de rest van de string wordt gedecodeerd als base64 naar bytes.

De = opvultekenen zijn optioneel, maar wanneer aanwezig moeten ze geldig zijn (dat wil zeggen: als u opvulling gebruikt, moet u het juiste aantal opvultekenen voor de lengte gebruiken).

Wanneer de base64-gecodeerde waarde + bevat, moet deze worden geëscaped als %2B in de JDBC-URL. Voor achterwaartse compatibiliteit met Jaybird 3 kunnen we niet overschakelen naar de URL-veilige variant van base64.

In de IBSurgeon-implementatie van het sleutelbeheerplugin wordt een dergelijke overdracht van de sleutel als min of meer onveilig beschouwd: als netwerkprotocol-encryptie niet is ingeschakeld ( trouwens, om dit in te schakelen, stelt u in firebird.conf WireCrypt=Required in en gebruikt u geen legacy-authenticatie), kan de sleutel gemakkelijk worden opgemerkt met een netwerkverkeersanalysator zoals WireShark. Om overdracht van sleutels op deze manier mogelijk te maken, is het dus noodzakelijk om UnsafeClient=true in te stellen in KeyHolder.conf van het IBSurgeon-sleutelbeheerplugin.

3.3 .NET-applicaties

De Firebird.NET-provider implementeert een vergelijkbaar schema voor sleuteluitwisseling voor versleutelde databases en vereist ook dat de parameter UnsafeClient=true wordt ingesteld in KeyHolder.conf in FEPF.

.NET-voorbeeld van de verbindingsstring voor versleutelde databases:

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

U kunt opmerken dat de encryptiesleutel er anders uitziet dan in het voorbeeld voor native applicaties en JayBird; dit komt omdat het het resultaat is van Base64-transformatie. Om de sleutel voor .NET- of Java-applicaties te verkrijgen, is het dus noodzakelijk om base64 te berekenen uit de 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,”

en gebruik dit als parameter voor “cryptkey=xxx;” met “;” aan het einde van de verbindingsstring.

4. Installatie en configuratie

Om database-encryptie en het sleutelbeheerplugin mogelijk te maken, is het noodzakelijk om de naam van het encryptieplugin op te geven in het Firebird-configuratiebestand firebird.conf:

Code
 KeyHolderPlugin = KeyHolder

Of, alternatief, in databases.conf, voor het alias van de versleutelde database:

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

Vervolgens is het noodzakelijk om te controleren dat alle benodigde bestanden voor het plugin op de server aanwezig zijn.

Het onderstaande voorbeeld is voor IBSurgeon’s FEPF, maar andere plugins zijn min of meer vergelijkbaar:

In %FirebirdFolder$\plugins

Code
    • DbCrypt.dll
    • DbCrypt.conf
    • KeyHolder.dll
    • KeyHolder.conf - alleen voor debug-modus!

In %FirebirdFolder$

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

Daarna kunnen we de testversleuteling op de server uitvoeren. Hiervoor gebruiken we in 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

Als u op Linux werkt, onthoud dan dat hoofdlettergevoeligheid belangrijk is, dus de opdracht zal zijn:

Code
alter database encrypt with "DbCrypt" key Red;

Nu kunnen we de clienttoegang tot de versleutelde database testen. Hiervoor verwijderen (of hernoemen of bewerken) we het configuratiebestand KeyHolder.conf en proberen we verbinding te maken met de versleutelde database met de eenvoudige testtoepassing.

Hiervoor moeten we in de map met de client-app de volgende bestanden plaatsen:

  • Demo-app van FEPF- CryptTest.exe (32bit)
  • Verplichte bestanden:
    • fbclient.dll
    • fbcrypt.dll
    • libcrypto-1.1.dll
    • libssl-1.1-x64.dll
  • Optionele bestanden:
    • firebird.conf
    • in plugins
    • ◦ KeyHolder.conf
    • ◦ keyhodler.dll

In sommige implementaties van plugins voor sleutelbeheer is het mogelijk om sleutels in de clientbibliotheek (fbclient.dll) te laden, zonder wijziging van de clientsoftware.

Dit maakt transparant werken mogelijk met Firebird-ontwikkeltools (zoals Firebird SQL Studio, DatabaseWorkbench, IBExpert, FlameRobin, RedExpert, enz.) en transparant gebruik van Firebird-opdrachtregeltools (gfix.exe, nbackup.exe, enz.).

5. Hoe de voortgang van de versleuteling te volgen

Firebird versleutelt een database alleen wanneer er actieve verbindingen zijn. Het versleutelingsproces wordt uitgevoerd in een afzonderlijke parallelle thread, en voor grote databases kan de volledige versleuteling aanzienlijke tijd in beslag nemen.

Om het versleutelingsproces te volgen, voert u een SQL-query uit vanuit MON$:

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

of voer het gstat-hulpprogramma uit met de speciale schakelaar:

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

Houd er rekening mee dat de uitvoering van gstat een langdurig proces kan zijn.

6. Samenvatting

  1. Firebird-databaseversleuteling is een krachtige functie om de informatie in databases te beschermen tegen niet-geautoriseerde toegang.
  2. Het versleutelingsproces vereist een server-side dynamische bibliotheek - de versleutelingsplugin (meestal DbCrypt genoemd), en in de overgrote meerderheid van de situaties, de plugin voor sleutelbeheer (meestal KeyHolder genoemd).
  3. De veilige en betrouwbare implementatie van DbCrypt- en KeyHolder-plugins moet worden gedaan met de meest voorkomende aanvalstypen in gedachten.
  4. Om met de versleutelde database te werken, moeten clienttoepassingen de versleutelingssleutel overdragen.
  5. Installatie en configuratie van de versleutelingsplugin aan de serverzijde is triviaal; het vereist 1 parameter in firebird.conf/databases.conf en verschillende bestanden.
  6. Het versleutelingsproces kan lang duren; het wordt uitgevoerd in een afzonderlijke achtergrondthread. De voortgang kan worden gevolgd met een MON$-aanroep of gstat.

Wat nu?

We werken aan een gedetailleerde prestatietest van Firebird-databaseversleuteling. Over het algemeen is de prestatie 4-8% lager, maar dit hangt af van de hardware en Firebird-instellingen. Blijf op de hoogte!

Neem contact met ons op:

Stuur uw suggesties, typefouten, fouten, enz. en eventuele vragen per e-mail: [email protected]