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

BaseKdfBytesGenerator

public abstract class BaseKdfBytesGenerator : IDerivationFunction
using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Crypto.Utilities; using System; namespace Org.BouncyCastle.Crypto.Generators { public abstract class BaseKdfBytesGenerator : IDerivationFunction { private int counterStart; private IDigest digest; private byte[] shared; private byte[] iv; public IDigest Digest => digest; protected BaseKdfBytesGenerator(int counterStart, IDigest digest) { this.counterStart = counterStart; this.digest = digest; } public void Init(IDerivationParameters parameters) { KdfParameters kdfParameters = parameters as KdfParameters; if (kdfParameters != null) { shared = kdfParameters.GetSharedSecret(); iv = kdfParameters.GetIV(); } else { Iso18033KdfParameters iso18033KdfParameters = parameters as Iso18033KdfParameters; if (iso18033KdfParameters == null) throw new ArgumentException("KDF parameters required for KDF Generator"); shared = iso18033KdfParameters.GetSeed(); iv = null; } } public int GenerateBytes(byte[] output, int outOff, int length) { Check.OutputLength(output, outOff, length, "output buffer too short"); return GenerateBytes(output.AsSpan(outOff, length)); } public unsafe int GenerateBytes(Span<byte> output) { long num = output.Length; int digestSize = digest.GetDigestSize(); if (num > 8589934591) throw new ArgumentException("Output length too large"); int num2 = (int)((num + digestSize - 1) / digestSize); Span<byte> span; if (digestSize <= 128) { int num3 = digestSize; span = new Span<byte>(stackalloc byte[(int)(uint)num3], num3); } else span = new byte[digestSize]; Span<byte> output2 = span; Span<byte> span2 = new Span<byte>(stackalloc byte[4], 4); Pack.UInt32_To_BE((uint)counterStart, span2); uint num4 = (uint)(counterStart & -256); for (int i = 0; i < num2; i++) { digest.BlockUpdate(shared); digest.BlockUpdate(span2); if (iv != null) digest.BlockUpdate(iv); digest.DoFinal(output2); int length = output.Length; if (length > digestSize) { output2.CopyTo(output); int num3 = digestSize; output = output.Slice(num3, output.Length - num3); } else { span = output2.Slice(0, length); span.CopyTo(output); } if (++span2[3] == 0) { num4 += 256; Pack.UInt32_To_BE(num4, span2); } } digest.Reset(); return (int)num; } } }