Я следую этому руководству:
https://learn.microsoft.com/en-us/dotne ... bs=net-cli
Я использую эту версию .NET:
9.0.306 [C:\Program Files\dotnet\sdk]
У меня есть база данных Sqlite3.
Некоторые подробности:
$ file Core.db
Core.db: SQLite 3.x database, last written using SQLite version 3046001, file counter 4732, database pages 524, cookie 0x106, schema 4, UTF-8, version-valid-for 4732
Я запустил:
dotnet remove package Microsoft.Data.Sqlite
dotnet add package Microsoft.Data.Sqlite.Core
dotnet add package SQLitePCLRaw.bundle_e_sqlcipher
Я могу открыть базу данных с помощью Microsoft.Data.Sqlite без каких-либо проблем и выполнить любой оператор SQL, который захочу, с нормальным поведением.
Когда я запускаю это (как сказано в разделе «Укажите ключ»):
var connectionString = new SqliteConnectionStringBuilder(baseConnectionString)
{
Mode = SqliteOpenMode.ReadWriteCreate,
Password = password
}.ToString();
Я получаю:
Unhandled exception. Microsoft.Data.Sqlite.SqliteException (0x80004005): SQLite Error 26: 'file is not a database'.
Я предполагал, что сначала мне нужно это сделать (позже в руководстве):
var commandPassword = connection.CreateCommand();
commandPassword.CommandText = "PRAGMA rekey = MyGreatPassword";
commandPassword.Parameters.Clear();
commandPassword.ExecuteNonQuery();
Это компилируется, запускается, без ошибок. Но когда я повторно открываю свою базу данных со строкой подключения, в которой не указан какой-либо пароль, все работает. И это не должно быть так. Он должен быть зашифрован.
Что мне не хватает?
1/ Вот полный MRE, вдохновленный https://github.com/dotnet/docs/blob/mai ... Program.cs:
using System;
using System.IO;
using Microsoft.Data.Sqlite;
using static SQLitePCL.raw;
namespace EncryptionSample
{
class Program
{
static void Main()
{
const string baseConnectionString = "Data Source=EncryptionSample.db";
var password = "...";
// 1 - Create a database WITHOUT a password
var connectionString = new SqliteConnectionStringBuilder(baseConnectionString)
{
Mode = SqliteOpenMode.ReadWriteCreate
}.ToString();
using (var connection = new SqliteConnection(connectionString))
{
connection.Open();
var command = connection.CreateCommand();
command.CommandText = @"
CREATE TABLE data (
value TEXT
);
INSERT INTO data
VALUES ('Hello, encryption!');
";
command.ExecuteNonQuery();
connection.Close();
}
// 2 - Try to set a password to that non-encrypted database
connectionString = new SqliteConnectionStringBuilder(baseConnectionString)
{
Mode = SqliteOpenMode.ReadWrite,
Password = password
}.ToString();
using (var connection = new SqliteConnection(connectionString))
{
try
{
// This will throw
connection.Open();
}
catch (SqliteException ex) when (ex.SqliteErrorCode == SQLITE_NOTADB)
{
Console.WriteLine("Access denied.");
}
}
}
}
}
2/ Вот второй полный MRE, показывающий, что PRAGMA на самом деле не добавляет пароль:
using System;
using System.IO;
using Microsoft.Data.Sqlite;
using static SQLitePCL.raw;
namespace EncryptionSample
{
class Program
{
static void Main()
{
const string baseConnectionString = "Data Source=EncryptionSample.db";
var password = "...";
// 1 - Create a database WITHOUT a password
var connectionString = new SqliteConnectionStringBuilder(baseConnectionString)
{
Mode = SqliteOpenMode.ReadWriteCreate
}.ToString();
using (var connection = new SqliteConnection(connectionString))
{
connection.Open();
var command = connection.CreateCommand();
command.CommandText = @"
CREATE TABLE data (
value TEXT
);
INSERT INTO data
VALUES ('Hello, encryption!');
";
command.ExecuteNonQuery();
connection.Close();
}
// 2 - Set a password to that non-encrypted database
using (var connection = new SqliteConnection(connectionString))
{
connection.Open();
var commandPassword = connection.CreateCommand();
commandPassword.CommandText = "SELECT quote($newPassword);";
commandPassword.Parameters.AddWithValue("$newPassword", ("myNewPassword"));
var quotedNewPassword = (string)commandPassword.ExecuteScalar();
commandPassword.CommandText = "PRAGMA rekey = " + quotedNewPassword;
commandPassword.Parameters.Clear();
commandPassword.ExecuteNonQuery();
}
// 3 - Reopen without specifying the password. this shouldn't work! But it does.
using (var connection = new SqliteConnection(connectionString))
{
connection.Open();
var queryCommand = connection.CreateCommand();
queryCommand.CommandText =
@"
SELECT value
FROM data
LIMIT 1
";
var value = (string)queryCommand.ExecuteScalar();
Console.WriteLine(value);
connection.Close();
}
}
}
}
Подробнее здесь: https://stackoverflow.com/questions/798 ... pclraw-bun