171

I'm just learning to use SQLite and I was curious if such is possible:

  1. Encryption of the database file?

  2. Password protect opening of the database?

PS. I know that there is this "SQLite Encryption Extension (SEE).", but according to the documentation, "The SEE is licensed software...." and "The cost of a perpetual source code license for SEE is US $2000."

ahmd0
  • 16,633
  • 33
  • 137
  • 233
  • 2
    @RobotMess: To be honest with you -- none of the ones listed here. I had strict time constrains on that project, so I had to do something quick. I went with what I knew best -- AES on the raw data before placing it into the DB... It is not very efficient though in terms of lookup, search and DB management. – ahmd0 Oct 04 '13 at 21:57
  • 1
    @ahmd0 Hm, doesn't that make the DB kind of useless though? I mean, all it really does now is ensure commits are atomic. – Navin Nov 16 '13 at 18:36
  • Yes, it's possible. If targeting .Net Standard 4.6.1+ or Core, I think a fairly straightforward to get Sqlite encryption is to use Microsoft.Data.Sqlite per my answer [here](https://stackoverflow.com/a/49588874/8663165). – paulyb Mar 31 '18 at 16:06
  • It's certainly possible and there exist several open source solutions besides SEE. Among them the encryption extension coming with wxSQLite3. [See my answer to a similar question for details.](https://stackoverflow.com/questions/4971483/how-to-compile-wxsqlite3-and-sqlite-to-get-encryption-support/4979051#4979051) – Ulrich Telle Apr 15 '11 at 18:58

9 Answers9

141

SQLite has hooks built-in for encryption which are not used in the normal distribution, but here are a few implementations I know of:

  • SEE - The official implementation.
  • wxSQLite - A wxWidgets style C++ wrapper that also implements SQLite's encryption.
  • SQLCipher - Uses openSSL's libcrypto to implement.
  • SQLiteCrypt - Custom implementation, modified API.
  • botansqlite3 - botansqlite3 is an encryption codec for SQLite3 that can use any algorithms in Botan for encryption.
  • sqleet - another encryption implementation, using ChaCha20/Poly1305 primitives. Note that wxSQLite mentioned above can use this as a crypto provider.

The SEE and SQLiteCrypt require the purchase of a license.

Disclosure: I created botansqlite3.

Brian Minton
  • 3,377
  • 3
  • 35
  • 41
