SQLite z szyfrowaniem / ochroną hasłem


136

Właśnie uczę się obsługi SQLite i byłem ciekawy, czy to możliwe:

  1. Szyfrowanie pliku bazy danych?

  2. Ochrona hasłem otwierania bazy danych?

PS. Wiem, że istnieje to „Rozszerzenie szyfrowania SQLite (SEE)”, ale zgodnie z dokumentacją „SEE jest licencjonowanym oprogramowaniem…” oraz „Koszt wieczystej licencji na kod źródłowy dla SEE wynosi 2000 USD”.


Jest to z pewnością możliwe i poza SEE istnieje kilka rozwiązań open source. Wśród nich rozszerzenie szyfrowania dostarczane z wxSQLite3. Zobacz moją odpowiedź na podobne pytanie po szczegóły.
Ulrich Telle

1
@RobotMess: Szczerze mówiąc - żaden z wymienionych tutaj. Miałem ścisłe ograniczenia czasowe w tym projekcie, więc musiałem zrobić coś szybko. Poszedłem z tym, co wiedziałem najlepiej - AES na surowych danych przed umieszczeniem ich w bazie danych ... Nie jest to jednak zbyt wydajne pod względem wyszukiwania, wyszukiwania i zarządzania bazą danych.
ahmd0

@ ahmd0 Hm, czy to jednak nie czyni DB trochę bezużytecznym? Chodzi mi o to, że wszystko, co teraz naprawdę robi, to upewnienie się, że zatwierdzenia są atomowe.
Navin

Tak, to możliwe. Jeśli celem jest .Net Standard 4.6.1+ lub Core, myślę, że dość prostym do uzyskania szyfrowania Sqlite jest użycie Microsoft.Data.Sqlite na moją odpowiedź tutaj .
paulyb

Odpowiedzi:


110

SQLite ma wbudowane haki do szyfrowania, które nie są używane w normalnej dystrybucji, ale oto kilka implementacji, które znam:

  • ZOBACZ - Oficjalna realizacja.
  • wxSQLite - Opakowanie C ++ w stylu wxWidgets, które również implementuje szyfrowanie SQLite.
  • SQLCipher - Wykorzystuje libcrypto openSSL do implementacji.
  • SQLiteCrypt - niestandardowa implementacja, zmodyfikowane API.
  • botansqlite3 - botansqlite3 to kodek szyfrujący dla SQLite3, który może wykorzystywać do szyfrowania dowolne algorytmy w Botan.
  • sqleet - kolejna implementacja szyfrowania, wykorzystująca prymitywy ChaCha20 / Poly1305. Zauważ, że wspomniany powyżej wxSQLite może używać tego jako dostawcy kryptografii.

SEE i SQLiteCrypt wymagają zakupu licencji.

Ujawnienie: stworzyłem botansqlite3.


1
Czy masz jakąś dokumentację dotyczącą korzystania z programu Botan do szyfrowania bazy danych SQLite? Witryna internetowa Botan nie wspomina o tej funkcji.
Marc Schlösser

5
botansqlite3 jest teraz dystrybuowany niezależnie od Botan.
OliJG,

1
Jest też litereplica . Używa szyfru ChaCha, szybszego niż AES na urządzeniach przenośnych opartych na ARMv7
Bernardo Ramos

SQLite3 .Net jako wbudowana obsługa szyfrowania teraz, co w dużej mierze unieważnia tę odpowiedź.
Krythic

21

Możesz zabezpieczyć hasłem SQLite3 DB. Po raz pierwszy przed wykonaniem jakichkolwiek operacji ustaw hasło w następujący sposób.

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

wtedy następnym razem będziesz mógł uzyskać do niego dostęp

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

To nie pozwoli żadnemu edytorowi GUI na przeglądanie Twoich danych. Później, jeśli chcesz zmienić hasło, użyj conn.ChangePassword("new_password"); Aby zresetować lub usunąć hasło, użyjconn.ChangePassword(String.Empty);


16
Nie będzie działać z Open Source Sqlite. Nie mam pojęcia, jaka to ma być implementacja języka, język lub API.
mikerobi,

1
Skąd mam wiedzieć, jaki sposób szyfrowania został ChangePasswordużyty? AES 128? RSA ..?
qakmak

1
RSA 1024 czy 2048? Czy jest jakiś dokument, w którym można znaleźć więcej szczegółów?
qakmak


W moich własnych testach stwierdziłem, że SetPasswordmetoda (w tej chwili) wydaje się w zasadzie bezużyteczna. Jedynym sposobem, w jaki udało mi się zmusić System.Data.SQLitebibliotekę do prawidłowego zastosowania hasła, było użycie ChangePasswordmetody. Używając SetPassword( przed wywołaniem Openmetody, jak najwyraźniej wymaga tego biblioteka), nadal mogłem otwierać i edytować bazę danych w SQLiteStudio bez hasła. Dopiero gdy użyłem ChangePasswordmetody ( po wywołaniu Openmetody), aplikacja z hasłem faktycznie "utknęła".
G_Hosa_Phat


