@deadspace12

Как решить проблему database is locked?

столкнулся с такой проблемой, что при экспорте подписи в БД SQLite что или база данных занята другим процессом или не удается ее открыть не знаю, но при генерации подписи при помощи импортированных параметров и ключей выходит сделать а сам экспорт в таблицу нет.
Вот код, который реализует генерацию:
public class ElGamalDigitalSignature
{
    private ElGamalKeyParametersImporter keyImporter;

    public ElGamalDigitalSignature(string dbFileName)
    {
        keyImporter = new ElGamalKeyParametersImporter(dbFileName);
    }

    public byte[] Sign(string message)
    {
        // Import parameters and private key
        var parameters = keyImporter.ImportParameters();
        var privateKey = keyImporter.ImportPrivateKey();
        var publicKey = keyImporter.ImportPublicKey();

        // Create ElGamal parameters
        var p = parameters.Item1;
        var g = parameters.Item2;
        var y = publicKey;

        // Generate a random value k
        var random = new Random();
        BigInteger k;
        do
        {
            k = new BigInteger(p.Subtract(BigInteger.One).BitLength, random).Mod(p.Subtract(BigInteger.Two)).Add(BigInteger.Two);
        } while (!IsRelativelyPrime(k, p.Subtract(BigInteger.One)));

        // Проверка, являются ли числа a и b взаимно простыми


        // Calculate r = g^k mod p
        var r = g.ModPow(k, p);

        // Calculate s = (Hash(message) - x * r) * k^-1 mod (p - 1)
        var hash = HashMessage(message);
        var x = privateKey;
        var s = hash.Subtract(x.Multiply(r)).Multiply(k.ModInverse(p.Subtract(BigInteger.One))).Mod(p.Subtract(BigInteger.One));

        // Convert r and s to byte arrays
        var rBytes = r.ToByteArrayUnsigned();
        var sBytes = s.ToByteArrayUnsigned();

        // Combine r and s into signature
        var signature = new byte[rBytes.Length + sBytes.Length];
        Array.Copy(rBytes, 0, signature, 0, rBytes.Length);
        Array.Copy(sBytes, 0, signature, rBytes.Length, sBytes.Length);

        return signature;
    }
    private bool IsRelativelyPrime(BigInteger a, BigInteger b)
    {
        return a.Gcd(b).Equals(BigInteger.One);
    }
    public bool Verify(string message, byte[] signature)
    {
        // Import parameters and public key
        var parameters = keyImporter.ImportParameters();
        var publicKey = keyImporter.ImportPublicKey();

        // Extract r and s from signature
        var rBytes = new byte[signature.Length / 2];
        var sBytes = new byte[signature.Length / 2];
        Array.Copy(signature, 0, rBytes, 0, rBytes.Length);
        Array.Copy(signature, rBytes.Length, sBytes, 0, sBytes.Length);

        var r = new BigInteger(1, rBytes);
        var s = new BigInteger(1, sBytes);

        // Calculate w = s^-1 mod (p - 1)
        var p = parameters.Item1;
        var w = s.ModInverse(p.Subtract(BigInteger.One));

        // Calculate u1 = Hash(message) * w mod (p - 1)
        var hash = HashMessage(message);
        var u1 = hash.Multiply(w).Mod(p.Subtract(BigInteger.One));

        // Calculate u2 = r * w mod (p - 1)
        var u2 = r.Multiply(w).Mod(p.Subtract(BigInteger.One));

        // Calculate v = (g^u1 * y^u2 mod p) mod p mod (p - 1)
        var g = parameters.Item2;
        var y = publicKey;
        var v = (g.ModPow(u1, p).Multiply(y.ModPow(u2, p))).Mod(p).Mod(p.Subtract(BigInteger.One));

        // Verify signature
        return v.Equals(r);
    }

    private BigInteger HashMessage(string message)
    {
        // Simple hash function for demonstration purposes
        byte[] bytes = Encoding.UTF8.GetBytes(message);
        byte[] hashBytes = System.Security.Cryptography.SHA256.Create().ComputeHash(bytes);
        return new BigInteger(1, hashBytes);
    }
}

и кнопка которая реализует генерацию и здесь все получается генерировать подпись с использованием параметров из SQLite.
public partial class Subscribe_message : MetroForm
{
    private string dbFileName = @"D:\Учеба\ИТИ магис\2 курс 2 сем\Диссертация\проект\Programs\EL_Gamal\EL_Gamal\database\Keys.db";
    public Subscribe_message()
    {
        InitializeComponent();
    }

