<PackageReference Include="BouncyCastle.Cryptography" Version="2.6.2" />

SlhDsaSigner

public sealed class SlhDsaSigner : ISigner
using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Pqc.Crypto.SphincsPlus; using Org.BouncyCastle.Security; using System; using System.IO; namespace Org.BouncyCastle.Crypto.Signers { public sealed class SlhDsaSigner : ISigner { private sealed class Buffer : MemoryStream { private int m_prefixLength; internal void Init(byte[] context) { lock (this) { TruncateAndClear(0); WriteByte(0); WriteByte((byte)context.Length); Write(context, 0, context.Length); m_prefixLength = Convert.ToInt32(Length); } } internal byte[] GenerateSignature(SlhDsaPrivateKeyParameters privateKey, SphincsPlusEngine engine, SecureRandom random) { lock (this) { byte[] buffer = GetBuffer(); int msgLen = Convert.ToInt32(Length); byte[] optRand = (random == null) ? null : SecureRandom.GetNextBytes(random, engine.N); byte[] result = privateKey.SignInternal(optRand, buffer, 0, msgLen); Reset(); return result; } } internal bool VerifySignature(SlhDsaPublicKeyParameters publicKey, SphincsPlusEngine engine, byte[] signature) { if (engine.SignatureLength != signature.Length) { Reset(); return false; } lock (this) { byte[] buffer = GetBuffer(); int msgLen = Convert.ToInt32(Length); bool result = publicKey.VerifyInternal(buffer, 0, msgLen, signature); Reset(); return result; } } internal void Reset() { lock (this) { TruncateAndClear(m_prefixLength); } } private void TruncateAndClear(int newLength) { int num = Convert.ToInt32(Length); Array.Clear(GetBuffer(), newLength, num - newLength); SetLength(newLength); } } private readonly Buffer m_buffer = new Buffer(); private readonly SlhDsaParameters m_parameters; private readonly bool m_deterministic; private SlhDsaPrivateKeyParameters m_privateKey; private SlhDsaPublicKeyParameters m_publicKey; private SecureRandom m_random; private SphincsPlusEngine m_engine; public string AlgorithmName => m_parameters.Name; public SlhDsaSigner(SlhDsaParameters parameters, bool deterministic) { if (parameters == null) throw new ArgumentNullException("parameters"); if (parameters.PreHashOid != null) throw new ArgumentException("cannot be used for HashSLH-DSA", "parameters"); m_parameters = parameters; m_deterministic = deterministic; } public void Init(bool forSigning, ICipherParameters parameters) { byte[] array = null; ParametersWithContext parametersWithContext = parameters as ParametersWithContext; if (parametersWithContext != null) { if (parametersWithContext.ContextLength > 255) throw new ArgumentOutOfRangeException("context too long", "parameters"); array = parametersWithContext.GetContext(); parameters = parametersWithContext.Parameters; } if (forSigning) { SecureRandom secureRandom = null; ParametersWithRandom parametersWithRandom = parameters as ParametersWithRandom; if (parametersWithRandom != null) { secureRandom = parametersWithRandom.Random; parameters = parametersWithRandom.Parameters; } m_privateKey = (SlhDsaPrivateKeyParameters)parameters; m_publicKey = null; m_random = (m_deterministic ? null : CryptoServicesRegistrar.GetSecureRandom(secureRandom)); m_engine = GetEngine(m_privateKey.Parameters); } else { m_privateKey = null; m_publicKey = (SlhDsaPublicKeyParameters)parameters; m_random = null; m_engine = GetEngine(m_publicKey.Parameters); } m_buffer.Init(array ?? Array.Empty<byte>()); } public void Update(byte input) { m_buffer.WriteByte(input); } public void BlockUpdate(byte[] input, int inOff, int inLen) { m_buffer.Write(input, inOff, inLen); } public int GetMaxSignatureSize() { return m_engine.SignatureLength; } public byte[] GenerateSignature() { if (m_privateKey == null) throw new InvalidOperationException("SlhDsaSigner not initialised for signature generation."); return m_buffer.GenerateSignature(m_privateKey, m_engine, m_random); } public bool VerifySignature(byte[] signature) { if (m_publicKey == null) throw new InvalidOperationException("SlhDsaSigner not initialised for verification"); return m_buffer.VerifySignature(m_publicKey, m_engine, signature); } public void Reset() { m_buffer.Reset(); } private SphincsPlusEngine GetEngine(SlhDsaParameters keyParameters) { SlhDsaParameterSet parameterSet = keyParameters.ParameterSet; if (keyParameters.ParameterSet != m_parameters.ParameterSet) throw new ArgumentException("Mismatching key parameter set", "keyParameters"); return parameterSet.GetEngine(); } } }