Files
git.stella-ops.org/src/__Libraries/StellaOps.Cryptography.Plugin.SmRemote/SmRemoteHttpClient.cs
StellaOps Bot bc0762e97d up
2025-12-09 00:20:52 +02:00

91 lines
3.3 KiB
C#

using System.Net.Http.Json;
namespace StellaOps.Cryptography.Plugin.SmRemote;
public sealed class SmRemoteHttpClient
{
private readonly HttpClient client;
public SmRemoteHttpClient(HttpClient client)
{
this.client = client ?? throw new ArgumentNullException(nameof(client));
}
public async Task<SmRemoteStatus> GetStatusAsync(CancellationToken cancellationToken = default)
{
var response = await client.GetAsync("/status", cancellationToken).ConfigureAwait(false);
response.EnsureSuccessStatusCode();
var status = await response.Content.ReadFromJsonAsync<SmRemoteStatus>(cancellationToken: cancellationToken).ConfigureAwait(false);
return status ?? new SmRemoteStatus { IsAvailable = false, Error = "empty response" };
}
public async Task<string> SignAsync(string keyId, string algorithmId, byte[] pae, CancellationToken cancellationToken = default)
{
var request = new SmRemoteSignRequest
{
KeyId = keyId,
AlgorithmId = algorithmId,
PayloadBase64 = Convert.ToBase64String(pae)
};
var response = await client.PostAsJsonAsync("/sign", request, cancellationToken).ConfigureAwait(false);
response.EnsureSuccessStatusCode();
var envelope = await response.Content.ReadFromJsonAsync<SmRemoteSignResponse>(cancellationToken: cancellationToken).ConfigureAwait(false);
if (envelope is null || string.IsNullOrWhiteSpace(envelope.Signature))
{
throw new InvalidOperationException("SM remote sign response was empty.");
}
return envelope.Signature;
}
public async Task<bool> VerifyAsync(string keyId, string algorithmId, byte[] pae, string signatureBase64, CancellationToken cancellationToken = default)
{
var request = new SmRemoteVerifyRequest
{
KeyId = keyId,
AlgorithmId = algorithmId,
PayloadBase64 = Convert.ToBase64String(pae),
Signature = signatureBase64
};
var response = await client.PostAsJsonAsync("/verify", request, cancellationToken).ConfigureAwait(false);
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadFromJsonAsync<SmRemoteVerifyResponse>(cancellationToken: cancellationToken).ConfigureAwait(false);
return result?.Valid == true;
}
}
internal sealed class SmRemoteSignRequest
{
public string KeyId { get; set; } = string.Empty;
public string AlgorithmId { get; set; } = string.Empty;
public string PayloadBase64 { get; set; } = string.Empty;
}
public sealed class SmRemoteSignResponse
{
public string Signature { get; set; } = string.Empty;
}
public sealed class SmRemoteVerifyRequest
{
public string KeyId { get; set; } = string.Empty;
public string AlgorithmId { get; set; } = string.Empty;
public string PayloadBase64 { get; set; } = string.Empty;
public string Signature { get; set; } = string.Empty;
}
public sealed class SmRemoteVerifyResponse
{
public bool Valid { get; set; }
}
public sealed class SmRemoteStatus
{
public bool IsAvailable { get; set; }
public string? ProviderName { get; set; }
public string[] SupportedAlgorithms { get; set; } = Array.Empty<string>();
public string? Error { get; set; }
}