SlhDsaSigner
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();
}
}
}