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

HkdfBytesGenerator

public sealed class HkdfBytesGenerator : IDerivationFunction
using Org.BouncyCastle.Crypto.Macs; using Org.BouncyCastle.Crypto.Parameters; using System; namespace Org.BouncyCastle.Crypto.Generators { public sealed class HkdfBytesGenerator : IDerivationFunction { private HMac hMacHash; private int hashLen; private byte[] info; private byte[] currentT; private int generatedBytes; public IDigest Digest => hMacHash.GetUnderlyingDigest(); public HkdfBytesGenerator(IDigest hash) { hMacHash = new HMac(hash); hashLen = hash.GetDigestSize(); } public void Init(IDerivationParameters parameters) { HkdfParameters hkdfParameters = parameters as HkdfParameters; if (hkdfParameters == null) throw new ArgumentException("HKDF parameters required for HkdfBytesGenerator", "parameters"); if (hkdfParameters.SkipExtract) hMacHash.Init(new KeyParameter(hkdfParameters.GetIkm())); else hMacHash.Init(Extract(hkdfParameters.GetSalt(), hkdfParameters.GetIkm())); info = hkdfParameters.GetInfo(); generatedBytes = 0; currentT = new byte[hashLen]; } private KeyParameter Extract(byte[] salt, byte[] ikm) { if (salt == null) hMacHash.Init(new KeyParameter(new byte[hashLen])); else hMacHash.Init(new KeyParameter(salt)); hMacHash.BlockUpdate(ikm, 0, ikm.Length); byte[] array = new byte[hashLen]; hMacHash.DoFinal(array, 0); return new KeyParameter(array); } private void ExpandNext() { int num = generatedBytes / hashLen + 1; if (num >= 256) throw new DataLengthException("HKDF cannot generate more than 255 blocks of HashLen size"); if (generatedBytes != 0) hMacHash.BlockUpdate(currentT, 0, hashLen); hMacHash.BlockUpdate(info, 0, info.Length); hMacHash.Update((byte)num); hMacHash.DoFinal(currentT, 0); } public int GenerateBytes(byte[] output, int outOff, int length) { if (generatedBytes > 255 * hashLen - length) throw new DataLengthException("HKDF may only be used for 255 * HashLen bytes of output"); int num = length; int num2 = generatedBytes % hashLen; if (num2 != 0) { int num3 = System.Math.Min(hashLen - num2, num); Array.Copy(currentT, num2, output, outOff, num3); generatedBytes += num3; num -= num3; outOff += num3; } while (num > 0) { ExpandNext(); int num4 = System.Math.Min(hashLen, num); Array.Copy(currentT, 0, output, outOff, num4); generatedBytes += num4; num -= num4; outOff += num4; } return length; } } }