using StellaOps.Cryptography; using System; using System.Collections.Generic; using System.Linq; namespace StellaOps.Cryptography.Plugin.PqSoft; public sealed partial class PqSoftCryptoProvider { public ICryptoSigner GetSigner(string algorithmId, CryptoKeyReference keyReference) { EnsureAllowed(); ArgumentNullException.ThrowIfNull(keyReference); if (!SupportedAlgorithms.Contains(algorithmId)) { throw new InvalidOperationException($"Signing algorithm '{algorithmId}' is not supported by provider '{Name}'."); } if (!_entries.TryGetValue(keyReference.KeyId, out var entry)) { throw new KeyNotFoundException($"Signing key '{keyReference.KeyId}' is not registered with provider '{Name}'."); } if (!string.Equals(entry.AlgorithmId, algorithmId, StringComparison.OrdinalIgnoreCase)) { throw new InvalidOperationException($"Signing key '{keyReference.KeyId}' is registered for algorithm '{entry.AlgorithmId}', not '{algorithmId}'."); } return entry.CreateSigner(); } public void UpsertSigningKey(CryptoSigningKey signingKey) { EnsureAllowed(); ArgumentNullException.ThrowIfNull(signingKey); var normalizedAlg = Normalize(signingKey.AlgorithmId); if (!SupportedAlgorithms.Contains(normalizedAlg)) { throw new InvalidOperationException($"Signing algorithm '{normalizedAlg}' is not supported by provider '{Name}'."); } if (signingKey.PrivateKey.IsEmpty) { throw new InvalidOperationException("PQ provider requires raw private key bytes."); } var entry = normalizedAlg switch { SignatureAlgorithms.Dilithium3 => CreateDilithiumEntry(signingKey), SignatureAlgorithms.Falcon512 => CreateFalconEntry(signingKey), _ => throw new InvalidOperationException($"Unsupported PQ algorithm '{normalizedAlg}'.") }; _entries.AddOrUpdate(signingKey.Reference.KeyId, entry, (_, _) => entry); } public bool RemoveSigningKey(string keyId) { if (string.IsNullOrWhiteSpace(keyId)) { return false; } return _entries.TryRemove(keyId, out _); } public IReadOnlyCollection GetSigningKeys() => _entries.Values.Select(static e => e.Descriptor).ToArray(); public IEnumerable DescribeKeys() { foreach (var entry in _entries.Values) { yield return new CryptoProviderKeyDescriptor( Name, entry.Descriptor.Reference.KeyId, entry.AlgorithmId, new Dictionary(StringComparer.OrdinalIgnoreCase) { ["provider"] = Name, ["algorithm"] = entry.AlgorithmId, ["certified"] = "false", ["simulation"] = "software" }); } } private static string Normalize(string algorithmId) => algorithmId.ToUpperInvariant(); }