SphincsPlusSigner
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using System;
namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus
{
[Obsolete("Use SLH-DSA instead")]
public sealed class SphincsPlusSigner : IMessageSigner
{
private SphincsPlusPrivateKeyParameters m_privKey;
private SphincsPlusPublicKeyParameters m_pubKey;
private SecureRandom m_random;
public void Init(bool forSigning, ICipherParameters param)
{
if (forSigning) {
m_pubKey = null;
ParametersWithRandom parametersWithRandom = param as ParametersWithRandom;
if (parametersWithRandom != null) {
m_privKey = (SphincsPlusPrivateKeyParameters)parametersWithRandom.Parameters;
m_random = parametersWithRandom.Random;
} else {
m_privKey = (SphincsPlusPrivateKeyParameters)param;
m_random = null;
}
} else {
m_pubKey = (SphincsPlusPublicKeyParameters)param;
m_privKey = null;
m_random = null;
}
}
public byte[] GenerateSignature(byte[] message)
{
SphincsPlusEngine engine = m_privKey.Parameters.GetEngine();
engine.Init(m_privKey.GetPublicSeed());
byte[] array = new byte[engine.N];
if (m_random != null)
m_random.NextBytes(array);
else
Array.Copy(m_privKey.m_pk.seed, 0, array, 0, array.Length);
Fors fors = new Fors(engine);
byte[] array2 = engine.PRF_msg(m_privKey.m_sk.prf, array, message, 0, message.Length);
IndexedDigest indexedDigest = engine.H_msg(array2, m_privKey.m_pk.seed, m_privKey.m_pk.root, message, 0, message.Length);
byte[] digest = indexedDigest.digest;
ulong idx_tree = indexedDigest.idx_tree;
uint idx_leaf = indexedDigest.idx_leaf;
Adrs adrs = new Adrs();
adrs.SetTypeAndClear(3);
adrs.SetTreeAddress(idx_tree);
adrs.SetKeyPairAddress(idx_leaf);
SIG_FORS[] array3 = fors.Sign(digest, m_privKey.m_sk.seed, m_privKey.m_pk.seed, adrs, true);
adrs = new Adrs();
adrs.SetTypeAndClear(3);
adrs.SetTreeAddress(idx_tree);
adrs.SetKeyPairAddress(idx_leaf);
byte[] m = fors.PKFromSig(array3, digest, m_privKey.m_pk.seed, adrs, true);
new Adrs().SetTypeAndClear(2);
HT hT = new HT(engine, m_privKey.GetSeed(), m_privKey.GetPublicSeed());
byte[] array4 = new byte[engine.SignatureLength];
int pos = 0;
Array.Copy(array2, 0, array4, 0, array2.Length);
pos += array2.Length;
for (int i = 0; i < array3.Length; i++) {
array3[i].CopyToSignature(array4, ref pos);
}
hT.Sign(m, idx_tree, idx_leaf, array4, ref pos);
return array4;
}
public bool VerifySignature(byte[] message, byte[] signature)
{
SphincsPlusEngine engine = m_pubKey.Parameters.GetEngine();
if (engine.SignatureLength != signature.Length)
return false;
engine.Init(m_pubKey.GetSeed());
Adrs adrs = new Adrs();
SIG sIG = new SIG(engine.N, engine.K, engine.A, engine.D, engine.H_PRIME, engine.WOTS_LEN, signature);
byte[] r = sIG.R;
SIG_FORS[] sIG_FORS = sIG.SIG_FORS;
SIG_XMSS[] sIG_HT = sIG.SIG_HT;
IndexedDigest indexedDigest = engine.H_msg(r, m_pubKey.GetSeed(), m_pubKey.GetRoot(), message, 0, message.Length);
byte[] digest = indexedDigest.digest;
ulong idx_tree = indexedDigest.idx_tree;
uint idx_leaf = indexedDigest.idx_leaf;
adrs.SetTypeAndClear(3);
adrs.SetLayerAddress(0);
adrs.SetTreeAddress(idx_tree);
adrs.SetKeyPairAddress(idx_leaf);
byte[] m = new Fors(engine).PKFromSig(sIG_FORS, digest, m_pubKey.GetSeed(), adrs, true);
adrs.SetTypeAndClear(2);
adrs.SetLayerAddress(0);
adrs.SetTreeAddress(idx_tree);
adrs.SetKeyPairAddress(idx_leaf);
return new HT(engine, null, m_pubKey.GetSeed()).Verify(m, sIG_HT, m_pubKey.GetSeed(), idx_tree, idx_leaf, m_pubKey.GetRoot());
}
}
}