How encrypt SQLite database with FireDAC? - sqlite

I'm create SQLite databse with DB Browser for SQLite (non encrypted) and open with FireDAC in delphi.(Can retrive data Eg. Select * from abc).
How encrypt this SQLite database with FireDAC? When enter username, password and encrypt get message "Cipher DB is not encrypdet"
Note:
When create SQLite database from Delphi FireDac I can use encryption!

To encrypt a database, use a TFDSQLiteSecurity Component. You'll also need a TFDSQLitePhysSQLiteDriverLink component to go along with it.
If a database is unencrypted, then its password is ''. So use '' as the OldPassword and create the new password in that case. Passwords are formatted as algorithm:PassPhrase. See documentation on the choices, I use aes-256. Also, the database needs to be closed when you do this.
...
//Change password
FDSQLiteSecurity1.Password := OldPassword;
FDSQLiteSecurity1.ToPassword := NewPassword; // example: 'aes-256:mypassword123'
FDSQLiteSecurity1.ChangePassword;
...
//Remove Password
FDSQLiteSecurity1.Password := OldPassword;
FDSQLiteSecurity1.ToPassword := '';
FDSQLiteSecurity1.RemovePassword;
...

From the Documentation
SQLite Encrypted Database
Approach
One of the distinctive SQLite
features is the high-speed strong database encryption. It allows you
to make database file content confidential and enforce integrity
control on the database file. The encrypted database format is not
compatible with other similar SQLite encryption extensions. This means
that you cannot use an encrypted database, encrypted with non-FireDAC
libraries. If you need to do this, then you have to decrypt a database
with an original tool and encrypt it with FireDAC.

Recent Delphi versions come with an example project for working with encryption on Sqlite databases, see this documentation. I have not used this myself, btw.
It includes this section
Encrypt DB
Encrypt: Encrypts the database according to the Encryption mode and the password provided.
The sampe uses TFDSQLiteSecurity.SetPassword to encrypt the database with the password provided.
The database password is the combination of <encryption algorythm>:<password>.

I have faced several challenges when first time tried to encrypt SQLite database for use with Embarcadero FireDAC. Also all information is published by Embarcadero question pops up again and again on different forums. My case was solved based on community support, but when time has permitted simple Delphi application was assembled and available on Sourceforge. Hope it will make encryption/decryption slightly easier particularly for the newbie
https://sourceforge.net/projects/sqlite-sequrity-for-delphi/

Related

FireDAC SQLite Standard Encryption question

If I declare and create some SQLite database inside FDConnectionDefs.ini as follows
[SQLITESAMPLE]
Database=sample.sdb
Password=masterkey
LockingMode=Normal
SharedCache=false;
DriverID=SQLite
it should be encrypted with aes-256 as standard settings. FDSQLiteSecurity1.CheckEncryption is returning aes-256
Later, if I add the param Encrypt=aes-256 to that definition my apps still work correctly.
But RAD Studio Data Explorer and FireDAC Explorer will only work with a setting
Encrypt=No(with aes-256 I get some corrupt datafile message from these two apps).
If I define the Encrypt=aes-256 param from the beginning all apps do work correct.
Maybe there is some other encryption mode standard defined, if I do not declare encryption mode from the beginning? I wonder about this.
The SQLite3 DB file is either encrypted, or not, from the beginning.
You will have to maunally backup the file from one encrypted state to another.
There is no "standard" free encryption on SQLite3.
Only a few variants:
FireDAC encryption
Closed Source SQLite Encryption Extension
SQLite-Crypt commercial
SQLCipher
WXSQLite3 variant
DISQLite3 commercial for Delphi
SynSQLite3 Delphi/FPC Open Source
and probably others... all incompatible!

Encrypt SQLITE database and use it with FireDac in a windows VCL application

