SQLCipher 集成到 Xamarin.Forms; SQLite 库不支持加密异常
SQLCipher integration into Xamarin.Forms; SQLite Library doesn't support encryption exception
我正在 Xamarin.Forms 应用程序中实施 SQLCipher。我以为一切正常,直到我注意到 X.F 创建的数据库。应用程序实际上是 SQLite3 DB w/o 加密或密码。研究了一段时间后,我一直无法找到解决方案。我遇到一个异常
System.InvalidOperationException: 'You specified a password in the connection string, but the native SQLite library you're using doesn't support encryption.'
我目前在这个解决方案中有 4 个项目。 XamarinForms 中的标准 3 (跨平台内容默认 PCL,Project.Android,和 Project.iOS)。除了这 3 个,我还有一个自定义的 PCL,标签为 Project.Core。此 PCL 负责所有数据访问,因为它实现了存储库模式、工作单元、DbContext 等。
在第 4 个项目中,在我的 DbContext.cs class 中,我有这个:
// 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();
}
根据我的研究,此 PCL 中的 SQLite/SQLCipher 包之一可能存在问题(PCL 以 .NET Standard 2.0 为参考)。
我目前有:
- Microsoft.Data.Sqlite.Core 3.1.1(依赖于 Microsoft.Data.Sqlite.dll & SQLitePCLRaw.core 2.0.2)
- SQLitePCLRaw.bundle_sqlcipher 1.1.14(w 依赖于 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.0.2\lib\netstandard2.0\SQLitePCLRaw.batteries_v2.dll
- 我认为这种依赖性可能存在问题,但我不确定并希望得到任何帮助!
提前致谢。
PS - 可以根据要求提供更多信息
找到了可行的解决方案。
查看包后,我发现用 SQLitePCLRaw.bundle_zetetic
替换现有的 SQLitePCLRaw 捆绑包发现 here,解决了连接和维护加密数据库的问题。
工作代码片段是:
// 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();
我正在 Xamarin.Forms 应用程序中实施 SQLCipher。我以为一切正常,直到我注意到 X.F 创建的数据库。应用程序实际上是 SQLite3 DB w/o 加密或密码。研究了一段时间后,我一直无法找到解决方案。我遇到一个异常
System.InvalidOperationException: 'You specified a password in the connection string, but the native SQLite library you're using doesn't support encryption.'
我目前在这个解决方案中有 4 个项目。 XamarinForms 中的标准 3 (跨平台内容默认 PCL,Project.Android,和 Project.iOS)。除了这 3 个,我还有一个自定义的 PCL,标签为 Project.Core。此 PCL 负责所有数据访问,因为它实现了存储库模式、工作单元、DbContext 等。
在第 4 个项目中,在我的 DbContext.cs class 中,我有这个:
// 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();
}
根据我的研究,此 PCL 中的 SQLite/SQLCipher 包之一可能存在问题(PCL 以 .NET Standard 2.0 为参考)。
我目前有:
- Microsoft.Data.Sqlite.Core 3.1.1(依赖于 Microsoft.Data.Sqlite.dll & SQLitePCLRaw.core 2.0.2)
- SQLitePCLRaw.bundle_sqlcipher 1.1.14(w 依赖于 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.0.2\lib\netstandard2.0\SQLitePCLRaw.batteries_v2.dll
- 我认为这种依赖性可能存在问题,但我不确定并希望得到任何帮助!
提前致谢。
PS - 可以根据要求提供更多信息
找到了可行的解决方案。
查看包后,我发现用 SQLitePCLRaw.bundle_zetetic
替换现有的 SQLitePCLRaw 捆绑包发现 here,解决了连接和维护加密数据库的问题。
工作代码片段是:
// 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();