diff --git a/crypto/src/crypto/IDerivationFunction.cs b/crypto/src/crypto/IDerivationFunction.cs
index 7f289f790..9c0228ab0 100644
--- a/crypto/src/crypto/IDerivationFunction.cs
+++ b/crypto/src/crypto/IDerivationFunction.cs
@@ -12,13 +12,12 @@ namespace Org.BouncyCastle.Crypto
/**
* return the message digest used as the basis for the function
*/
- IDigest Digest
- {
- get;
- }
+ IDigest Digest { get; }
int GenerateBytes(byte[] output, int outOff, int length);
- //throws DataLengthException, ArgumentException;
- }
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ int GenerateBytes(Span<byte> output);
+#endif
+ }
}
diff --git a/crypto/src/crypto/IMacDerivationFunction.cs b/crypto/src/crypto/IMacDerivationFunction.cs
index 7297cd854..354524e5a 100644
--- a/crypto/src/crypto/IMacDerivationFunction.cs
+++ b/crypto/src/crypto/IMacDerivationFunction.cs
@@ -1,7 +1,8 @@
namespace Org.BouncyCastle.Crypto
{
- public interface IMacDerivationFunction:IDerivationFunction
+ public interface IMacDerivationFunction
+ : IDerivationFunction
{
- IMac GetMac();
+ IMac Mac { get; }
}
-}
\ No newline at end of file
+}
diff --git a/crypto/src/crypto/agreement/kdf/ConcatenationKdfGenerator.cs b/crypto/src/crypto/agreement/kdf/ConcatenationKdfGenerator.cs
index d88f4dfdb..207c795da 100644
--- a/crypto/src/crypto/agreement/kdf/ConcatenationKdfGenerator.cs
+++ b/crypto/src/crypto/agreement/kdf/ConcatenationKdfGenerator.cs
@@ -5,96 +5,110 @@ using Org.BouncyCastle.Crypto.Utilities;
namespace Org.BouncyCastle.Crypto.Agreement.Kdf
{
- /**
- * Generator for Concatenation Key Derivation Function defined in NIST SP 800-56A, Sect 5.8.1
- */
- public class ConcatenationKdfGenerator
+ /// <summary>Generator for Concatenation Key Derivation Function defined in NIST SP 800-56A, Sect 5.8.1</summary>
+ public sealed class ConcatenationKdfGenerator
: IDerivationFunction
{
- private readonly IDigest mDigest;
+ private readonly IDigest m_digest;
+ private readonly int m_hLen;
- private byte[] mShared;
- private byte[] mOtherInfo;
- private int mHLen;
+ private byte[] m_buffer;
- /**
- * @param digest the digest to be used as the source of generated bytes
- */
+ /// <param name="digest">the digest to be used as the source of generated bytes</param>
public ConcatenationKdfGenerator(IDigest digest)
{
- this.mDigest = digest;
- this.mHLen = digest.GetDigestSize();
+ m_digest = digest;
+ m_hLen = digest.GetDigestSize();
}
- public virtual void Init(IDerivationParameters param)
+ public void Init(IDerivationParameters param)
{
- if (!(param is KdfParameters))
+ if (!(param is KdfParameters kdfParameters))
throw new ArgumentException("KDF parameters required for ConcatenationKdfGenerator");
- KdfParameters p = (KdfParameters)param;
+ byte[] sharedSecret = kdfParameters.GetSharedSecret();
+ byte[] otherInfo = kdfParameters.GetIV();
- mShared = p.GetSharedSecret();
- mOtherInfo = p.GetIV();
+ m_buffer = new byte[4 + sharedSecret.Length + otherInfo.Length + m_hLen];
+ sharedSecret.CopyTo(m_buffer, 4);
+ otherInfo.CopyTo(m_buffer, 4 + sharedSecret.Length);
}
- /**
- * return the underlying digest.
- */
- public virtual IDigest Digest
- {
- get { return mDigest; }
- }
+ /// <summary>the underlying digest.</summary>
+ public IDigest Digest => m_digest;
- /**
- * fill len bytes of the output buffer with bytes generated from
- * the derivation function.
- *
- * @throws DataLengthException if the out buffer is too small.
- */
- public virtual int GenerateBytes(byte[] outBytes, int outOff, int len)
+ /// <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)
{
- if ((outBytes.Length - len) < outOff)
- throw new DataLengthException("output buffer too small");
+ Check.OutputLength(output, outOff, length, "output buffer too small");
- byte[] hashBuf = new byte[mHLen];
- byte[] C = new byte[4];
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ return GenerateBytes(output.AsSpan(outOff, length));
+#else
+ int hashPos = m_buffer.Length - m_hLen;
uint counter = 1;
- int outputLen = 0;
- mDigest.Reset();
+ m_digest.Reset();
+
+ int end = outOff + length;
+ int limit = end - m_hLen;
- if (len > mHLen)
+ while (outOff <= limit)
{
- do
- {
- Pack.UInt32_To_BE(counter, C);
+ Pack.UInt32_To_BE(counter++, m_buffer, 0);
- mDigest.BlockUpdate(C, 0, C.Length);
- mDigest.BlockUpdate(mShared, 0, mShared.Length);
- mDigest.BlockUpdate(mOtherInfo, 0, mOtherInfo.Length);
+ m_digest.BlockUpdate(m_buffer, 0, hashPos);
+ m_digest.DoFinal(output, outOff);
- mDigest.DoFinal(hashBuf, 0);
+ outOff += m_hLen;
+ }
- Array.Copy(hashBuf, 0, outBytes, outOff + outputLen, mHLen);
- outputLen += mHLen;
- }
- while ((counter++) < (len / mHLen));
+ if (outOff < end)
+ {
+ Pack.UInt32_To_BE(counter, m_buffer, 0);
+
+ m_digest.BlockUpdate(m_buffer, 0, hashPos);
+ m_digest.DoFinal(m_buffer, hashPos);
+
+ Array.Copy(m_buffer, hashPos, output, outOff, end - outOff);
}
- if (outputLen < len)
+ return length;
+#endif
+ }
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public int GenerateBytes(Span<byte> output)
+ {
+ int hashPos = m_buffer.Length - m_hLen;
+ uint counter = 1;
+
+ m_digest.Reset();
+
+ int pos = 0, length = output.Length, limit = length - m_hLen;
+
+ while (pos <= limit)
{
- Pack.UInt32_To_BE(counter, C);
+ Pack.UInt32_To_BE(counter++, m_buffer.AsSpan());
+
+ m_digest.BlockUpdate(m_buffer.AsSpan(0, hashPos));
+ m_digest.DoFinal(output[pos..]);
- mDigest.BlockUpdate(C, 0, C.Length);
- mDigest.BlockUpdate(mShared, 0, mShared.Length);
- mDigest.BlockUpdate(mOtherInfo, 0, mOtherInfo.Length);
+ pos += m_hLen;
+ }
- mDigest.DoFinal(hashBuf, 0);
+ if (pos < length)
+ {
+ Pack.UInt32_To_BE(counter, m_buffer.AsSpan());
- Array.Copy(hashBuf, 0, outBytes, outOff + outputLen, len - outputLen);
+ 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 len;
+ return length;
}
+#endif
}
}
diff --git a/crypto/src/crypto/agreement/kdf/DHKekGenerator.cs b/crypto/src/crypto/agreement/kdf/DHKekGenerator.cs
index 259e21e69..7d75c2224 100644
--- a/crypto/src/crypto/agreement/kdf/DHKekGenerator.cs
+++ b/crypto/src/crypto/agreement/kdf/DHKekGenerator.cs
@@ -1,17 +1,19 @@
using System;
using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Crypto.IO;
using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Security;
namespace Org.BouncyCastle.Crypto.Agreement.Kdf
{
/**
* RFC 2631 Diffie-hellman KEK derivation function.
*/
- public class DHKekGenerator
+ public sealed class DHKekGenerator
: IDerivationFunction
{
- private readonly IDigest digest;
+ private readonly IDigest m_digest;
private DerObjectIdentifier algorithm;
private int keySize;
@@ -20,10 +22,10 @@ namespace Org.BouncyCastle.Crypto.Agreement.Kdf
public DHKekGenerator(IDigest digest)
{
- this.digest = digest;
+ m_digest = digest;
}
- public virtual void Init(IDerivationParameters param)
+ public void Init(IDerivationParameters param)
{
DHKdfParameters parameters = (DHKdfParameters)param;
@@ -33,20 +35,79 @@ namespace Org.BouncyCastle.Crypto.Agreement.Kdf
this.partyAInfo = parameters.GetExtraInfo(); // TODO Clone?
}
- public virtual IDigest Digest
- {
- get { return digest; }
- }
+ public IDigest Digest => m_digest;
- public virtual int GenerateBytes(byte[] outBytes, int outOff, int len)
+ public int GenerateBytes(byte[] outBytes, int outOff, int length)
{
- if ((outBytes.Length - len) < outOff)
+ Check.OutputLength(outBytes, outOff, length, "output buffer too small");
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ return GenerateBytes(outBytes.AsSpan(outOff, length));
+#else
+ long oBytes = length;
+ int digestSize = m_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);
+
+ byte[] dig = new byte[digestSize];
+
+ uint counter = 1;
+
+ for (int i = 0; i < cThreshold; i++)
{
- throw new DataLengthException("output buffer too small");
+ // KeySpecificInfo
+ DerSequence keyInfo = new DerSequence(algorithm, new DerOctetString(Pack.UInt32_To_BE(counter)));
+
+ // OtherInfo
+ Asn1EncodableVector v1 = new Asn1EncodableVector(keyInfo);
+
+ if (partyAInfo != null)
+ {
+ v1.Add(new DerTaggedObject(true, 0, new DerOctetString(partyAInfo)));
+ }
+
+ v1.Add(new DerTaggedObject(true, 2, new DerOctetString(Pack.UInt32_To_BE((uint)keySize))));
+
+ byte[] other = new DerSequence(v1).GetDerEncoded();
+
+ m_digest.BlockUpdate(z, 0, z.Length);
+ m_digest.BlockUpdate(other, 0, other.Length);
+ m_digest.DoFinal(dig, 0);
+
+ if (length > digestSize)
+ {
+ Array.Copy(dig, 0, outBytes, outOff, digestSize);
+ outOff += digestSize;
+ length -= digestSize;
+ }
+ else
+ {
+ Array.Copy(dig, 0, outBytes, outOff, length);
+ }
+
+ counter++;
}
- long oBytes = len;
- int outLen = digest.GetDigestSize();
+ m_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 = m_digest.GetDigestSize();
//
// this is at odds with the standard implementation, the
@@ -55,24 +116,18 @@ namespace Org.BouncyCastle.Crypto.Agreement.Kdf
// array with a long index at the moment...
//
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()];
+ Span<byte> dig = stackalloc byte[digestSize];
uint counter = 1;
for (int i = 0; i < cThreshold; i++)
{
- digest.BlockUpdate(z, 0, z.Length);
-
// KeySpecificInfo
- DerSequence keyInfo = new DerSequence(
- algorithm,
- new DerOctetString(Pack.UInt32_To_BE(counter)));
+ DerSequence keyInfo = new DerSequence(algorithm, new DerOctetString(Pack.UInt32_To_BE(counter)));
// OtherInfo
Asn1EncodableVector v1 = new Asn1EncodableVector(keyInfo);
@@ -86,27 +141,28 @@ namespace Org.BouncyCastle.Crypto.Agreement.Kdf
byte[] other = new DerSequence(v1).GetDerEncoded();
- digest.BlockUpdate(other, 0, other.Length);
-
- digest.DoFinal(dig, 0);
+ m_digest.BlockUpdate(z);
+ m_digest.BlockUpdate(other);
+ m_digest.DoFinal(dig);
- if (len > outLen)
+ int remaining = output.Length;
+ if (remaining > digestSize)
{
- Array.Copy(dig, 0, outBytes, outOff, outLen);
- outOff += outLen;
- len -= outLen;
+ dig.CopyTo(output);
+ output = output[digestSize..];
}
else
{
- Array.Copy(dig, 0, outBytes, outOff, len);
+ dig[..remaining].CopyTo(output);
}
counter++;
}
- digest.Reset();
+ m_digest.Reset();
return (int)oBytes;
}
+#endif
}
}
diff --git a/crypto/src/crypto/agreement/kdf/ECDHKekGenerator.cs b/crypto/src/crypto/agreement/kdf/ECDHKekGenerator.cs
index 74464574c..dbb7ad535 100644
--- a/crypto/src/crypto/agreement/kdf/ECDHKekGenerator.cs
+++ b/crypto/src/crypto/agreement/kdf/ECDHKekGenerator.cs
@@ -11,10 +11,10 @@ namespace Org.BouncyCastle.Crypto.Agreement.Kdf
/**
* X9.63 based key derivation function for ECDH CMS.
*/
- public class ECDHKekGenerator
+ public sealed class ECDHKekGenerator
: IDerivationFunction
{
- private readonly IDerivationFunction kdf;
+ private readonly IDerivationFunction m_kdf;
private DerObjectIdentifier algorithm;
private int keySize;
@@ -22,10 +22,10 @@ namespace Org.BouncyCastle.Crypto.Agreement.Kdf
public ECDHKekGenerator(IDigest digest)
{
- this.kdf = new Kdf2BytesGenerator(digest);
+ m_kdf = new Kdf2BytesGenerator(digest);
}
- public virtual void Init(IDerivationParameters param)
+ public void Init(IDerivationParameters param)
{
DHKdfParameters parameters = (DHKdfParameters)param;
@@ -34,12 +34,29 @@ namespace Org.BouncyCastle.Crypto.Agreement.Kdf
this.z = parameters.GetZ(); // TODO Clone?
}
- public virtual IDigest Digest
+ public IDigest Digest => m_kdf.Digest;
+
+ public int GenerateBytes(byte[] outBytes, int outOff, int length)
{
- get { return kdf.Digest; }
+ Check.OutputLength(outBytes, outOff, length, "output buffer too small");
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ return GenerateBytes(outBytes.AsSpan(outOff, length));
+#else
+ // TODO Create an ASN.1 class for this (RFC3278)
+ // ECC-CMS-SharedInfo
+ DerSequence s = new DerSequence(
+ new AlgorithmIdentifier(algorithm, DerNull.Instance),
+ new DerTaggedObject(true, 2, new DerOctetString(Pack.UInt32_To_BE((uint)keySize))));
+
+ m_kdf.Init(new KdfParameters(z, s.GetDerEncoded()));
+
+ return m_kdf.GenerateBytes(outBytes, outOff, length);
+#endif
}
- public virtual int GenerateBytes(byte[] outBytes, int outOff, int len)
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public int GenerateBytes(Span<byte> output)
{
// TODO Create an ASN.1 class for this (RFC3278)
// ECC-CMS-SharedInfo
@@ -47,9 +64,10 @@ namespace Org.BouncyCastle.Crypto.Agreement.Kdf
new AlgorithmIdentifier(algorithm, DerNull.Instance),
new DerTaggedObject(true, 2, new DerOctetString(Pack.UInt32_To_BE((uint)keySize))));
- kdf.Init(new KdfParameters(z, s.GetDerEncoded()));
+ m_kdf.Init(new KdfParameters(z, s.GetDerEncoded()));
- return kdf.GenerateBytes(outBytes, outOff, len);
+ return m_kdf.GenerateBytes(output);
}
+#endif
}
}
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
}
-
}
diff --git a/crypto/src/crypto/parameters/KdfParameters.cs b/crypto/src/crypto/parameters/KdfParameters.cs
index bc5c905d0..78cf81855 100644
--- a/crypto/src/crypto/parameters/KdfParameters.cs
+++ b/crypto/src/crypto/parameters/KdfParameters.cs
@@ -6,28 +6,26 @@ namespace Org.BouncyCastle.Crypto.Parameters
/**
* parameters for Key derivation functions for IEEE P1363a
*/
- public class KdfParameters : IDerivationParameters
+ public class KdfParameters
+ : IDerivationParameters
{
- byte[] iv;
- byte[] shared;
+ private readonly byte[] m_iv;
+ private readonly byte[] m_shared;
- public KdfParameters(
- byte[] shared,
- byte[] iv)
+ public KdfParameters(byte[] shared, byte[] iv)
{
- this.shared = shared;
- this.iv = iv;
+ m_shared = shared;
+ m_iv = iv;
}
public byte[] GetSharedSecret()
{
- return shared;
+ return m_shared;
}
public byte[] GetIV()
{
- return iv;
+ return m_iv;
}
}
-
}
diff --git a/crypto/src/crypto/parameters/MgfParameters.cs b/crypto/src/crypto/parameters/MgfParameters.cs
index 11983b877..7915567e2 100644
--- a/crypto/src/crypto/parameters/MgfParameters.cs
+++ b/crypto/src/crypto/parameters/MgfParameters.cs
@@ -1,31 +1,42 @@
using System;
+using Org.BouncyCastle.Utilities;
+
namespace Org.BouncyCastle.Crypto.Parameters
{
/// <remarks>Parameters for mask derivation functions.</remarks>
- public class MgfParameters
+ public sealed class MgfParameters
: IDerivationParameters
{
- private readonly byte[] seed;
+ private readonly byte[] m_seed;
- public MgfParameters(
- byte[] seed)
+ public MgfParameters(byte[] seed)
: this(seed, 0, seed.Length)
{
}
- public MgfParameters(
- byte[] seed,
- int off,
- int len)
+ public MgfParameters(byte[] seed, int off, int len)
+ {
+ m_seed = Arrays.CopyOfRange(seed, off, len);
+ }
+
+ public byte[] GetSeed()
{
- this.seed = new byte[len];
- Array.Copy(seed, off, this.seed, 0, len);
+ return (byte[])m_seed.Clone();
}
- public byte[] GetSeed()
+ public void GetSeed(byte[] buffer, int offset)
{
- return (byte[]) seed.Clone();
+ m_seed.CopyTo(buffer, offset);
}
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public void GetSeed(Span<byte> output)
+ {
+ m_seed.CopyTo(output);
+ }
+#endif
+
+ public int SeedLength => m_seed.Length;
}
}
|