1

I am implementing SQLCipher into a Xamarin.Forms application. I thought everything was working until I noticed that the DB that was being created by the X.F. application was actually a SQLite3 DB w/o encryption or a password. After looking into it for a while, I haven't been able to find a solution. I am encountering an exception that says

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

I currently have 4 projects in this solution. The standard 3 in XamarinForms (Default PCL for cross platform stuff, Project.Android, and Project.iOS). In addition to those 3, I have a custom PCL that is labeled Project.Core. This PCL is responsible for all DataAccess since it implements the Repository Pattern, Unit Of Work, DbContext, etc.

In this 4th project, and within my DbContext.cs class, I have this:

// 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://learn.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();
}        

Through my research it appears there might be an issue with one of the SQLite/SQLCipher packages in this PCL (the PCL is targeting .NET Standard 2.0 for reference).

I currently have:

  • Microsoft.Data.Sqlite.Core 3.1.1 (w/ dependencies on Microsoft.Data.Sqlite.dll & SQLitePCLRaw.core 2.0.2)
  • SQLitePCLRaw.bundle_sqlcipher 1.1.14 (w dependencies on SQLitePCLRaw.core 2.0.2, SQLitePCLRaw.batteries_sqlcipher.dll, SQLitePCLRaw.batteries_v2.dll)

A couple of other things to note:

  • When viewing SQLitePCL namespace, it shows the package as being sqlitepclraw.bundle_e_sqlite3 instead of having a reference to sqlcipher. \.nuget\packages\sqlitepclraw.bundle_e_sqlite3\2.0.2\lib\netstandard2.0\SQLitePCLRaw.batteries_v2.dll
  • I believe there may be an issue with that dependency, but I'm not sure and would appreciate any assistance!

Thanks in advance.

PS - Can provide more information as requested

1 Answer 1

2

Found a working solution.

After looking into the packages, I found that replacing the existing SQLitePCLRaw bundle package with SQLitePCLRaw.bundle_zetetic found here, resolved the issues connecting and maintaining an encrypted database.

Working code snippet is:

// 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();
Sign up to request clarification or add additional context in comments.

1 Comment

You can mark it later which can help more people with same problems:).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.