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

Lms

public static class Lms
using Org.BouncyCastle.Crypto; using System; namespace Org.BouncyCastle.Pqc.Crypto.Lms { public static class Lms { internal static ushort D_LEAF = 33410; internal static ushort D_INTR = 33667; public static LmsPrivateKeyParameters GenerateKeys(LMSigParameters parameterSet, LMOtsParameters lmOtsParameters, int q, byte[] I, byte[] rootSeed) { if (rootSeed == null || rootSeed.Length < parameterSet.M) throw new ArgumentException($"""{parameterSet.M}"); int maxQ = 1 << parameterSet.H; return new LmsPrivateKeyParameters(parameterSet, lmOtsParameters, q, I, maxQ, rootSeed); } public static LmsSignature GenerateSign(LmsPrivateKeyParameters privateKey, byte[] message) { LmsContext lmsContext = privateKey.GenerateLmsContext(); lmsContext.BlockUpdate(message, 0, message.Length); return GenerateSign(lmsContext); } public static LmsSignature GenerateSign(LmsContext context) { LMOtsSignature otsSignature = LMOts.LMOtsGenerateSignature(context.PrivateKey, context.GetQ(), context.C); return new LmsSignature(context.PrivateKey.Q, otsSignature, context.SigParams, context.Path); } public static bool VerifySignature(LmsPublicKeyParameters publicKey, LmsSignature S, byte[] message) { LmsContext lmsContext = publicKey.GenerateOtsContext(S); LmsUtilities.ByteArray(message, lmsContext); return VerifySignature(publicKey, lmsContext); } public static bool VerifySignature(LmsPublicKeyParameters publicKey, byte[] S, byte[] message) { LmsContext lmsContext = publicKey.GenerateLmsContext(S); LmsUtilities.ByteArray(message, lmsContext); return VerifySignature(publicKey, lmsContext); } public static bool VerifySignature(LmsPublicKeyParameters publicKey, LmsContext context) { LmsSignature lmsSignature = (LmsSignature)context.Signature; LMSigParameters sigParameters = lmsSignature.SigParameters; int h = sigParameters.H; byte[][] y = lmsSignature.Y; byte[] array = LMOts.LMOtsValidateSignatureCalculate(context); int num = (1 << h) + lmsSignature.Q; byte[] i = publicKey.GetI(); IDigest digest = LmsUtilities.GetDigest(sigParameters); byte[] array2 = new byte[digest.GetDigestSize()]; digest.BlockUpdate(i, 0, i.Length); LmsUtilities.U32Str(num, digest); LmsUtilities.U16Str((short)D_LEAF, digest); digest.BlockUpdate(array, 0, array.Length); digest.DoFinal(array2, 0); int num2 = 0; while (num > 1) { if ((num & 1) == 1) { digest.BlockUpdate(i, 0, i.Length); LmsUtilities.U32Str(num / 2, digest); LmsUtilities.U16Str((short)D_INTR, digest); digest.BlockUpdate(y[num2], 0, y[num2].Length); digest.BlockUpdate(array2, 0, array2.Length); digest.DoFinal(array2, 0); } else { digest.BlockUpdate(i, 0, i.Length); LmsUtilities.U32Str(num / 2, digest); LmsUtilities.U16Str((short)D_INTR, digest); digest.BlockUpdate(array2, 0, array2.Length); digest.BlockUpdate(y[num2], 0, y[num2].Length); digest.DoFinal(array2, 0); } num /= 2; num2++; if (num2 == y.Length && num > 1) return false; } byte[] sig = array2; return publicKey.MatchesT1(sig); } } }