diff --git a/crypto/src/crypto/generators/BaseKdfBytesGenerator.cs b/crypto/src/crypto/generators/BaseKdfBytesGenerator.cs
index bca420711..c0c4be217 100644
--- a/crypto/src/crypto/generators/BaseKdfBytesGenerator.cs
+++ b/crypto/src/crypto/generators/BaseKdfBytesGenerator.cs
@@ -11,7 +11,7 @@ namespace Org.BouncyCastle.Crypto.Generators
* <br/>
* This implementation is based on ISO 18033/P1363a.
*/
- public class BaseKdfBytesGenerator
+ public abstract class BaseKdfBytesGenerator
: IDerivationFunction
{
private int counterStart;
@@ -25,26 +25,22 @@ namespace Org.BouncyCastle.Crypto.Generators
* @param counterStart value of counter.
* @param digest the digest to be used as the source of derived keys.
*/
- public BaseKdfBytesGenerator(int counterStart, IDigest digest)
+ protected BaseKdfBytesGenerator(int counterStart, IDigest digest)
{
this.counterStart = counterStart;
this.digest = digest;
}
- public virtual void Init(IDerivationParameters parameters)
+ public void Init(IDerivationParameters parameters)
{
- if (parameters is KdfParameters)
+ if (parameters is KdfParameters kdfParameters)
{
- KdfParameters p = (KdfParameters)parameters;
-
- shared = p.GetSharedSecret();
- iv = p.GetIV();
+ shared = kdfParameters.GetSharedSecret();
+ iv = kdfParameters.GetIV();
}
- else if (parameters is Iso18033KdfParameters)
+ else if (parameters is Iso18033KdfParameters iso18033KdfParameters)
{
- Iso18033KdfParameters p = (Iso18033KdfParameters)parameters;
-
- shared = p.GetSeed();
+ shared = iso18033KdfParameters.GetSeed();
iv = null;
}
else
@@ -56,10 +52,7 @@ namespace Org.BouncyCastle.Crypto.Generators
/**
* return the underlying digest.
*/
- public virtual IDigest Digest
- {
- get { return digest; }
- }
+ public IDigest Digest => digest;
/**
* fill len bytes of the output buffer with bytes generated from
@@ -68,13 +61,15 @@ namespace Org.BouncyCastle.Crypto.Generators
* @throws ArgumentException if the size of the request will cause an overflow.
* @throws DataLengthException if the out buffer is too small.
*/
- public virtual int GenerateBytes(byte[] output, int outOff, int length)
+ public int GenerateBytes(byte[] output, int outOff, int length)
{
- if ((output.Length - length) < outOff)
- throw new DataLengthException("output buffer too small");
+ Check.OutputLength(output, outOff, length, "output buffer too small");
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ return GenerateBytes(output.AsSpan(outOff, length));
+#else
long oBytes = length;
- int outLen = digest.GetDigestSize();
+ int digestSize = digest.GetDigestSize();
//
// this is at odds with the standard implementation, the
@@ -85,9 +80,9 @@ namespace Org.BouncyCastle.Crypto.Generators
if (oBytes > ((2L << 32) - 1))
throw new ArgumentException("Output length too large");
- int cThreshold = (int)((oBytes + outLen - 1) / outLen);
+ int cThreshold = (int)((oBytes + digestSize - 1) / digestSize);
- byte[] dig = new byte[digest.GetDigestSize()];
+ byte[] dig = new byte[digestSize];
byte[] C = new byte[4];
Pack.UInt32_To_BE((uint)counterStart, C, 0);
@@ -106,11 +101,11 @@ namespace Org.BouncyCastle.Crypto.Generators
digest.DoFinal(dig, 0);
- if (length > outLen)
+ if (length > digestSize)
{
- Array.Copy(dig, 0, output, outOff, outLen);
- outOff += outLen;
- length -= outLen;
+ Array.Copy(dig, 0, output, outOff, digestSize);
+ outOff += digestSize;
+ length -= digestSize;
}
else
{
@@ -127,6 +122,67 @@ namespace Org.BouncyCastle.Crypto.Generators
digest.Reset();
return (int)oBytes;
+#endif
+ }
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public int GenerateBytes(Span<byte> output)
+ {
+ long oBytes = output.Length;
+ int digestSize = digest.GetDigestSize();
+
+ //
+ // this is at odds with the standard implementation, the
+ // maximum value should be hBits * (2^32 - 1) where hBits
+ // is the digest output size in bits. We can't have an
+ // array with a long index at the moment...
+ //
+ if (oBytes > ((2L << 32) - 1))
+ throw new ArgumentException("Output length too large");
+
+ int cThreshold = (int)((oBytes + digestSize - 1) / digestSize);
+
+ Span<byte> dig = stackalloc byte[digestSize];
+
+ Span<byte> C = stackalloc byte[4];
+ Pack.UInt32_To_BE((uint)counterStart, C);
+
+ uint counterBase = (uint)(counterStart & ~0xFF);
+
+ for (int i = 0; i < cThreshold; i++)
+ {
+ digest.BlockUpdate(shared);
+ digest.BlockUpdate(C);
+
+ if (iv != null)
+ {
+ digest.BlockUpdate(iv);
+ }
+
+ digest.DoFinal(dig);
+
+ int remaining = output.Length;
+ if (remaining > digestSize)
+ {
+ dig.CopyTo(output);
+ output = output[digestSize..];
+ }
+ else
+ {
+ dig[..remaining].CopyTo(output);
+ }
+
+ if (++C[3] == 0)
+ {
+ counterBase += 0x100;
+ Pack.UInt32_To_BE(counterBase, C);
+ }
+ }
+
+ digest.Reset();
+
+ return (int)oBytes;
}
+#endif
}
-}
\ No newline at end of file
+}
diff --git a/crypto/src/crypto/generators/HKdfBytesGenerator.cs b/crypto/src/crypto/generators/HKdfBytesGenerator.cs
index 6f36a6faa..e5c122049 100644
--- a/crypto/src/crypto/generators/HKdfBytesGenerator.cs
+++ b/crypto/src/crypto/generators/HKdfBytesGenerator.cs
@@ -13,7 +13,7 @@ namespace Org.BouncyCastle.Crypto.Generators
* (output keying material) and is likely to have better security properties
* than KDF's based on just a hash function.
*/
- public class HkdfBytesGenerator
+ public sealed class HkdfBytesGenerator
: IDerivationFunction
{
private HMac hMacHash;
@@ -35,12 +35,11 @@ namespace Org.BouncyCastle.Crypto.Generators
this.hashLen = hash.GetDigestSize();
}
- public virtual void Init(IDerivationParameters parameters)
+ public void Init(IDerivationParameters parameters)
{
- if (!(parameters is HkdfParameters))
+ if (!(parameters is HkdfParameters hkdfParameters))
throw new ArgumentException("HKDF parameters required for HkdfBytesGenerator", "parameters");
- HkdfParameters hkdfParameters = (HkdfParameters)parameters;
if (hkdfParameters.SkipExtract)
{
// use IKM directly as PRK
@@ -108,45 +107,70 @@ namespace Org.BouncyCastle.Crypto.Generators
hMacHash.DoFinal(currentT, 0);
}
- public virtual IDigest Digest
- {
- get { return hMacHash.GetUnderlyingDigest(); }
- }
+ public IDigest Digest => hMacHash.GetUnderlyingDigest();
- public virtual int GenerateBytes(byte[] output, int outOff, int len)
+ public int GenerateBytes(byte[] output, int outOff, int length)
{
- if (generatedBytes + len > 255 * hashLen)
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ return GenerateBytes(output.AsSpan(outOff, length));
+#else
+ if (generatedBytes > 255 * hashLen - length)
+ throw new DataLengthException("HKDF may only be used for 255 * HashLen bytes of output");
+
+ int toGenerate = length;
+ int posInT = generatedBytes % hashLen;
+ if (posInT != 0)
{
- throw new DataLengthException(
- "HKDF may only be used for 255 * HashLen bytes of output");
+ // copy what is left in the currentT (1..hash
+ int toCopy = System.Math.Min(hashLen - posInT, toGenerate);
+ Array.Copy(currentT, posInT, output, outOff, toCopy);
+ generatedBytes += toCopy;
+ toGenerate -= toCopy;
+ outOff += toCopy;
}
- if (generatedBytes % hashLen == 0)
+ while (toGenerate > 0)
{
ExpandNext();
+ int toCopy = System.Math.Min(hashLen, toGenerate);
+ Array.Copy(currentT, 0, output, outOff, toCopy);
+ generatedBytes += toCopy;
+ toGenerate -= toCopy;
+ outOff += toCopy;
}
- // copy what is left in the currentT (1..hash
- int toGenerate = len;
+ return length;
+#endif
+ }
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public int GenerateBytes(Span<byte> outputX)
+ {
+ int length = outputX.Length;
+ if (generatedBytes > 255 * hashLen - length)
+ throw new DataLengthException("HKDF may only be used for 255 * HashLen bytes of output");
+
int posInT = generatedBytes % hashLen;
- int leftInT = hashLen - generatedBytes % hashLen;
- int toCopy = System.Math.Min(leftInT, toGenerate);
- Array.Copy(currentT, posInT, output, outOff, toCopy);
- generatedBytes += toCopy;
- toGenerate -= toCopy;
- outOff += toCopy;
+ if (posInT != 0)
+ {
+ // copy what is left in the currentT (1..hash
+ int toCopy = System.Math.Min(hashLen - posInT, outputX.Length);
+ currentT.AsSpan(posInT, toCopy).CopyTo(outputX);
+ generatedBytes += toCopy;
+ outputX = outputX[toCopy..];
+ }
- while (toGenerate > 0)
+ while (!outputX.IsEmpty)
{
ExpandNext();
- toCopy = System.Math.Min(hashLen, toGenerate);
- Array.Copy(currentT, 0, output, outOff, toCopy);
+ int toCopy = System.Math.Min(hashLen, outputX.Length);
+ currentT.AsSpan(0, toCopy).CopyTo(outputX);
generatedBytes += toCopy;
- toGenerate -= toCopy;
- outOff += toCopy;
+ outputX = outputX[toCopy..];
}
- return len;
+ return length;
}
+#endif
}
}
diff --git a/crypto/src/crypto/generators/KDFCounterBytesGenerator.cs b/crypto/src/crypto/generators/KDFCounterBytesGenerator.cs
index 0d7647289..7fa50e2fa 100644
--- a/crypto/src/crypto/generators/KDFCounterBytesGenerator.cs
+++ b/crypto/src/crypto/generators/KDFCounterBytesGenerator.cs
@@ -3,17 +3,12 @@
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
+ public sealed 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;
@@ -37,13 +32,8 @@ namespace Org.BouncyCastle.Crypto.Generators
public void Init(IDerivationParameters param)
{
- KdfCounterParameters kdfParams = param as KdfCounterParameters;
- if (kdfParams == null)
- {
+ if (!(param is KdfCounterParameters kdfParams))
throw new ArgumentException("Wrong type of arguments given");
- }
-
-
// --- init mac based PRF ---
@@ -57,54 +47,45 @@ namespace Org.BouncyCastle.Crypto.Generators
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 ?
- int.MaxValue : maxSize.IntValue;
+ BigInteger maxSize = BigInteger.One.ShiftLeft(r).Multiply(BigInteger.ValueOf(h));
+ this.maxSizeExcl = maxSize.BitLength > 31 ? int.MaxValue : maxSize.IntValueExact;
// --- set operational state ---
generatedBytes = 0;
}
-
- public IMac GetMac()
- {
- return prf;
- }
+ public IMac Mac => prf;
public IDigest Digest
{
- get { return prf is HMac ? ((HMac)prf).GetUnderlyingDigest() : null; }
+ get { return (prf as 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();
- }
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ return GenerateBytes(output.AsSpan(outOff, length));
+#else
+ if (generatedBytes >= maxSizeExcl - length)
+ throw new DataLengthException("Current KDFCTR may only be used for " + maxSizeExcl + " bytes");
- // 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;
+ if (posInK != 0)
+ {
+ // copy what is left in the currentT (1..hash
+ int toCopy = System.Math.Min(h - posInK, toGenerate);
+ Array.Copy(k, posInK, output, outOff, toCopy);
+ generatedBytes += toCopy;
+ toGenerate -= toCopy;
+ outOff += toCopy;
+ }
while (toGenerate > 0)
{
- generateNext();
- toCopy = System.Math.Min(h, toGenerate);
+ GenerateNext();
+ int toCopy = System.Math.Min(h, toGenerate);
Array.Copy(k, 0, output, outOff, toCopy);
generatedBytes += toCopy;
toGenerate -= toCopy;
@@ -112,38 +93,65 @@ namespace Org.BouncyCastle.Crypto.Generators
}
return length;
-
+#endif
}
- private void generateNext()
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public int GenerateBytes(Span<byte> output)
{
+ int length = output.Length;
+ if (generatedBytes >= maxSizeExcl - length)
+ throw new DataLengthException("Current KDFCTR may only be used for " + maxSizeExcl + " bytes");
+
+ int posInK = generatedBytes % h;
+ if (posInK != 0)
+ {
+ // copy what is left in the currentT (1..hash
+ int toCopy = System.Math.Min(h - posInK, output.Length);
+ k.AsSpan(posInK, toCopy).CopyTo(output);
+ generatedBytes += toCopy;
+ output = output[toCopy..];
+ }
+ while (!output.IsEmpty)
+ {
+ GenerateNext();
+ int toCopy = System.Math.Min(h, output.Length);
+ k.AsSpan(0, toCopy).CopyTo(output);
+ generatedBytes += toCopy;
+ output = output[toCopy..];
+ }
+
+ return length;
+ }
+#endif
+
+ 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;
+ case 4:
+ ios[0] = (byte)(i >> 24);
// 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");
+ 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");
}
-
-
// special case for K(0): K(0) is empty, so no update
prf.BlockUpdate(fixedInputDataCtrPrefix, 0, fixedInputDataCtrPrefix.Length);
prf.BlockUpdate(ios, 0, ios.Length);
@@ -151,4 +159,4 @@ namespace Org.BouncyCastle.Crypto.Generators
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
index 63c0787f3..01feda6f4 100644
--- a/crypto/src/crypto/generators/KDFDoublePipelineIterationBytesGenerator.cs
+++ b/crypto/src/crypto/generators/KDFDoublePipelineIterationBytesGenerator.cs
@@ -6,11 +6,9 @@ using Org.BouncyCastle.Math;
namespace Org.BouncyCastle.Crypto.Generators
{
- public class KdfDoublePipelineIterationBytesGenerator : IMacDerivationFunction
+ public sealed 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;
@@ -28,7 +26,6 @@ namespace Org.BouncyCastle.Crypto.Generators
private byte[] a;
private byte[] k;
-
public KdfDoublePipelineIterationBytesGenerator(IMac prf)
{
this.prf = prf;
@@ -37,16 +34,10 @@ namespace Org.BouncyCastle.Crypto.Generators
this.k = new byte[h];
}
-
public void Init(IDerivationParameters parameters)
{
- KdfDoublePipelineIterationParameters dpiParams = parameters as KdfDoublePipelineIterationParameters;
- if (dpiParams == null)
- {
+ if (!(parameters is KdfDoublePipelineIterationParameters dpiParams))
throw new ArgumentException("Wrong type of arguments given");
- }
-
-
// --- init mac based PRF ---
@@ -62,13 +53,12 @@ namespace Org.BouncyCastle.Crypto.Generators
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 ?
- int.MaxValue : maxSize.IntValue;
+ BigInteger maxSize = BigInteger.One.ShiftLeft(r).Multiply(BigInteger.ValueOf(h));
+ this.maxSizeExcl = maxSize.BitLength > 31 ? int.MaxValue : maxSize.IntValueExact;
}
else
{
- this.maxSizeExcl = IntegerMax.IntValue;
+ this.maxSizeExcl = int.MaxValue;
}
this.useCounter = dpiParams.UseCounter;
@@ -78,12 +68,8 @@ namespace Org.BouncyCastle.Crypto.Generators
generatedBytes = 0;
}
-
-
-
- private void generateNext()
+ private void GenerateNext()
{
-
if (generatedBytes == 0)
{
// --- step 4 ---
@@ -107,23 +93,23 @@ namespace Org.BouncyCastle.Crypto.Generators
// 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");
+ 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);
}
@@ -134,37 +120,33 @@ namespace Org.BouncyCastle.Crypto.Generators
public IDigest Digest
{
- get { return prf is HMac ? ((HMac)prf).GetUnderlyingDigest() : null; }
+ get { return (prf as 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 NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ return GenerateBytes(output.AsSpan(outOff, length));
+#else
+ if (generatedBytes >= maxSizeExcl - length)
+ 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;
+ if (posInK != 0)
+ {
+ // copy what is left in the currentT (1..hash
+ int toCopy = System.Math.Min(h - posInK, toGenerate);
+ Array.Copy(k, posInK, output, outOff, toCopy);
+ generatedBytes += toCopy;
+ toGenerate -= toCopy;
+ outOff += toCopy;
+ }
while (toGenerate > 0)
{
- generateNext();
- toCopy = System.Math.Min(h, toGenerate);
+ GenerateNext();
+ int toCopy = System.Math.Min(h, toGenerate);
Array.Copy(k, 0, output, outOff, toCopy);
generatedBytes += toCopy;
toGenerate -= toCopy;
@@ -172,11 +154,40 @@ namespace Org.BouncyCastle.Crypto.Generators
}
return length;
+#endif
}
- public IMac GetMac()
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public int GenerateBytes(Span<byte> output)
{
- return prf;
+ int length = output.Length;
+ if (generatedBytes >= maxSizeExcl - length)
+ throw new DataLengthException("Current KDFCTR may only be used for " + maxSizeExcl + " bytes");
+
+ int posInK = generatedBytes % h;
+ if (posInK != 0)
+ {
+ // copy what is left in the currentT (1..hash
+ GenerateNext();
+ int toCopy = System.Math.Min(h - posInK, output.Length);
+ k.AsSpan(posInK, toCopy).CopyTo(output);
+ generatedBytes += toCopy;
+ output = output[toCopy..];
+ }
+
+ while (!output.IsEmpty)
+ {
+ GenerateNext();
+ int toCopy = System.Math.Min(h, output.Length);
+ k.AsSpan(0, toCopy).CopyTo(output);
+ generatedBytes += toCopy;
+ output = output[toCopy..];
+ }
+
+ return length;
}
+#endif
+
+ public IMac Mac => prf;
}
-}
\ No newline at end of file
+}
diff --git a/crypto/src/crypto/generators/KDFFeedbackBytesGenerator.cs b/crypto/src/crypto/generators/KDFFeedbackBytesGenerator.cs
index 11a5552fe..58a035ef6 100644
--- a/crypto/src/crypto/generators/KDFFeedbackBytesGenerator.cs
+++ b/crypto/src/crypto/generators/KDFFeedbackBytesGenerator.cs
@@ -6,11 +6,9 @@ using Org.BouncyCastle.Math;
namespace Org.BouncyCastle.Crypto.Generators
{
- public class KdfFeedbackBytesGenerator : IMacDerivationFunction
+ public sealed 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
@@ -38,15 +36,10 @@ namespace Org.BouncyCastle.Crypto.Generators
this.k = new byte[h];
}
-
public void Init(IDerivationParameters parameters)
{
- KdfFeedbackParameters feedbackParams = parameters as KdfFeedbackParameters;
- if (feedbackParams == null)
- {
+ if (!(parameters is KdfFeedbackParameters feedbackParams))
throw new ArgumentException("Wrong type of arguments given");
- }
-
// --- init mac based PRF ---
@@ -62,9 +55,8 @@ namespace Org.BouncyCastle.Crypto.Generators
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 ?
- int.MaxValue : maxSize.IntValue;
+ BigInteger maxSize = BigInteger.One.ShiftLeft(r).Multiply(BigInteger.ValueOf(h));
+ this.maxSizeExcl = maxSize.BitLength > 31 ? int.MaxValue : maxSize.IntValueExact;
}
else
{
@@ -81,40 +73,33 @@ namespace Org.BouncyCastle.Crypto.Generators
public IDigest Digest
{
- get { return prf is HMac ? ((HMac)prf).GetUnderlyingDigest() : null; }
+ get { return (prf as 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();
- }
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ return GenerateBytes(output.AsSpan(outOff, length));
+#else
+ if (generatedBytes >= maxSizeExcl - length)
+ throw new DataLengthException("Current KDFCTR may only be used for " + maxSizeExcl + " bytes");
- // 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;
+ if (posInK != 0)
+ {
+ // copy what is left in the currentT (1..hash
+ int toCopy = System.Math.Min(h - posInK, toGenerate);
+ Array.Copy(k, posInK, output, outOff, toCopy);
+ generatedBytes += toCopy;
+ toGenerate -= toCopy;
+ outOff += toCopy;
+ }
while (toGenerate > 0)
{
- generateNext();
- toCopy = System.Math.Min(h, toGenerate);
+ GenerateNext();
+ int toCopy = System.Math.Min(h, toGenerate);
Array.Copy(k, 0, output, outOff, toCopy);
generatedBytes += toCopy;
toGenerate -= toCopy;
@@ -122,11 +107,41 @@ namespace Org.BouncyCastle.Crypto.Generators
}
return length;
+#endif
}
- private void generateNext()
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public int GenerateBytes(Span<byte> output)
{
+ int length = output.Length;
+ if (generatedBytes >= maxSizeExcl - length)
+ throw new DataLengthException("Current KDFCTR may only be used for " + maxSizeExcl + " bytes");
+ int posInK = generatedBytes % h;
+ if (posInK != 0)
+ {
+ // copy what is left in the currentT (1..hash
+ int toCopy = System.Math.Min(h - posInK, output.Length);
+ k.AsSpan(posInK, toCopy).CopyTo(output);
+ generatedBytes += toCopy;
+ output = output[toCopy..];
+ }
+
+ while (!output.IsEmpty)
+ {
+ GenerateNext();
+ int toCopy = System.Math.Min(h, output.Length);
+ k.AsSpan(0, toCopy).CopyTo(output);
+ generatedBytes += toCopy;
+ output = output[toCopy..];
+ }
+
+ return length;
+ }
+#endif
+
+ private void GenerateNext()
+ {
// TODO enable IV
if (generatedBytes == 0)
{
@@ -144,23 +159,23 @@ namespace Org.BouncyCastle.Crypto.Generators
// encode i into counter buffer
switch (ios.Length)
{
- case 4:
- ios[0] = (byte)(i >> 24);
- goto case 3;
+ case 4:
+ ios[0] = (byte)(i >> 24);
// 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");
+ 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);
}
@@ -169,9 +184,6 @@ namespace Org.BouncyCastle.Crypto.Generators
prf.DoFinal(k, 0);
}
- public IMac GetMac()
- {
- return prf;
- }
+ public IMac Mac => prf;
}
-}
\ No newline at end of file
+}
diff --git a/crypto/src/crypto/generators/Kdf1BytesGenerator.cs b/crypto/src/crypto/generators/Kdf1BytesGenerator.cs
index 0ddf6c166..a43fa06d1 100644
--- a/crypto/src/crypto/generators/Kdf1BytesGenerator.cs
+++ b/crypto/src/crypto/generators/Kdf1BytesGenerator.cs
@@ -1,16 +1,11 @@
-using System;
-
-using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Crypto.Parameters;
-
namespace Org.BouncyCastle.Crypto.Generators
{
/**
- * KFD2 generator for derived keys and ivs as defined by IEEE P1363a/ISO 18033
+ * KFD1 generator for derived keys and ivs as defined by IEEE P1363a/ISO 18033
* <br/>
* This implementation is based on IEEE P1363/ISO 18033.
*/
- public class Kdf1BytesGenerator
+ public sealed class Kdf1BytesGenerator
: BaseKdfBytesGenerator
{
/**
diff --git a/crypto/src/crypto/generators/Kdf2BytesGenerator.cs b/crypto/src/crypto/generators/Kdf2BytesGenerator.cs
index 8a6821980..2dc1d4301 100644
--- a/crypto/src/crypto/generators/Kdf2BytesGenerator.cs
+++ b/crypto/src/crypto/generators/Kdf2BytesGenerator.cs
@@ -1,8 +1,3 @@
-using System;
-
-using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Crypto.Parameters;
-
namespace Org.BouncyCastle.Crypto.Generators
{
/**
@@ -10,7 +5,7 @@ namespace Org.BouncyCastle.Crypto.Generators
* <br/>
* This implementation is based on IEEE P1363/ISO 18033.
*/
- public class Kdf2BytesGenerator
+ public sealed class Kdf2BytesGenerator
: BaseKdfBytesGenerator
{
/**
diff --git a/crypto/src/crypto/generators/Mgf1BytesGenerator.cs b/crypto/src/crypto/generators/Mgf1BytesGenerator.cs
index 23a3aca25..7b4bb3c0b 100644
--- a/crypto/src/crypto/generators/Mgf1BytesGenerator.cs
+++ b/crypto/src/crypto/generators/Mgf1BytesGenerator.cs
@@ -1,117 +1,112 @@
using System;
-//using Org.BouncyCastle.Math;
-//using Org.BouncyCastle.Security;
-using Org.BouncyCastle.Crypto;
+
using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
namespace Org.BouncyCastle.Crypto.Generators
{
- /**
- * Generator for MGF1 as defined in Pkcs 1v2
- */
- public class Mgf1BytesGenerator : IDerivationFunction
+ /// <summary>Generator for MGF1 as defined in Pkcs 1v2</summary>
+ public sealed class Mgf1BytesGenerator
+ : IDerivationFunction
{
- private IDigest digest;
- private byte[] seed;
- private int hLen;
-
- /**
- * @param digest the digest to be used as the source of Generated bytes
- */
- public Mgf1BytesGenerator(
- IDigest digest)
+ private readonly IDigest m_digest;
+ private readonly int m_hLen;
+
+ private byte[] m_buffer;
+
+ /// <param name="digest">the digest to be used as the source of generated bytes</param>
+ public Mgf1BytesGenerator(IDigest digest)
{
- this.digest = digest;
- this.hLen = digest.GetDigestSize();
+ m_digest = digest;
+ m_hLen = digest.GetDigestSize();
}
- public void Init(
- IDerivationParameters parameters)
+ public void Init(IDerivationParameters parameters)
{
- if (!(typeof(MgfParameters).IsInstanceOfType(parameters)))
- {
+ if (!(parameters is MgfParameters mgfParameters))
throw new ArgumentException("MGF parameters required for MGF1Generator");
- }
-
- MgfParameters p = (MgfParameters)parameters;
- seed = p.GetSeed();
+ m_buffer = new byte[mgfParameters.SeedLength + 4 + m_hLen];
+ mgfParameters.GetSeed(m_buffer, 0);
}
- /**
- * return the underlying digest.
- */
- public IDigest Digest
+ /// <summary>the underlying digest.</summary>
+ public IDigest Digest => m_digest;
+
+ /// <summary>Fill <c>len</c> bytes of the output buffer with bytes generated from the derivation function.
+ /// </summary>
+ public int GenerateBytes(byte[] output, int outOff, int length)
{
- get
+ Check.OutputLength(output, outOff, length, "output buffer too small");
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ return GenerateBytes(output.AsSpan(outOff, length));
+#else
+ int hashPos = m_buffer.Length - m_hLen;
+ int counterPos = hashPos - 4;
+ uint counter = 0;
+
+ m_digest.Reset();
+
+ int end = outOff + length;
+ int limit = end - m_hLen;
+
+ while (outOff <= limit)
{
- return digest;
+ Pack.UInt32_To_BE(counter++, m_buffer, counterPos);
+
+ m_digest.BlockUpdate(m_buffer, 0, hashPos);
+ m_digest.DoFinal(output, outOff);
+
+ outOff += m_hLen;
}
- }
- /**
- * int to octet string.
- */
- private void ItoOSP(
- int i,
- byte[] sp)
- {
- sp[0] = (byte)((uint) i >> 24);
- sp[1] = (byte)((uint) i >> 16);
- sp[2] = (byte)((uint) i >> 8);
- sp[3] = (byte)((uint) i >> 0);
+ if (outOff < end)
+ {
+ Pack.UInt32_To_BE(counter, m_buffer, counterPos);
+
+ m_digest.BlockUpdate(m_buffer, 0, hashPos);
+ m_digest.DoFinal(m_buffer, hashPos);
+
+ Array.Copy(m_buffer, hashPos, output, outOff, end - outOff);
+ }
+
+ return length;
+#endif
}
- /**
- * fill len bytes of the output buffer with bytes Generated from
- * the derivation function.
- *
- * @throws DataLengthException if the out buffer is too small.
- */
- public int GenerateBytes(
- byte[] output,
- int outOff,
- int length)
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public int GenerateBytes(Span<byte> output)
{
- if ((output.Length - length) < outOff)
- {
- throw new DataLengthException("output buffer too small");
- }
+ int hashPos = m_buffer.Length - m_hLen;
+ int counterPos = hashPos - 4;
+ uint counter = 0;
- byte[] hashBuf = new byte[hLen];
- byte[] C = new byte[4];
- int counter = 0;
+ m_digest.Reset();
- digest.Reset();
+ int pos = 0, length = output.Length, limit = length - m_hLen;
- if (length > hLen)
- {
- do
- {
- ItoOSP(counter, C);
+ while (pos <= limit)
+ {
+ Pack.UInt32_To_BE(counter++, m_buffer.AsSpan(counterPos));
- digest.BlockUpdate(seed, 0, seed.Length);
- digest.BlockUpdate(C, 0, C.Length);
- digest.DoFinal(hashBuf, 0);
+ m_digest.BlockUpdate(m_buffer.AsSpan(0, hashPos));
+ m_digest.DoFinal(output[pos..]);
- Array.Copy(hashBuf, 0, output, outOff + counter * hLen, hLen);
- }
- while (++counter < (length / hLen));
- }
+ pos += m_hLen;
+ }
- if ((counter * hLen) < length)
+ if (pos < length)
{
- ItoOSP(counter, C);
-
- digest.BlockUpdate(seed, 0, seed.Length);
- digest.BlockUpdate(C, 0, C.Length);
- digest.DoFinal(hashBuf, 0);
+ Pack.UInt32_To_BE(counter, m_buffer.AsSpan(counterPos));
- Array.Copy(hashBuf, 0, output, outOff + counter * hLen, length - (counter * hLen));
+ m_digest.BlockUpdate(m_buffer.AsSpan(0, hashPos));
+ m_digest.DoFinal(m_buffer.AsSpan(hashPos));
+ m_buffer.AsSpan(hashPos, length - pos).CopyTo(output[pos..]);
}
return length;
}
+#endif
}
-
}
|