столкнулся с такой проблемой, что при экспорте подписи в БД 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.
Заранее спасибо за помощь!!!