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

DHKekGenerator

public sealed class DHKekGenerator : IDerivationFunction
using Org.BouncyCastle.Asn1; using Org.BouncyCastle.Crypto.Utilities; using System; namespace Org.BouncyCastle.Crypto.Agreement.Kdf { public sealed class DHKekGenerator : IDerivationFunction { private readonly IDigest m_digest; private DerObjectIdentifier algorithm; private int keySize; private byte[] z; private byte[] partyAInfo; public IDigest Digest => m_digest; public DHKekGenerator(IDigest digest) { m_digest = digest; } public void Init(IDerivationParameters param) { DHKdfParameters dHKdfParameters = (DHKdfParameters)param; algorithm = dHKdfParameters.Algorithm; keySize = dHKdfParameters.KeySize; z = dHKdfParameters.GetZ(); partyAInfo = dHKdfParameters.GetExtraInfo(); } public int GenerateBytes(byte[] outBytes, int outOff, int length) { Check.OutputLength(outBytes, outOff, length, "output buffer too short"); return GenerateBytes(outBytes.AsSpan(outOff, length)); } public unsafe int GenerateBytes(Span<byte> output) { long num = output.Length; int digestSize = m_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; uint num4 = 1; for (int i = 0; i < num2; i++) { Asn1EncodableVector asn1EncodableVector = new Asn1EncodableVector(new DerSequence(algorithm, new DerOctetString(Pack.UInt32_To_BE(num4)))); if (partyAInfo != null) asn1EncodableVector.Add(new DerTaggedObject(true, 0, new DerOctetString(partyAInfo))); asn1EncodableVector.Add(new DerTaggedObject(true, 2, new DerOctetString(Pack.UInt32_To_BE((uint)keySize)))); byte[] derEncoded = new DerSequence(asn1EncodableVector).GetDerEncoded(); m_digest.BlockUpdate(z); m_digest.BlockUpdate(derEncoded); m_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); } num4++; } m_digest.Reset(); return (int)num; } } }