using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; using StellaOps.Cryptography; using System; using System.Collections.Concurrent; using System.Collections.Generic; namespace StellaOps.Cryptography.Plugin.PqSoft; /// /// Software-only post-quantum provider (Dilithium3, Falcon512) using BouncyCastle PQC primitives. /// Guarded by the PQ_SOFT_ALLOWED environment variable by default. /// public sealed partial class PqSoftCryptoProvider : ICryptoProvider, ICryptoProviderDiagnostics { private const string EnvGate = "PQ_SOFT_ALLOWED"; private static readonly HashSet SupportedAlgorithms = new(StringComparer.OrdinalIgnoreCase) { SignatureAlgorithms.Dilithium3, SignatureAlgorithms.Falcon512 }; private readonly ConcurrentDictionary _entries = new(StringComparer.OrdinalIgnoreCase); private readonly ILogger _logger; private readonly PqSoftProviderOptions _options; public PqSoftCryptoProvider( IOptions? optionsAccessor = null, ILogger? logger = null) { _options = optionsAccessor?.Value ?? new PqSoftProviderOptions(); _logger = logger ?? NullLogger.Instance; foreach (var key in _options.Keys) { TryLoadKeyFromFile(key); } } public string Name => "pq.soft"; public bool Supports(CryptoCapability capability, string algorithmId) { if (!GateEnabled() || string.IsNullOrWhiteSpace(algorithmId)) { return false; } return capability switch { CryptoCapability.Signing or CryptoCapability.Verification => SupportedAlgorithms.Contains(algorithmId), _ => false }; } public IPasswordHasher GetPasswordHasher(string algorithmId) => throw new NotSupportedException("PQ provider does not expose password hashing."); public ICryptoHasher GetHasher(string algorithmId) => throw new NotSupportedException("PQ provider does not expose hashing."); }