diff --git a/crypto/src/crypto/IMacDerivationFunction.cs b/crypto/src/crypto/IMacDerivationFunction.cs
new file mode 100644
index 000000000..7297cd854
--- /dev/null
+++ b/crypto/src/crypto/IMacDerivationFunction.cs
@@ -0,0 +1,7 @@
+namespace Org.BouncyCastle.Crypto
+{
+ public interface IMacDerivationFunction:IDerivationFunction
+ {
+ IMac GetMac();
+ }
+}
\ No newline at end of file
diff --git a/crypto/src/crypto/generators/KDFCounterBytesGenerator.cs b/crypto/src/crypto/generators/KDFCounterBytesGenerator.cs
new file mode 100644
index 000000000..470d7567b
--- /dev/null
+++ b/crypto/src/crypto/generators/KDFCounterBytesGenerator.cs
@@ -0,0 +1,158 @@
+using System;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+ public class KDFCounterBytesGenerator : IMacDerivationFunction
+ {
+
+ private static readonly BigInteger IntegerMax = BigInteger.ValueOf(0x7fffffff);
+ private static readonly BigInteger Two = BigInteger.Two;
+
+
+ private readonly IMac prf;
+ private readonly int h;
+
+ private byte[] fixedInputDataCtrPrefix;
+ private byte[] fixedInputData_afterCtr;
+ private int maxSizeExcl;
+ // ios is i defined as an octet string (the binary representation)
+ private byte[] ios;
+
+ // operational
+ private int generatedBytes;
+ // k is used as buffer for all K(i) values
+ private byte[] k;
+
+ public KDFCounterBytesGenerator(IMac prf)
+ {
+ this.prf = prf;
+ this.h = prf.GetMacSize();
+ this.k = new byte[h];
+ }
+
+ public void Init(IDerivationParameters param)
+ {
+ KDFCounterParameters kdfParams = param as KDFCounterParameters;
+ if (kdfParams == null)
+ {
+ throw new ArgumentException("Wrong type of arguments given");
+ }
+
+
+
+ // --- init mac based PRF ---
+
+ this.prf.Init(new KeyParameter(kdfParams.Ki));
+
+ // --- set arguments ---
+
+ this.fixedInputDataCtrPrefix = kdfParams.FixedInputDataCounterPrefix;
+ this.fixedInputData_afterCtr = kdfParams.FixedInputDataCounterSuffix;
+
+ int r = kdfParams.R;
+ this.ios = new byte[r / 8];
+
+ BigInteger maxSize = Two.Pow(r).Multiply(BigInteger.ValueOf(h));
+ this.maxSizeExcl = maxSize.CompareTo(IntegerMax) == 1 ?
+ Int32.MaxValue : maxSize.IntValue;
+
+ // --- set operational state ---
+
+ generatedBytes = 0;
+ }
+
+
+ public IMac GetMac()
+ {
+ return prf;
+ }
+
+
+ public IDigest Digest
+ {
+ get
+ {
+ HMac hmac = (prf as HMac);
+ return hmac?.GetUnderlyingDigest();
+ }
+ }
+
+ public int GenerateBytes(byte[] output, int outOff, int length)
+ {
+ int generatedBytesAfter = generatedBytes + length;
+ if (generatedBytesAfter < 0 || generatedBytesAfter >= maxSizeExcl)
+ {
+ throw new DataLengthException(
+ "Current KDFCTR may only be used for " + maxSizeExcl + " bytes");
+ }
+
+ if (generatedBytes % h == 0)
+ {
+ generateNext();
+ }
+
+ // copy what is left in the currentT (1..hash
+ int toGenerate = length;
+ int posInK = generatedBytes % h;
+ int leftInK = h - generatedBytes % h;
+ int toCopy = System.Math.Min(leftInK, toGenerate);
+ Array.Copy(k, posInK, output, outOff, toCopy);
+ generatedBytes += toCopy;
+ toGenerate -= toCopy;
+ outOff += toCopy;
+
+ while (toGenerate > 0)
+ {
+ generateNext();
+ toCopy = System.Math.Min(h, toGenerate);
+ Array.Copy(k, 0, output, outOff, toCopy);
+ generatedBytes += toCopy;
+ toGenerate -= toCopy;
+ outOff += toCopy;
+ }
+
+ return length;
+
+ }
+
+ private void generateNext()
+ {
+
+ int i = generatedBytes / h + 1;
+
+ // encode i into counter buffer
+ switch (ios.Length)
+ {
+ case 4:
+ ios[0] = (byte)(i >> 24);
+ goto case 3;
+ // fall through
+ case 3:
+ ios[ios.Length - 3] = (byte)(i >> 16);
+ // fall through
+ goto case 2;
+ case 2:
+ ios[ios.Length - 2] = (byte)(i >> 8);
+ // fall through
+ goto case 1;
+ case 1:
+ ios[ios.Length - 1] = (byte)i;
+ break;
+ default:
+ throw new InvalidOperationException("Unsupported size of counter i");
+ }
+
+
+
+ // special case for K(0): K(0) is empty, so no update
+ prf.BlockUpdate(fixedInputDataCtrPrefix, 0, fixedInputDataCtrPrefix.Length);
+ prf.BlockUpdate(ios, 0, ios.Length);
+ prf.BlockUpdate(fixedInputData_afterCtr, 0, fixedInputData_afterCtr.Length);
+ prf.DoFinal(k, 0);
+ }
+ }
+}
\ No newline at end of file
diff --git a/crypto/src/crypto/generators/KDFDoublePipelineIterationBytesGenerator.cs b/crypto/src/crypto/generators/KDFDoublePipelineIterationBytesGenerator.cs
new file mode 100644
index 000000000..57e0b2ae0
--- /dev/null
+++ b/crypto/src/crypto/generators/KDFDoublePipelineIterationBytesGenerator.cs
@@ -0,0 +1,185 @@
+using System;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+ public class KDFDoublePipelineIterationBytesGenerator : IMacDerivationFunction
+ {
+ private static readonly BigInteger IntegerMax = BigInteger.ValueOf(0x7fffffff);
+ private static readonly BigInteger Two = BigInteger.Two;
+
+ // fields set by the constructor
+ private readonly IMac prf;
+ private readonly int h;
+
+ // fields set by init
+ private byte[] fixedInputData;
+ private int maxSizeExcl;
+ // ios is i defined as an octet string (the binary representation)
+ private byte[] ios;
+ private bool useCounter;
+
+ // operational
+ private int generatedBytes;
+ // k is used as buffer for all K(i) values
+ private byte[] a;
+ private byte[] k;
+
+
+ public KDFDoublePipelineIterationBytesGenerator(IMac prf)
+ {
+ this.prf = prf;
+ this.h = prf.GetMacSize();
+ this.a = new byte[h];
+ this.k = new byte[h];
+ }
+
+
+ public void Init(IDerivationParameters parameters)
+ {
+ KDFDoublePipelineIterationParameters dpiParams = parameters as KDFDoublePipelineIterationParameters;
+ if (dpiParams == null)
+ {
+ throw new ArgumentException("Wrong type of arguments given");
+ }
+
+
+
+ // --- init mac based PRF ---
+
+ this.prf.Init(new KeyParameter(dpiParams.Ki));
+
+ // --- set arguments ---
+
+ this.fixedInputData = dpiParams.FixedInputData;
+
+ int r = dpiParams.R;
+ this.ios = new byte[r / 8];
+
+ if (dpiParams.UseCounter)
+ {
+ // this is more conservative than the spec
+ BigInteger maxSize = Two.Pow(r).Multiply(BigInteger.ValueOf(h));
+ this.maxSizeExcl = maxSize.CompareTo(IntegerMax) == 1 ?
+ Int32.MaxValue : maxSize.IntValue;
+ }
+ else
+ {
+ this.maxSizeExcl = IntegerMax.IntValue;
+ }
+
+ this.useCounter = dpiParams.UseCounter;
+
+ // --- set operational state ---
+
+ generatedBytes = 0;
+ }
+
+
+
+
+ private void generateNext()
+ {
+
+ if (generatedBytes == 0)
+ {
+ // --- step 4 ---
+ prf.BlockUpdate(fixedInputData, 0, fixedInputData.Length);
+ prf.DoFinal(a, 0);
+ }
+ else
+ {
+ // --- step 5a ---
+ prf.BlockUpdate(a, 0, a.Length);
+ prf.DoFinal(a, 0);
+ }
+
+ // --- step 5b ---
+ prf.BlockUpdate(a, 0, a.Length);
+
+ if (useCounter)
+ {
+ int i = generatedBytes / h + 1;
+
+ // encode i into counter buffer
+ switch (ios.Length)
+ {
+ case 4:
+ ios[0] = (byte)(i >> 24);
+ // fall through
+ goto case 3;
+ case 3:
+ ios[ios.Length - 3] = (byte)(i >> 16);
+ // fall through
+ goto case 2;
+ case 2:
+ ios[ios.Length - 2] = (byte)(i >> 8);
+ // fall through
+ goto case 1;
+ case 1:
+ ios[ios.Length - 1] = (byte)i;
+ break;
+ default:
+ throw new InvalidOperationException("Unsupported size of counter i");
+ }
+ prf.BlockUpdate(ios, 0, ios.Length);
+ }
+
+ prf.BlockUpdate(fixedInputData, 0, fixedInputData.Length);
+ prf.DoFinal(k, 0);
+ }
+
+
+ public IDigest Digest
+ {
+ get
+ {
+ HMac hmac = (prf as HMac);
+ return hmac?.GetUnderlyingDigest();
+ }
+ }
+ public int GenerateBytes(byte[] output, int outOff, int length)
+ {
+ int generatedBytesAfter = generatedBytes + length;
+ if (generatedBytesAfter < 0 || generatedBytesAfter >= maxSizeExcl)
+ {
+ throw new DataLengthException(
+ "Current KDFCTR may only be used for " + maxSizeExcl + " bytes");
+ }
+
+ if (generatedBytes % h == 0)
+ {
+ generateNext();
+ }
+
+ // copy what is left in the currentT (1..hash
+ int toGenerate = length;
+ int posInK = generatedBytes % h;
+ int leftInK = h - generatedBytes % h;
+ int toCopy = System.Math.Min(leftInK, toGenerate);
+ Array.Copy(k, posInK, output, outOff, toCopy);
+ generatedBytes += toCopy;
+ toGenerate -= toCopy;
+ outOff += toCopy;
+
+ while (toGenerate > 0)
+ {
+ generateNext();
+ toCopy = System.Math.Min(h, toGenerate);
+ Array.Copy(k, 0, output, outOff, toCopy);
+ generatedBytes += toCopy;
+ toGenerate -= toCopy;
+ outOff += toCopy;
+ }
+
+ return length;
+ }
+
+ public IMac GetMac()
+ {
+ return prf;
+ }
+ }
+}
\ No newline at end of file
diff --git a/crypto/src/crypto/generators/KDFFeedbackBytesGenerator.cs b/crypto/src/crypto/generators/KDFFeedbackBytesGenerator.cs
new file mode 100644
index 000000000..106cd0125
--- /dev/null
+++ b/crypto/src/crypto/generators/KDFFeedbackBytesGenerator.cs
@@ -0,0 +1,179 @@
+using System;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+ public class KDFFeedbackBytesGenerator : IMacDerivationFunction
+ {
+ private static readonly BigInteger IntegerMax = BigInteger.ValueOf(0x7fffffff);
+ private static readonly BigInteger Two = BigInteger.Two;
+
+ // please refer to the standard for the meaning of the variable names
+ // all field lengths are in bytes, not in bits as specified by the standard
+
+ // fields set by the constructor
+ private readonly IMac prf;
+ private readonly int h;
+
+ // fields set by init
+ private byte[] fixedInputData;
+ private int maxSizeExcl;
+ // ios is i defined as an octet string (the binary representation)
+ private byte[] ios;
+ private byte[] iv;
+ private bool useCounter;
+
+ // operational
+ private int generatedBytes;
+ // k is used as buffer for all K(i) values
+ private byte[] k;
+
+ public KDFFeedbackBytesGenerator(IMac prf)
+ {
+ this.prf = prf;
+ this.h = prf.GetMacSize();
+ this.k = new byte[h];
+ }
+
+
+ public void Init(IDerivationParameters parameters)
+ {
+ KDFFeedbackParameters feedbackParams = parameters as KDFFeedbackParameters;
+ if (feedbackParams == null)
+ {
+ throw new ArgumentException("Wrong type of arguments given");
+ }
+
+
+ // --- init mac based PRF ---
+
+ this.prf.Init(new KeyParameter(feedbackParams.Ki));
+
+ // --- set arguments ---
+
+ this.fixedInputData = feedbackParams.FixedInputData;
+
+ int r = feedbackParams.R;
+ this.ios = new byte[r / 8];
+
+ if (feedbackParams.UseCounter)
+ {
+ // this is more conservative than the spec
+ BigInteger maxSize = Two.Pow(r).Multiply(BigInteger.ValueOf(h));
+ this.maxSizeExcl = maxSize.CompareTo(IntegerMax) == 1 ?
+ Int32.MaxValue : maxSize.IntValue;
+ }
+ else
+ {
+ this.maxSizeExcl = Int32.MaxValue;
+ }
+
+ this.iv = feedbackParams.Iv;
+ this.useCounter = feedbackParams.UseCounter;
+
+ // --- set operational state ---
+
+ generatedBytes = 0;
+ }
+
+ public IDigest Digest
+ {
+ get
+ {
+ HMac hmac = (prf as HMac);
+ return hmac?.GetUnderlyingDigest();
+ }
+ }
+ public int GenerateBytes(byte[] output, int outOff, int length)
+ {
+ int generatedBytesAfter = generatedBytes + length;
+ if (generatedBytesAfter < 0 || generatedBytesAfter >= maxSizeExcl)
+ {
+ throw new DataLengthException(
+ "Current KDFCTR may only be used for " + maxSizeExcl + " bytes");
+ }
+
+ if (generatedBytes % h == 0)
+ {
+ generateNext();
+ }
+
+ // copy what is left in the currentT (1..hash
+ int toGenerate = length;
+ int posInK = generatedBytes % h;
+ int leftInK = h - generatedBytes % h;
+
+
+ int toCopy = System.Math.Min(leftInK, toGenerate);
+ Array.Copy(k, posInK, output, outOff, toCopy);
+
+ generatedBytes += toCopy;
+ toGenerate -= toCopy;
+ outOff += toCopy;
+
+ while (toGenerate > 0)
+ {
+ generateNext();
+ toCopy = System.Math.Min(h, toGenerate);
+ Array.Copy(k, 0, output, outOff, toCopy);
+ generatedBytes += toCopy;
+ toGenerate -= toCopy;
+ outOff += toCopy;
+ }
+
+ return length;
+ }
+
+ private void generateNext()
+ {
+
+ // TODO enable IV
+ if (generatedBytes == 0)
+ {
+ prf.BlockUpdate(iv, 0, iv.Length);
+ }
+ else
+ {
+ prf.BlockUpdate(k, 0, k.Length);
+ }
+
+ if (useCounter)
+ {
+ int i = generatedBytes / h + 1;
+
+ // encode i into counter buffer
+ switch (ios.Length)
+ {
+ case 4:
+ ios[0] = (byte)(i >> 24);
+ goto case 3;
+ // fall through
+ case 3:
+ ios[ios.Length - 3] = (byte)(i >> 16);
+ // fall through
+ goto case 2;
+ case 2:
+ ios[ios.Length - 2] = (byte)(i >> 8);
+ // fall through
+ goto case 1;
+ case 1:
+ ios[ios.Length - 1] = (byte)i;
+ break;
+ default:
+ throw new InvalidOperationException("Unsupported size of counter i");
+ }
+ prf.BlockUpdate(ios, 0, ios.Length);
+ }
+
+ prf.BlockUpdate(fixedInputData, 0, fixedInputData.Length);
+ prf.DoFinal(k, 0);
+ }
+
+ public IMac GetMac()
+ {
+ return prf;
+ }
+ }
+}
\ No newline at end of file
diff --git a/crypto/src/crypto/parameters/KDFCounterParameters.cs b/crypto/src/crypto/parameters/KDFCounterParameters.cs
new file mode 100644
index 000000000..79e0e5f53
--- /dev/null
+++ b/crypto/src/crypto/parameters/KDFCounterParameters.cs
@@ -0,0 +1,91 @@
+using System;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+ public class KDFCounterParameters : IDerivationParameters
+ {
+ private byte[] ki;
+ private byte[] fixedInputDataCounterPrefix;
+ private byte[] fixedInputDataCounterSuffix;
+ private int r;
+
+ /// <summary>
+ /// Base constructor - suffix fixed input data only.
+ /// </summary>
+ /// <param name="ki">the KDF seed</param>
+ /// <param name="fixedInputDataCounterSuffix">fixed input data to follow counter.</param>
+ /// <param name="r">length of the counter in bits</param>
+ public KDFCounterParameters(byte[] ki, byte[] fixedInputDataCounterSuffix, int r) : this(ki, null, fixedInputDataCounterSuffix, r)
+ {
+ }
+
+
+
+ /// <summary>
+ /// Base constructor - prefix and suffix fixed input data.
+ /// </summary>
+ /// <param name="ki">the KDF seed</param>
+ /// <param name="fixedInputDataCounterPrefix">fixed input data to precede counter</param>
+ /// <param name="fixedInputDataCounterSuffix">fixed input data to follow counter.</param>
+ /// <param name="r">length of the counter in bits.</param>
+ public KDFCounterParameters(byte[] ki, byte[] fixedInputDataCounterPrefix, byte[] fixedInputDataCounterSuffix, int r)
+ {
+ if (ki == null)
+ {
+ throw new ArgumentException("A KDF requires Ki (a seed) as input");
+ }
+ this.ki = Arrays.Clone(ki);
+
+ if (fixedInputDataCounterPrefix == null)
+ {
+ this.fixedInputDataCounterPrefix = new byte[0];
+ }
+ else
+ {
+ this.fixedInputDataCounterPrefix = Arrays.Clone(fixedInputDataCounterPrefix);
+ }
+
+ if (fixedInputDataCounterSuffix == null)
+ {
+ this.fixedInputDataCounterSuffix = new byte[0];
+ }
+ else
+ {
+ this.fixedInputDataCounterSuffix = Arrays.Clone(fixedInputDataCounterSuffix);
+ }
+
+ if (r != 8 && r != 16 && r != 24 && r != 32)
+ {
+ throw new ArgumentException("Length of counter should be 8, 16, 24 or 32");
+ }
+ this.r = r;
+ }
+
+ public byte[] Ki
+ {
+ get { return ki; }
+ }
+
+ public byte[] FixedInputData
+ {
+ get { return Arrays.Clone(fixedInputDataCounterSuffix); }
+ }
+
+ public byte[] FixedInputDataCounterPrefix
+ {
+ get { return Arrays.Clone(fixedInputDataCounterPrefix); }
+
+ }
+
+ public byte[] FixedInputDataCounterSuffix
+ {
+ get { return Arrays.Clone(fixedInputDataCounterSuffix); }
+ }
+
+ public int R
+ {
+ get { return r; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/crypto/src/crypto/parameters/KDFDoublePipelineIterationParameters.cs b/crypto/src/crypto/parameters/KDFDoublePipelineIterationParameters.cs
new file mode 100644
index 000000000..d7995cb41
--- /dev/null
+++ b/crypto/src/crypto/parameters/KDFDoublePipelineIterationParameters.cs
@@ -0,0 +1,78 @@
+using System;
+using Org.BouncyCastle.Asn1.Tests;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+
+ public class KDFDoublePipelineIterationParameters : IDerivationParameters
+ {
+ // could be any valid value, using 32, don't know why
+ private static readonly int UNUSED_R = 32;
+
+ private readonly byte[] ki;
+ private readonly bool useCounter;
+ private readonly int r;
+ private readonly byte[] fixedInputData;
+
+ private KDFDoublePipelineIterationParameters(byte[] ki, byte[] fixedInputData, int r, bool useCounter)
+ {
+ if (ki == null)
+ {
+ throw new ArgumentException("A KDF requires Ki (a seed) as input");
+ }
+
+ this.ki = Arrays.Clone(ki);
+
+ if (fixedInputData == null)
+ {
+ this.fixedInputData = new byte[0];
+ }
+ else
+ {
+ this.fixedInputData = Arrays.Clone(fixedInputData);
+ }
+
+ if (r != 8 && r != 16 && r != 24 && r != 32)
+ {
+ throw new ArgumentException("Length of counter should be 8, 16, 24 or 32");
+ }
+
+ this.r = r;
+
+ this.useCounter = useCounter;
+ }
+
+ public static KDFDoublePipelineIterationParameters CreateWithCounter(
+ byte[] ki, byte[] fixedInputData, int r)
+ {
+ return new KDFDoublePipelineIterationParameters(ki, fixedInputData, r, true);
+ }
+
+ public static KDFDoublePipelineIterationParameters CreateWithoutCounter(
+ byte[] ki, byte[] fixedInputData)
+ {
+ return new KDFDoublePipelineIterationParameters(ki, fixedInputData, UNUSED_R, false);
+ }
+
+ public byte[] Ki
+ {
+ get { return Arrays.Clone(ki); }
+ }
+
+ public bool UseCounter
+ {
+ get { return useCounter; }
+ }
+
+ public int R
+ {
+ get { return r; }
+ }
+
+ public byte[] FixedInputData
+ {
+ get { return Arrays.Clone(fixedInputData); }
+ }
+ }
+}
\ No newline at end of file
diff --git a/crypto/src/crypto/parameters/KDFFeedbackParameters.cs b/crypto/src/crypto/parameters/KDFFeedbackParameters.cs
new file mode 100644
index 000000000..87187dbdb
--- /dev/null
+++ b/crypto/src/crypto/parameters/KDFFeedbackParameters.cs
@@ -0,0 +1,91 @@
+using System;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+ public class KDFFeedbackParameters : IDerivationParameters
+ {
+ // could be any valid value, using 32, don't know why
+ private static readonly int UNUSED_R = -1;
+
+ private readonly byte[] ki;
+ private readonly byte[] iv;
+ private readonly bool useCounter;
+ private readonly int r;
+ private readonly byte[] fixedInputData;
+
+ private KDFFeedbackParameters(byte[] ki, byte[] iv, byte[] fixedInputData, int r, bool useCounter)
+ {
+ if (ki == null)
+ {
+ throw new ArgumentException("A KDF requires Ki (a seed) as input");
+ }
+
+ this.ki = Arrays.Clone(ki);
+
+ if (fixedInputData == null)
+ {
+ this.fixedInputData = new byte[0];
+ }
+ else
+ {
+ this.fixedInputData = Arrays.Clone(fixedInputData);
+ }
+
+ this.r = r;
+
+ if (iv == null)
+ {
+ this.iv = new byte[0];
+ }
+ else
+ {
+ this.iv = Arrays.Clone(iv);
+ }
+
+ this.useCounter = useCounter;
+ }
+
+ public static KDFFeedbackParameters CreateWithCounter(
+ byte[] ki, byte[] iv, byte[] fixedInputData, int r)
+ {
+ if (r != 8 && r != 16 && r != 24 && r != 32)
+ {
+ throw new ArgumentException("Length of counter should be 8, 16, 24 or 32");
+ }
+
+ return new KDFFeedbackParameters(ki, iv, fixedInputData, r, true);
+ }
+
+ public static KDFFeedbackParameters CreateWithoutCounter(
+ byte[] ki, byte[] iv, byte[] fixedInputData)
+ {
+ return new KDFFeedbackParameters(ki, iv, fixedInputData, UNUSED_R, false);
+ }
+
+ public byte[] Ki
+ {
+ get { return Arrays.Clone(ki); }
+ }
+
+ public byte[] Iv
+ {
+ get { return Arrays.Clone(iv); }
+ }
+
+ public bool UseCounter
+ {
+ get { return useCounter; }
+ }
+
+ public int R
+ {
+ get { return r; }
+ }
+
+ public byte[] FixedInputData
+ {
+ get { return Arrays.Clone(fixedInputData); }
+ }
+ }
+}
\ No newline at end of file
|