I am writing a Windows VCL desktop using c++ builder. The app uses Firedac and a SQLite database.
I want to protect this SQLite database:
Only my vcl app can connect to it and use it
Other programs and people cannot use the SQLite file
So far I found that the easiest thing that I can do is Encryption, you make it so that anybody without a correct password gets a message like "This file is not a database" if he tries to open it.
Yes we can do this with Embarcadero VCL, doc. using a TFDSQLiteSecurity component and these lines :
FDSQLiteSecurity1->Password = "";/* we are protecting (encrypting) our uncyphered database*/
FDSQLiteSecurity1->ToPassword = 'newpassword';
FDSQLiteSecurity1->ChangePassword();
Unfortunately the VCL Firedac app cannot connect to an encrypted sqlite database so it must decrypt it first.
In order to make things work my program starts and decrypts the database ( removes password) then it connects to the database and use it. When finished I recrypt the database again (when closing app).
THE PROBLEM:
During this time (My program is up and running and the database in uncrypted) can I stop other programs from opening the SQLITE database? Is there a better approach, I am opened for any suggestion
Once it is encrypted by FireDac just set the appropriate properties on the FDConnection. Those would be password to the password and encrypt to the encryption method.
Firedac can open a SQLite database it has encrypted itself so the problem resolves itself by doing that as a better approach. Other programs only see the encrypted version on disk and can't open it without the password.

Smooth migration to encrypted database ( SQLChiper )

I've been using unecrypted data base so far in my app and now I wanted to migrated my database to encrypted database using SQLCipher. Here is my situation.
For the next release I'll update the database version and that will execute the script. For the onUpgrade() to be called I've to call geReadableDatabase() or getWriteableDatabase(). So when I'll called for any operation() it will execute my script and that will do the following operation.
Create and encrypted database.
Export data from the old (un-encrypted) database to the encrypted database.
Delete the old database.
So when I'll perform the migration I'll like to halt all the other operation until the migration is complete and then halted operation will be performed on the encrypted database.
Not really sure how can I achieve that so what approach should I use to achieve this.
I think what you are searching for is
sqlcipher_export method
It easly facilitates copying unencrypted DB to the encrypted one. On Android probably you could do something like:
unencryptedDb.rawExecSQL("ATTACH DATABASE 'secure_db_name.db' AS encrypted KEY 'testkey'");
unencryptedDb.rawExecSQL("SELECT sqlcipher_export('secure_db_name')");
unencryptedDb.rawExecSQL("DETACH DATABASE secure_db_name");

Decrypt database using FMDB with SQLCipher, setkey with a wrong password always return YES

FMDB version (2.6.2)
Problem:
I am testing FMDB and SQLCipher, and find a tricky problem.
I encrypt a db with password 'test001' successfully, and I export it and open the db with DB Brower, with 'test001' I open it without any problem. Then in Xcode I try to open the DB with password 'test002'(I do this to test if FMDB will tell me that I use a wrong password), however the setkey() return YES. I check db.lastErrorMessage, it returns nil, which means FMDB thinks I give the right key.Then I try to read data from the DB using executeQuery(), the function returns NO, and the NSLog shows 'file is encrypted or is not a database'.
Anyone has the same problem? Is it a bug of sqlite or I use it in a wrong way?
setkey() return YES
executeQuery() return NO due to decrypt error
The call to setKey(…)does not verify the password provided is valid for current database, rather it just causes the database to attach a codec context within SQLCipher. The next SQL command that you issue following the keying of the database will cause key derivation to occur (so long as you are not using a raw hex key), and will generally validate whether SQLCipher is able to use the key to access your database. We generally recommend you attempt to execute the following query to validate the password is valid as the sqlite_master table will always be present, regardless of your schema.
SELECT count(*) FROM sqlite_master;

Advantage of sqlcipher

I have a general question to sqlcipher.. where is the advantage of sqlcipher against directly encrypting the database with GnuPG or openssl?
Everytime when I want to encrypt/decrypt with sqlcipher I must open the database, attach a new database, encrypt/decrypt it, export it in the new database and deattach it. For example like this:
echo "PRAGMA key='$1';select count(*) from sqlite_master;ATTACH DATABASE '$2/mydb-decrypt.db' AS plaintext KEY '';SELECT sqlcipher_export('plaintext');DETACH DATABASE plaintext;" | sqlcipher $2/mydb.db
This is pretty bloated isn't it?
With openssl or gnupg I can just decrypt/encrypt it directly with one command..
so why using sqlcipher?
The conflict you are seeing is likely in how you are using it versus how it is more commonly used. SQLCipher decrypts and encrypts data on the fly for user access. That is to say that once you have provided SQLCipher with the key material, only the pages of data that contain your data are decrypted. This does not require you to decrypt the entire database to plain text and write to disk in order to access your data as you model above. I would recommend you review the additional details on the SQLCipher design here.

Resources