    private void Subscribe_Click(object sender, EventArgs e)
    {
        // Создаем диалоговое окно для выбора файла
        OpenFileDialog openFileDialog = new OpenFileDialog();

        // Устанавливаем фильтр для выбора только текстовых файлов
        openFileDialog.Filter = "Text Files|*.txt";

        // Открываем диалоговое окно
        if (openFileDialog.ShowDialog() == DialogResult.OK)
        {
            // Получаем путь к выбранному файлу
            string filePath = openFileDialog.FileName;

            // Создаем экземпляр класса ElGamalDigitalSignature
            ElGamalDigitalSignature digitalSignature = new ElGamalDigitalSignature(dbFileName);

            // Считываем содержимое файла
            string message;
            using (StreamReader reader = new StreamReader(filePath))
            {
                message = reader.ReadToEnd();
            }

            // Подписываем содержимое файла
            byte[] signature = digitalSignature.Sign(message);

            // Разделяем подпись на две части: r и s
            var rBytes = new byte[signature.Length / 2];
            var sBytes = new byte[signature.Length / 2];
            Array.Copy(signature, 0, rBytes, 0, rBytes.Length);
            Array.Copy(signature, rBytes.Length, sBytes, 0, sBytes.Length);

            // Преобразуем r и s в строки для вывода
            string rString = BitConverter.ToString(rBytes).Replace("-", "");
            string sString = BitConverter.ToString(sBytes).Replace("-", "");

            number_R.Text = rString;
            number_S.Text = sString;
            Export.Visible = true;
        }
    }

здесь я передаю параметры r и s чтобы в другой форме выполнить эксопрт:
private void Export_Click(object sender, EventArgs e)
{
    // Получаем значения number_R и number_S
    string rValue = number_R.Text;
    string sValue = number_S.Text;
    // Создаем экземпляр формы Subscribe и передаем значения number_R и number_S в конструктор
    Subscribe subscribeForm = new Subscribe(rValue, sValue);
    this.Close();
    subscribeForm.ShowDialog();
}

и ее форма,где выполняю экспорт:
public partial class Subscribe : MetroForm
{
    private string dbFileName = @"D:\Учеба\ИТИ магис\2 курс 2 сем\Диссертация\проект\Programs\EL_Gamal\EL_Gamal\database\Keys.db";
    private string rValue;
    private string sValue;
    private SignatureExporter signatureExporter;

    public Subscribe(string rValue, string sValue)
    {
        InitializeComponent();
        this.rValue = rValue;
        this.sValue = sValue;
    }
    private byte[] ConvertHexStringToByteArray(string hexString)
    {
        int length = hexString.Length;
        byte[] bytes = new byte[length / 2];
        for (int i = 0; i < length; i += 2)
        {
            bytes[i / 2] = Convert.ToByte(hexString.Substring(i, 2), 16);
        }
        return bytes;
    }
    private void Export_sub_Click(object sender, EventArgs e)
    {
        // Создаем экземпляр класса SignatureExporter
        signatureExporter = new SignatureExporter(dbFileName);

        // Получаем значения r и s из конструктора и вызываем метод экспорта подписи
        byte[] r = ConvertHexStringToByteArray(rValue);
        byte[] s = ConvertHexStringToByteArray(sValue);
        signatureExporter.ExportSignature(r, s);

        // Выводим сообщение об успешном экспорте
        MessageBox.Show("Подпись успешно экспортирована в базу данных.");
    }
}

ну и класс, где я реализовываю импорт ключей:
public class ElGamalKeyParametersImporter
{
    private string connectionString;

    public ElGamalKeyParametersImporter(string dbFileName)
    {
        // Формируем строку подключения к базе данных SQLite
        connectionString = $"Data Source={dbFileName};Version=3;";
    }
    public Tuple<BigInteger, BigInteger> ImportParameters()
    {
        try
        {
            using (SQLiteConnection connection = new SQLiteConnection(connectionString))
            {
                connection.Open();
                using (SQLiteCommand command = connection.CreateCommand())
                {
                    // Выполняем SQL-запрос для получения параметров из таблицы ElGamalParameters
                    command.CommandText = "SELECT P, G FROM ElGamalParameters ORDER BY ID DESC LIMIT 1";
                    SQLiteDataReader reader = command.ExecuteReader();
                    if (reader.Read())
                    {
                        // Преобразуем результаты в значения BigInteger
                        BigInteger p = new BigInteger(reader["P"].ToString());
                        BigInteger g = new BigInteger(reader["G"].ToString());

                        return new Tuple<BigInteger, BigInteger>(p, g);
                    }
                    else
                    {
                        // Если результаты не найдены или произошла ошибка, возвращаем null
                        MetroFramework.MetroMessageBox.Show(null, "Параметры не найдены в базе данных.");
                        return null;
                    }

                }
            }
        }
        catch (Exception ex)
        {
            MetroFramework.MetroMessageBox.Show(null, "Ошибка при импорте параметров из базы данных: " + ex.Message);
            return null;
        }
    }

и я только основное показал, проект вроде не большой но массивный в плане строк кода, но в плане функционала маленький.
Помогите пожалуйста понять, почему, как и каким образом можно решить ошибку database is locked.
Возникает она только при экспорте подписи, вот и кинул все что связано с формой Subscribe.
Заранее спасибо за помощь!!!
  • Вопрос задан
  • 136 просмотров
Решения вопроса 1
AshBlade
@AshBlade Куратор тега C#
Просто хочу быть счастливым
Скорее всего проблема здесь:
SQLiteDataReader reader = command.ExecuteReader();

Ты его не закрываешь и в результате соединение висит.
Подсказка: от реализует интерфейс IDisposable
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы