using Microsoft.Data.Sqlite; namespace WebDrop.Storage; public sealed record AccountDeviceSigningKey(string PublicKey, byte[] CertificateSignature); public sealed partial class SqliteAccountStore { public AccountDeviceSigningKey? DeviceSigningKey(string username, string deviceId) { lock (_gate) { using var cmd = _connection.CreateCommand(); cmd.CommandText = "SELECT public_key,certificate_signature FROM account_device_signing_keys WHERE username=$u AND device_id=$d"; cmd.Parameters.AddWithValue("$u", username); cmd.Parameters.AddWithValue("$d", deviceId); using var reader = cmd.ExecuteReader(); return reader.Read() ? new(reader.GetString(0), (byte[])reader[1]) : null; } } public bool SaveDeviceSigningKey(string username, string deviceId, string publicKey, byte[] signature) { lock (_gate) { using var device = _connection.CreateCommand(); device.CommandText = "SELECT 1 FROM account_devices WHERE username=$u AND id=$d"; device.Parameters.AddWithValue("$u", username); device.Parameters.AddWithValue("$d", deviceId); if (device.ExecuteScalar() is null) return false; using var cmd = _connection.CreateCommand(); cmd.CommandText = """ INSERT INTO account_device_signing_keys(username,device_id,public_key,certificate_signature,modified_at) VALUES($u,$d,$p,$s,$m) ON CONFLICT(username,device_id) DO UPDATE SET public_key=excluded.public_key, certificate_signature=excluded.certificate_signature,modified_at=excluded.modified_at """; cmd.Parameters.AddWithValue("$u", username); cmd.Parameters.AddWithValue("$d", deviceId); cmd.Parameters.AddWithValue("$p", publicKey); cmd.Parameters.AddWithValue("$s", signature); cmd.Parameters.AddWithValue("$m", DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()); return cmd.ExecuteNonQuery() == 1; } } }