KdfDoublePipelineIterationBytesGenerator
public sealed class KdfDoublePipelineIterationBytesGenerator : IMacDerivationFunction, IDerivationFunction
using Org.BouncyCastle.Crypto.Macs;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using System;
namespace Org.BouncyCastle.Crypto.Generators
{
public sealed class KdfDoublePipelineIterationBytesGenerator : IMacDerivationFunction, IDerivationFunction
{
private readonly IMac prf;
private readonly int h;
private byte[] fixedInputData;
private int maxSizeExcl;
private byte[] ios;
private bool useCounter;
private int generatedBytes;
private byte[] a;
private byte[] k;
public IMac Mac => prf;
public IDigest Digest => (prf as HMac)?.GetUnderlyingDigest();
public KdfDoublePipelineIterationBytesGenerator(IMac prf)
{
this.prf = prf;
h = prf.GetMacSize();
a = new byte[h];
k = new byte[h];
}
public void Init(IDerivationParameters parameters)
{
KdfDoublePipelineIterationParameters kdfDoublePipelineIterationParameters = parameters as KdfDoublePipelineIterationParameters;
if (kdfDoublePipelineIterationParameters == null)
throw new ArgumentException("Wrong type of arguments given");
prf.Init(new KeyParameter(kdfDoublePipelineIterationParameters.Ki));
fixedInputData = kdfDoublePipelineIterationParameters.FixedInputData;
int r = kdfDoublePipelineIterationParameters.R;
ios = new byte[r / 8];
if (kdfDoublePipelineIterationParameters.UseCounter) {
BigInteger bigInteger = BigInteger.One.ShiftLeft(r).Multiply(BigInteger.ValueOf(h));
maxSizeExcl = ((bigInteger.BitLength > 31) ? 2147483647 : bigInteger.IntValueExact);
} else
maxSizeExcl = 2147483647;
useCounter = kdfDoublePipelineIterationParameters.UseCounter;
generatedBytes = 0;
}
public int GenerateBytes(byte[] output, int outOff, int length)
{
if (generatedBytes >= maxSizeExcl - length)
throw new DataLengthException("Current KDFCTR may only be used for " + maxSizeExcl.ToString() + " bytes");
int num = length;
int num2 = generatedBytes % h;
if (num2 != 0) {
int num3 = System.Math.Min(h - num2, num);
Array.Copy(k, num2, output, outOff, num3);
generatedBytes += num3;
num -= num3;
outOff += num3;
}
while (num > 0) {
GenerateNext();
int num4 = System.Math.Min(h, num);
Array.Copy(k, 0, output, outOff, num4);
generatedBytes += num4;
num -= num4;
outOff += num4;
}
return length;
}
private void GenerateNext()
{
if (generatedBytes == 0) {
prf.BlockUpdate(fixedInputData, 0, fixedInputData.Length);
prf.DoFinal(a, 0);
} else {
prf.BlockUpdate(a, 0, a.Length);
prf.DoFinal(a, 0);
}
prf.BlockUpdate(a, 0, a.Length);
if (useCounter) {
int num = generatedBytes / h + 1;
switch (ios.Length) {
case 4:
ios[0] = (byte)(num >> 24);
goto case 3;
case 3:
ios[ios.Length - 3] = (byte)(num >> 16);
goto case 2;
case 2:
ios[ios.Length - 2] = (byte)(num >> 8);
break;
case 1:
break;
default:
throw new InvalidOperationException("Unsupported size of counter i");
}
ios[ios.Length - 1] = (byte)num;
prf.BlockUpdate(ios, 0, ios.Length);
}
prf.BlockUpdate(fixedInputData, 0, fixedInputData.Length);
prf.DoFinal(k, 0);
}
}
}