OliJG
  • 2,650
  • 1
  • 16
  • 15
  • 7
    botansqlite3 is now distributed independantly of Botan. – OliJG Jun 05 '12 at 10:11
  • 1
    There is also [litereplica](http://litereplica.io/sqlite-encryption.html). It uses the ChaCha cipher, faster than AES on portable devices based on ARMv7 – Bernardo Ramos Jan 06 '17 at 19:28
  • SQLite3 .Net as built in support for encryption now, which largely invalidates this answer. – Krythic Feb 20 '18 at 20:58
  • 5
    @Krythic The fact that .Net library having encryption support does not "largely invalidate" this answer in any possible way even though the library carries native SQLite3. This answer is still relevant to this day. – m4heshd Nov 26 '21 at 13:56
22

You can password protect SQLite3 DB. For the first time before doing any operations, set password as follows.

SQLiteConnection conn = new SQLiteConnection("Data Source=MyDatabase.sqlite;Version=3;");
conn.SetPassword("password");
conn.open();

then next time you can access it like

conn = new SQLiteConnection("Data Source=MyDatabase.sqlite;Version=3;Password=password;");
conn.Open();

This wont allow any GUI editor to view Your data. Later if you wish to change the password, use conn.ChangePassword("new_password"); To reset or remove password, use conn.ChangePassword(String.Empty);

Mangesh
  • 5,491
  • 5
  • 48
  • 71
  • 26
    Won't work with the open source Sqlite. No clue what language implementation, language, or API this is supposed to be. – mikerobi Sep 27 '14 at 01:16
  • 1
    How do I know which encryption way ``ChangePassword`` used? AES 128? RSA ..? – qakmak Apr 14 '15 at 04:44
  • 1
    RSA 1024 or 2048? Is there any document could see that more details? – qakmak Apr 24 '16 at 15:20
  • Get the docs from here http://system.data.sqlite.org/index.html/doc/trunk/www/index.wiki – Mangesh Apr 26 '16 at 15:51
  • 1
    In my own testing, I've found that the `SetPassword` method (at this time) appears basically useless. The only way I was able to get the `System.Data.SQLite` library to properly apply the password was using the `ChangePassword` method. Using `SetPassword` (*before* calling the `Open` method, as is apparently required by the library), I was still able to open and edit the DB in SQLiteStudio without any password. It wasn't until I used the `ChangePassword` method (***after*** calling the `Open` method) that the password application actually "stuck". – G_Hosa_Phat Mar 18 '20 at 15:20
  • SetPassword not exists in SQLiteConnection object, System.Data.SQLite 1.0.113.0 – Ejrr1085 Oct 26 '20 at 19:11
16

The .net library System.Data.SQLite also provides for encryption.

TZHX
  • 5,291
  • 15
  • 47
  • 56
Rory
  • 40,559
  • 52
  • 175
  • 261
  • 11
    ASP.NET != SQL Server != installed instance of SQL Server – Zev Spitz Sep 09 '13 at 05:57
  • 1
    But [System.Data.SQLite](http://system.data.sqlite.org/index.html/doc/trunk/www/index.wiki) is not from Microsoft. This question is not about .Net but if it were then other compatibilities and incompatibilities would be important. – Sam Hobbs Nov 30 '17 at 02:54
10

You can get sqlite3.dll file with encryption support from http://system.data.sqlite.org/.

1 - Go to http://system.data.sqlite.org/index.html/doc/trunk/www/downloads.wiki and download one of the packages. .NET version is irrelevant here.

2 - Extract SQLite.Interop.dll from package and rename it to sqlite3.dll. This DLL supports encryption via plaintext passwords or encryption keys.

The mentioned file is native and does NOT require .NET framework. It might need Visual C++ Runtime depending on the package you have downloaded.

UPDATE

This is the package that I've downloaded for 32-bit development: http://system.data.sqlite.org/blobs/1.0.94.0/sqlite-netFx40-static-binary-Win32-2010-1.0.94.0.zip

Mohammad Banisaeid
  • 2,376
  • 27
  • 35
3

Keep in mind, the following is not intended to be a substitute for a proper security solution.

After playing around with this for four days, I've put together a solution using only the open source System.Data.SQLite package from NuGet. I don't know how much protection this provides. I'm only using it for my own course of study. This will create the DB, encrypt it, create a table, and add data.

using System.Data.SQLite;

namespace EncryptDB
{
    class Program
    {
        static void Main(string[] args)
        {
            string connectionString = @"C:\Programming\sqlite3\db.db";
            string passwordString = "password";
            byte[] passwordBytes = GetBytes(passwordString);
            SQLiteConnection.CreateFile(connectionString);
            SQLiteConnection conn = new SQLiteConnection("Data Source=" + connectionString + ";Version=3;");
            conn.SetPassword(passwordBytes);
            conn.Open();
            SQLiteCommand sqlCmd = new SQLiteCommand("CREATE TABLE data(filename TEXT, filepath TEXT, filelength INTEGER, directory TEXT)", conn);
            sqlCmd.ExecuteNonQuery();
            sqlCmd = new SQLiteCommand("INSERT INTO data VALUES('name', 'path', 200, 'dir')", conn);
            sqlCmd.ExecuteNonQuery();
            conn.Close();
        }
        static byte[] GetBytes(string str)
        {
            byte[] bytes = new byte[str.Length * sizeof(char)];
            bytes = System.Text.Encoding.Default.GetBytes(str);
            return bytes;
        }
    }
}

Optionally, you can remove conn.SetPassword(passwordBytes);, and replace it with conn.ChangePassword("password"); which needs to be placed after conn.Open(); instead of before. Then you won't need the GetBytes method.

To decrypt, it's just a matter of putting the password in your connection string before the call to open.

        string filename = @"C:\Programming\sqlite3\db.db";
        string passwordString = "password";
        SQLiteConnection conn = new SQLiteConnection("Data Source=" + filename + ";Version=3;Password=" + passwordString + ";");
        conn.Open();
  • 3
    `"I think I saw 128 bit somewhere"` - this is a very bad statement if you're planning to deal with encryption. The rule of thumb is that you **never** do it yourself if you don't understand it. Otherwise you'd be better off not using it at all. – ahmd0 Oct 15 '15 at 17:45
  • SetPassword not exists in SQLiteConnection object, System.Data.SQLite 1.0.113.0 – Ejrr1085 Oct 26 '20 at 19:11
2

Well, SEE is expensive. However SQLite has interface built-in for encryption (Pager). This means, that on top of existing code one can easily develop some encryption mechanism, does not have to be AES. Anything really. Please see my post here: https://stackoverflow.com/a/49161716/9418360

You need to define SQLITE_HAS_CODEC=1 to enable Pager encryption. Sample code below (original SQLite source):

#ifdef SQLITE_HAS_CODEC
/*
** This function is called by the wal module when writing page content
** into the log file.
**
** This function returns a pointer to a buffer containing the encrypted
** page content. If a malloc fails, this function may return NULL.
*/
SQLITE_PRIVATE void *sqlite3PagerCodec(PgHdr *pPg){
  void *aData = 0;
  CODEC2(pPg->pPager, pPg->pData, pPg->pgno, 6, return 0, aData);
  return aData;
}
#endif

There is a commercial version in C language for SQLite encryption using AES256 - it can also work with PHP, but it needs to be compiled with PHP and SQLite extension. It de/encrypts SQLite database file on the fly, file contents are always encrypted. Very useful.

http://www.iqx7.com/products/sqlite-encryption

q74
  • 88
  • 8
2

You can always encrypt data on the client side. Please note that not all of the data have to be encrypted because it has a performance issue.

Pang
  • 9,564
  • 146
  • 81
  • 122
Marcin
  • 1,429
  • 8
  • 16
2

I had also similar problem. Needed to store sensitive data in simple database (SQLite was the perfect choice except security). Finally I have placed database file on TrueCrypt encrypted valume.

Additional console app mounts temporary drive using TrueCrypt CLI and then starts the database application. Waits until the database application exits and then dismounts the drive again.

Maybe not suitable solution in all scenarios but for me working well ...

Tom
  • 31
  • 2
1

You can use SQLite's function creation routines (PHP manual):

$db_obj->sqliteCreateFunction('Encrypt', 'MyEncryptFunction', 2);
$db_obj->sqliteCreateFunction('Decrypt', 'MyDecryptFunction', 2);

When inserting data, you can use the encryption function directly and INSERT the encrypted data or you can use the custom function and pass unencrypted data:

$insert_obj = $db_obj->prepare('INSERT INTO table (Clear, Encrypted) ' .
 'VALUES (:clear, Encrypt(:data, "' . $passwordhash_str . '"))');

When retrieving data, you can also use SQL search functionality:

$select_obj = $db_obj->prepare('SELECT Clear, ' .
 'Decrypt(Encrypted, "' . $passwordhash_str . '") AS PlainText FROM table ' .
 'WHERE PlainText LIKE :searchterm');
Alien426
  • 1,097
  • 10
  • 12