7

Możesz pobrać sqlite3.dllplik z obsługą szyfrowania ze strony http://system.data.sqlite.org/ .

1 - Przejdź do http://system.data.sqlite.org/index.html/doc/trunk/www/downloads.wiki i pobierz jeden z pakietów. Wersja .NET nie ma tutaj znaczenia.

2 - Wyodrębnij SQLite.Interop.dllz pakietu i zmień jego nazwę na sqlite3.dll. Ta biblioteka DLL obsługuje szyfrowanie za pomocą haseł w postaci zwykłego tekstu lub kluczy szyfrowania.

Wspomniany plik jest natywny i NIE wymaga platformy .NET. W zależności od pobranego pakietu może wymagać środowiska uruchomieniowego Visual C ++.

AKTUALIZACJA

To jest pakiet, który pobrałem do programowania w wersji 32-bitowej: http://system.data.sqlite.org/blobs/1.0.94.0/sqlite-netFx40-static-binary-Win32-2010-1.0.94.0.zip


W moim konkretnym przykładzie potrzebowałem pliku, .libktóry mógłbym osadzić w moim pliku wykonywalnym. Nie mogłem mieć żadnych bibliotek dll.
ahmd0

2
Sprawdź również ten plik github.com/rindeal/wxSQLite3-VS, który da ci plik libi dll.
Mohammad Banisaeid

4

Należy pamiętać, że poniższe informacje nie zastępują prawidłowego rozwiązania zabezpieczającego.

Po czterech dniach zabawy przygotowałem rozwiązanie wykorzystujące tylko pakiet System.Data.SQLite o otwartym kodzie źródłowym z NuGet. Nie wiem, jaką ochronę to zapewnia. Używam go tylko do własnego toku studiów. Spowoduje to utworzenie bazy danych, zaszyfrowanie jej, utworzenie tabeli i dodanie danych.

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;
        }
    }
}

Opcjonalnie możesz go usunąć conn.SetPassword(passwordBytes);i zastąpić nim, conn.ChangePassword("password");który ma być umieszczony po conn.Open();zamiast przed. Wtedy nie będziesz potrzebować metody GetBytes.

Aby odszyfrować, wystarczy umieścić hasło w ciągu połączenia przed wywołaniem do otwarcia.

        string filename = @"C:\Programming\sqlite3\db.db";
        string passwordString = "password";
        SQLiteConnection conn = new SQLiteConnection("Data Source=" + filename + ";Version=3;Password=" + passwordString + ";");
        conn.Open();

2
"I think I saw 128 bit somewhere"- to bardzo złe stwierdzenie, jeśli planujesz zająć się szyfrowaniem. Ogólna zasada jest taka, że nigdy nie robisz tego sam, jeśli tego nie rozumiesz. W przeciwnym razie lepiej go w ogóle nie używać.
ahmd0

Rozumiem co masz na myśli. W większości próbowałem poprawić otrzymane porady, które nie działają z aktualną wersją System.Data.Sqlite. Nie chciałem sugerować, że to dobre zabezpieczenie. Zaktualizowałem swój post. Dzięki za wkład!
Mike Warner

2

Zawsze możesz zaszyfrować dane po stronie klienta. Należy pamiętać, że nie wszystkie dane muszą być szyfrowane, ponieważ mają problemy z wydajnością.


1

Cóż, SEEjest drogi. SQLiteMa jednak wbudowany interfejs do szyfrowania (Pager). Oznacza to, że poza istniejącym kodem można łatwo opracować jakiś mechanizm szyfrowania, ale nie musi AES. Naprawdę wszystko. Zobacz mój post tutaj: https://stackoverflow.com/a/49161716/9418360

Musisz zdefiniować SQLITE_HAS_CODEC = 1, aby włączyć szyfrowanie Pager. Przykładowy kod poniżej (oryginalne SQLiteźródło):

#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

Dostępna jest wersja komercyjna C languagedo SQLiteszyfrowania przy użyciu AES256 - może również współpracować PHP, ale wymaga kompilacji PHPi SQLiterozszerzenia. Odszyfrowuje / szyfruje SQLiteplik bazy danych w locie, zawartość pliku jest zawsze szyfrowana. Bardzo przydatne.

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


0

Możesz użyć procedur tworzenia funkcji SQLite ( podręcznik PHP ):

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

Podczas wstawiania danych możesz użyć funkcji szyfrowania bezpośrednio i WSTAWIĆ zaszyfrowane dane lub możesz użyć funkcji niestandardowej i przekazać niezaszyfrowane dane:

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

Podczas pobierania danych możesz również skorzystać z funkcji wyszukiwania SQL:

$select_obj = $db_obj->prepare('SELECT Clear, ' .
 'Decrypt(Encrypted, "' . $passwordhash_str . '") AS PlainText FROM table ' .
 'WHERE PlainText LIKE :searchterm');
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.