Интеграция SQLCipher в Xamarin.Forms; Библиотека SQLite не поддерживает исключение шифрования - PullRequest
1 голос
/ 06 февраля 2020

Я внедряю SQLCipher в приложение Xamarin.Forms. Я думал, что все работает, пока не заметил, что БД, создаваемая приложением XF, на самом деле была БД SQLite3 без шифрования или пароля. После долгого изучения я не смог найти решение. Я сталкиваюсь с исключением, которое говорит

System.InvalidOperationException: 'You specified a password in the connection string, but the native SQLite library you're using doesn't support encryption.'

У меня есть 4 проекта в этом решении. Стандарт 3 в XamarinForms (PCL по умолчанию для кроссплатформенного содержимого, Project. Android и Project. iOS) . В дополнение к этим 3, у меня есть пользовательский PCL, который помечен как Project.Core. Этот PCL отвечает за весь DataAccess, поскольку он реализует шаблон репозитория, Unit Of Work, DbContext и т. Д. c.

В этом 4-м проекте и в моем классе DbContext.cs у меня есть следующее:

// Added for more context
using System;
using System.IO;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Xamarin.Forms;


private SqliteConnection connection;

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
        string connStr = Path.Combine(
            path1: Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
            path2: "App.db");

        string passStr = deviceIdentifier;

        string path = Path.GetDirectoryName(connStr);
        if (!Directory.Exists(path))
        {
            Directory.CreateDirectory(path);
        }

        // Check if db file exists
        if (!File.Exists(connStr))
        {
            FileStream stream = File.Create(connStr);
            stream.Close();
        }

        // DOCS => https://docs.microsoft.com/en-us/dotnet/standard/data/sqlite/encryption?tabs=netcore-cli
        // => https://www.bricelam.net/2016/06/13/sqlite-encryption.html
        var connectionString = new SqliteConnectionStringBuilder()
        {
            DataSource = connStr,
            Mode = SqliteOpenMode.ReadWriteCreate,
            Password = passStr
        }.ToString();

        // NOTE: THIS IS WHERE THE EXCEPTION IS THROWN!!!
        // THE CODE BELOW THIS IS AN ALTERNATE ROUTE THAT DOENS'T WORK EITHER
        **connection.Open();**

        // This code doesn't throw anything, but it doesn't key the DB either
        using (SqliteCommand command = connection.CreateCommand())
        {
            command.CommandText = "SELECT quote($password);";
            command.Parameters.AddWithValue("$password", passStr);
            string escapedPassword = (string)command.ExecuteScalar(); // Protects against SQL injection

            command.CommandText = "PRAGMA key = " + escapedPassword /*+ ";"*/;
            command.Parameters.Clear();
            command.ExecuteNonQuery();
        }

#if DEBUG
        optionsBuilder.EnableSensitiveDataLogging();
#endif

        optionsBuilder.UseSqlite(connection);
        SQLitePCL.Batteries_V2.Init();
}        

В ходе моего исследования выяснилось, что может быть проблема с одним из пакетов SQLite / SQLCipher. в этом PCL (PCL нацеливается. NET Стандарт 2.0 для справки).

В настоящее время у меня есть:

  • Microsoft.Data.Sqlite.Core 3.1.1 (с зависимостями от Microsoft.Data.Sqlite.dll и SQLitePCLRaw.core 2.0.2)
  • SQLitePCLRaw.bundle_sqlcipher 1.1.14 (с зависимостями от SQLitePCLRaw.core 2.0.2, SQLitePCLRaw.batteries_sqlcipher.dll, SQLitePCLRaw.batteries_v2.dll)

пара других замечаний :

  • При просмотре пространства имен SQLitePCL пакет будет показан как sqlitepclraw.bundle_e_sqlite3 вместо ссылки на sqlcipher. \.nuget\packages\sqlitepclraw.bundle_e_sqlite3\2.0.2\lib\netstandard2.0\SQLitePCLRaw.batteries_v2.dll
  • Я полагаю, что с этой зависимостью может быть проблема, но я не уверен и буду признателен за любую помощь!

Заранее спасибо.

PS - может предоставить больше информации по запросу

1 Ответ

1 голос
/ 06 февраля 2020

Нашел работающее решение.

Изучив пакеты, я обнаружил, что замена существующего пакета SQLitePCLRaw на SQLitePCLRaw.bundle_zetetic найдено здесь , решил проблемы с подключением и поддержанием зашифрованного база данных.

Фрагмент рабочего кода:

// StringBuilder here, and the SqliteConnection below are 
// from the Microsoft.Data.Sqlite namespace v3.1.1
var connectionString = new SqliteConnectionStringBuilder()
{
  DataSource = connStr,
  Mode = SqliteOpenMode.ReadWriteCreate,
  Password = passStr
}.ToString();

connection = new SqliteConnection(connectionString);
connection.Open();
...