DBEncryption Plugin for Firebird

<< IBExpert PlugIns menu | IBExpert | IBExpert Help menu >>

IBExpert has developed an encyption plugin for Firebird. The plugin is currently available for Windows (32/64 bit) and Linux (32/64 bit). Introduced in version 2019.04.14, the IBExpert Developer Studio includes the 32-bit embedded version, free to use in embedded mode. Server versions (32 bit and x64) require the IBExpert Server Tools.

Important: each program, which needs to access an encrypted server, has to recognise and know the encryption, regardless of whether an embedded or server version.

Installation

1. Install the latest IBExpert customer version, it includes all files and configs you need. The first run of IBExpert should be done using Admin rights, so that it can generate the correct license key for using dbcrypt plugin.

Encrypt db

2. Create a database using Local, default as Server / protocol to use the included embedded version.

3. Specify C:\Program Files (x86)\HK-Software\IBExpert\firebird3\fbclient.dll as the client library in the IBExpert Database Registration.

4. In the Database Registration's Additional connect parameters add this key: CryptKeyName=IBE

5. Still in the IBExpert Database Registration under Scripts / Before Connect add the following:

  execute ibeblock
  as
  begin
    ibec_RegisterFBCryptKey('IBE',  
               '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,', '');
   end

6. Connect to the database and encrypt it with :

    ALTER DATABASE ENCRYPT WITH "DbCrypt" KEY IBE

7. Now remove CryptKeyName=IBE from the Database Registration.

And you are done.

Create encryption key

You can use the supplied aesKeyGen.exe to create the correct keys for db encryption.

Check database encryption

There are two different ways to check if the database is successfully encrypted. You can invoke isql:

  isql -user SYSDBA -password masterkey
  Use CONNECT or CREATE DATABASE to specify a database
  SQL> connect C:\db\ibe.fdb;
  Statement failed, SQLSTATE = HY000
  Key not set
  SQL>

Also, you can use gstat to check:

  gstat -e c:\db\ibe.fdb

  Database "C:\DB\IBE.FDB"
  Gstat execution time Mon Mar 26 14:31:43 2018

  Database header page information:
          Flags                   0
          Generation              199
          System Change Number    0
          Page size               16384
          ODS version             12.0
          Oldest transaction      143
          Oldest active           183
          Oldest snapshot         183
          Next transaction        183
          Sequence number         0
          Next attachment ID      41
          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           Mar 5, 2018 13:21:04
          Attributes              force write, encrypted, plugin DbCrypt

      Variable header data:
         Encoded option 5, length 28
          Key hash:       ask88tfWbinvC6b1JvS9Mfuh47c=
          Encryption key name:    IBE
          *END*

  Data pages: total 32, encrypted 32, non-crypted 0
  Index pages: total 54, encrypted 54, non-crypted 0
  Blob pages: total 0, encrypted 0, non-crypted 0
  Gstat completion time Mon Mar 26 14:31:43 2018
 

back to top of page

FPC and Lazarus example

To use the encryption plugin developed by IBExpert, you need to use the cdecl calling convention, as the following code shows:

  Tfbcrypt_key = function (AName : PChar; AData : PChar; ALength : DWORD) : integer; cdecl;
  Tfbcrypt_callback = function (Provider : Pointer) : integer; cdecl;

To make the connection to the encrypted database, you need to use the following code:

  function PassCryptKey(const FBCryptPath, AKeyName, AKeyData : string) : integer;
  var
    hFBCryptLib : THandle;
    fFBCryptKey : Tfbcrypt_key;
    fFBCryptCallback : Tfbcrypt_callback;
  begin
    Result := 0;
    hFBCryptLib := LoadLibraryEx(PChar(FBCryptPath), 0, LOAD_WITH_ALTERED_SEARCH_PATH);
    if (hFBCryptLib > HINSTANCE_ERROR) then
    begin
      Pointer(fFBCryptKey) := GetProcAddress(hFBCryptLib, 'fbcrypt_key');
      Pointer(fFBCryptCallback) := GetProcAddress(hFBCryptLib, 'fbcrypt_callback');
      if (@fFBCryptKey <> nil) and (@fFBCryptCallback <> nil) then
      begin
        Result := fFBCryptKey(PChar(AKeyName), PChar(AKeyData), Length(AKeyData));
        if Result = 0 then
          Result := fFBCryptCallback(nil);
      end
      else
        Result := -2; // fbcrypt_key or fbcrypt_callback function not found
    end
    else
      Result := -1;  // Cannot find/load fbcrypt.dll
  end; 

Also, you should declare a private procedure to load the firebird client library and to pass the encryption key ...
For example:

  procedure LoadLibrary(Filename: String);
  var
     KeyData : ansistring;
  begin
    with LibLoader do
    begin
      ConnectionType:='Firebird';
      LibraryName:=Filename;
      Enabled:=True;
    end;

    KeyData :=
  chr($ec)+chr($a1)+chr($52)+chr($f6)+chr($4d)+chr($27)+chr($da)+chr($93)+chr($53)+chr($e5)+chr($48)+chr($86)+chr($b9)
  +chr($7d)+chr($e2)+chr($8f)+chr($3b)+chr($fa)+chr($b7)+chr($91)+chr($22)+chr($5b)+chr($59)+chr($15)+chr($82)+chr($35)
  +chr($f5)+chr($30)+chr($1f)+chr($04)+chr($dc)+chr($75);
    PassCryptKey(ExtractFilePath(Filename)+'fbcrypt.dll','IBE',KeyData);

  end;

We have provided a sample encryption key name and key data value in the previous code.

If you want to use cross database queries, and the other database is encrypted using a different key, just define KeyData for the second key as in the previous example, and pass the data to the PassCryptKey method along with the second key name...

IMPORTANT! If you are using execute block, the sqldb library doesn't like output parameters, so just remove ":" in front of the return value.
So, instead of something like this, default firebird behaviour:

  execute block
  returns (
      LOGON varchar(31))
  as
  begin
    execute statement 'select current_user from rdb$database'
        on external 'C:\db\ibe2.fdb'
        as user 'SYSDBA' password 'masterkey'
        into :LOGON;
    suspend;
  end

  remove ":" like

  execute block
  returns (
      LOGON varchar(31))
  as
  begin
    execute statement 'select current_user from rdb$database'
        on external 'C:\db\ibe2.fdb'
        as user 'SYSDBA' password 'masterkey'
        into LOGON;
    suspend;
  end

Using a different db connection library might not need this, as Delphi FireDAC supports execute block just fine.

Finally you need to load fbclient lib, usually done like this:

  procedure TDataModule1.DataModuleCreate(Sender: TObject);
  begin
    LoadLibrary(Path to firebird client library\'fbclient.dll');
  end; 

The methods provided as sample code here are all you need to get started.
The complete Lazarus and FPC example is available for download here. (to be uploaded)

See also:
DBEncryption Plugin for Firebird 3.0 and later

back to top of page
<< IBExpert PlugIns menu | IBExpert | IBExpert Help menu >>