SQLite Datenbankverschlüsselung

LiteSync wird mit der Verschlüsselung von SQLite-Datenbanken sowie der Kommunikation zwischen den Knoten geliefert

Die verfügbaren Chiffren sind ChaCha, das auf kleinen Geräten schneller als AES ist, und XRC4, eine erweiterte Version von RC4, die noch schneller als ChaCha ist.

Zum Öffnen einer verschlüsselten Datenbank verwenden wir die URI-Parameter cipher und key oder hexkey. Beispiel:

"file:/path/to/file.db?cipher=...&key=..."

Or

"file:/path/to/file.db?cipher=...&hexkey=..."


DIE CIPHER

Das cipher Argument kann auf einen dieser Werte gesetzt werden:

xrc4 - am schnellsten
chacha8 - schnell
chacha12 - mittel
chacha20 - am stärksten



DER SCHLÜSSEL

Verwenden von XRC4 Schlüssel kann bis zu 256 Byte lang sein. Beispiel:

"file:data.db?cipher=xrc4&key=testing"

Verwenden von ChaCha Der Schlüssel muss 32 Byte lang sein. Beispiel:

"file:data.db?cipher=chacha20&key=ThisIsAReallyLongKeyWith32Bytess"

Der Schlüssel kann auch im Hex-Format mit dem hexkey Parameter vorliegen:

"file:data.db?cipher=...&hexkey=11223344556677889900AABBCCDDEEFF..."


ERSTELLEN EINER EINGESCHRIEBENEN DATENBANK

Öffnen Sie die Datenbank mit einem URI wie den oben genannten, erstellen Sie die Tabellen und füllen Sie sie aus.



KONVERTIEREN EINER BESTEHENDEN DATENBANK

Derzeit ist eine direkte Konvertierung einer vorhandenen Datenbank nicht möglich. Wir müssen eine verschlüsselte Datenbank mit der SQLite-Shell erstellen und dann die Daten aus der einfachen Datenbank in diese kopieren.

Dies kann in nur 1 Schritt erfolgen:

sqlite3 plain.db .dump | sqlite3 "file:encrypted.db?cipher=...&key=..."

Oder in zwei Schritten, wenn Sie die generierten SQL-Befehle überprüfen möchten:

sqlite3 plain.db .dump > out.sql

sqlite3 "file:encrypted.db?cipher=...&key=..." < out.sql

Wenn Sie eine andere Seitengröße als die Standardgröße verwenden möchten, öffnen Sie die generierte Datei out.sql und fügen Sie die Pragma-Zeile oben hinzu:

PRAGMA page_size=...;

Achtung: Diese verschlüsselte Datenbankdatei sollte nur auf dem Primärknoten verwendet werden. Die sekundären Knoten laden diese Datei vom primären Knoten herunter, wenn die Verbindung hergestellt wird.



DATENBANK HEADER

Die ersten 100 Bytes einer SQLite-Datenbank bilden den Header. Das meiste davon sind feste Daten.

Wenn bei der Verschlüsselung bekannte einfache Daten vorliegen, kann ein Angreifer versuchen, den Verschlüsselungsschlüssel zu ermitteln.

Aus diesem Grund ist der Datenbankheader nicht standardmäßig verschlüsselt, Sie haben jedoch insgesamt 3 Optionen:


1. Verschlüsseln Sie den Datenbank-Header nicht

Dies ist das Standardverhalten


2. Verschlüsseln Sie den Datenbank-Header nicht und verwenden Sie eine benutzerdefinierte Header-Zeichenfolge

Die ersten 16 Bytes des Headers bilden die Header-Zeichenfolge. Die Standard-Header-Zeichenfolge lautet "SQLite-Format 3" (mit einem Null-Terminator).

Wenn Sie aus irgendeinem Grund nicht klarstellen möchten, dass es sich bei der Datei um eine SQLite-Datenbank handelt, können Sie diese Zeichenfolge ändern.

So aktivieren Sie die Verwendung eines benutzerdefinierten Headers: Kompilieren Sie LiteSync mit:

CODEC_USE_CUSTOM_HEADER

CODEC_CUSTOM_HEADER="ExampleNewHeader"

Die benutzerdefinierte Header-Zeichenfolge muss 15 oder 16 Byte lang sein. Wenn Sie 15 Bytes verwenden, ist das letzte ein Nullterminator.


3. Verschlüsseln Sie den Datenbank-Header, aber verschlüsseln Sie nicht die Bytes 16-23

Diese Bytes müssen von SQLite unverschlüsselt sein.

Um den Datenbankheader zu verschlüsseln, kompilieren Sie LiteSync mit:

CODEC_ENCRYPT_DB_HEADER



INTERNES DESIGN

Jede Seite wird bei Bedarf verschlüsselt und entschlüsselt, und jede Seite verfügt über eine eigene Initialisierung Vektor (Nonce). Jedes Mal, wenn eine Seite gespeichert wird, wird eine neue IV verwendet und dann die gesamte verschlüsselt Seitendaten sind anders als zuvor.

WAL-Seiten sind ebenfalls verschlüsselt.

Die Kommunikation zwischen den Knoten verwendet dieselbe Verschlüsselung und denselben Schlüssel, die für die Datenbank ausgewählt wurden. Jede Nachricht verwendet einen anderen Initialisierungsvektor, sodass dieselben einfachen Daten als unterschiedlicher Kryptostream gesendet werden.