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

HMacDsaKCalculator

using Org.BouncyCastle.Crypto.Macs; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities; using System; namespace Org.BouncyCastle.Crypto.Signers { public class HMacDsaKCalculator : IDsaKCalculator { private readonly HMac hMac; private readonly byte[] K; private readonly byte[] V; private BigInteger n; public virtual bool IsDeterministic => true; public HMacDsaKCalculator(IDigest digest) { hMac = new HMac(digest); int macSize = hMac.GetMacSize(); V = new byte[macSize]; K = new byte[macSize]; } public virtual void Init(BigInteger n, SecureRandom random) { throw new InvalidOperationException("Operation not supported"); } public unsafe void Init(BigInteger n, BigInteger d, byte[] message) { this.n = n; BigInteger bigInteger = BitsToInt(message); if (bigInteger.CompareTo(n) >= 0) bigInteger = bigInteger.Subtract(n); int unsignedByteLength = BigIntegers.GetUnsignedByteLength(n); int num = unsignedByteLength * 2; Span<byte> span; int num2; if (num <= 512) { num2 = num; span = new Span<byte>(stackalloc byte[(int)(uint)num2], num2); } else span = new byte[num]; Span<byte> span2 = span; BigIntegers.AsUnsignedByteArray(d, span2.Slice(0, unsignedByteLength)); BigInteger bigInteger2 = bigInteger; num2 = unsignedByteLength; BigIntegers.AsUnsignedByteArray(bigInteger2, span2.Slice(num2, span2.Length - num2)); Arrays.Fill(K, 0); Arrays.Fill(V, 1); hMac.Init(new KeyParameter(K)); hMac.BlockUpdate(V, 0, V.Length); hMac.Update(0); hMac.BlockUpdate(span2); InitAdditionalInput0(hMac); hMac.DoFinal(K, 0); hMac.Init(new KeyParameter(K)); hMac.BlockUpdate(V, 0, V.Length); hMac.DoFinal(V, 0); hMac.BlockUpdate(V, 0, V.Length); hMac.Update(1); hMac.BlockUpdate(span2); InitAdditionalInput1(hMac); hMac.DoFinal(K, 0); hMac.Init(new KeyParameter(K)); hMac.BlockUpdate(V, 0, V.Length); hMac.DoFinal(V, 0); } public virtual BigInteger NextK() { byte[] array = new byte[BigIntegers.GetUnsignedByteLength(n)]; BigInteger bigInteger; while (true) { int num; for (int i = 0; i < array.Length; i += num) { hMac.BlockUpdate(V, 0, V.Length); hMac.DoFinal(V, 0); num = System.Math.Min(array.Length - i, V.Length); Array.Copy(V, 0, array, i, num); } bigInteger = BitsToInt(array); if (bigInteger.SignValue > 0 && bigInteger.CompareTo(n) < 0) break; hMac.BlockUpdate(V, 0, V.Length); hMac.Update(0); hMac.DoFinal(K, 0); hMac.Init(new KeyParameter(K)); hMac.BlockUpdate(V, 0, V.Length); hMac.DoFinal(V, 0); } return bigInteger; } protected virtual void InitAdditionalInput0(HMac hmac0) { } protected virtual void InitAdditionalInput1(HMac hmac1) { } private BigInteger BitsToInt(byte[] t) { int num = t.Length * 8; int bitLength = n.BitLength; BigInteger bigInteger = BigIntegers.FromUnsignedByteArray(t); if (num > bitLength) bigInteger = bigInteger.ShiftRight(num - bitLength); return bigInteger; } } }