From 60c2d34deac485cb50c2350735b4efff50c88a62 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sun, 29 Jan 2023 17:35:58 +0700 Subject: Improve seed generation --- crypto/src/crypto/prng/BasicEntropySourceProvider.cs | 2 +- .../src/crypto/prng/CryptoApiEntropySourceProvider.cs | 2 +- crypto/src/crypto/prng/EntropyUtilities.cs | 17 +++++++++++++++++ crypto/src/crypto/prng/SP800SecureRandom.cs | 7 +++++++ crypto/src/crypto/prng/X931SecureRandom.cs | 7 +++++++ .../src/crypto/prng/test/TestEntropySourceProvider.cs | 2 +- crypto/test/src/util/test/FixedSecureRandom.cs | 9 +++++++++ 7 files changed, 43 insertions(+), 3 deletions(-) diff --git a/crypto/src/crypto/prng/BasicEntropySourceProvider.cs b/crypto/src/crypto/prng/BasicEntropySourceProvider.cs index 5de1e4e5e..7a3e2b2b4 100644 --- a/crypto/src/crypto/prng/BasicEntropySourceProvider.cs +++ b/crypto/src/crypto/prng/BasicEntropySourceProvider.cs @@ -71,7 +71,7 @@ namespace Org.BouncyCastle.Crypto.Prng #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER int IEntropySource.GetEntropy(Span output) { - int length = (mEntropySize + 7) / 8; + int length = System.Math.Min(output.Length, (mEntropySize + 7) / 8); mSecureRandom.NextBytes(output[..length]); return length; } diff --git a/crypto/src/crypto/prng/CryptoApiEntropySourceProvider.cs b/crypto/src/crypto/prng/CryptoApiEntropySourceProvider.cs index 9a2f6de2c..d20b5b22b 100644 --- a/crypto/src/crypto/prng/CryptoApiEntropySourceProvider.cs +++ b/crypto/src/crypto/prng/CryptoApiEntropySourceProvider.cs @@ -59,7 +59,7 @@ namespace Org.BouncyCastle.Crypto.Prng #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER int IEntropySource.GetEntropy(Span output) { - int length = (mEntropySize + 7) / 8; + int length = System.Math.Min(output.Length, (mEntropySize + 7) / 8); mRng.GetBytes(output[..length]); return length; } diff --git a/crypto/src/crypto/prng/EntropyUtilities.cs b/crypto/src/crypto/prng/EntropyUtilities.cs index 58c8703f4..156b46622 100644 --- a/crypto/src/crypto/prng/EntropyUtilities.cs +++ b/crypto/src/crypto/prng/EntropyUtilities.cs @@ -16,6 +16,10 @@ namespace Org.BouncyCastle.Crypto.Prng public static byte[] GenerateSeed(IEntropySource entropySource, int numBytes) { byte[] bytes = new byte[numBytes]; + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + GenerateSeed(entropySource, bytes); +#else int count = 0; while (count < numBytes) { @@ -24,7 +28,20 @@ namespace Org.BouncyCastle.Crypto.Prng Array.Copy(entropy, 0, bytes, count, toCopy); count += toCopy; } +#endif + return bytes; } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public static void GenerateSeed(IEntropySource entropySource, Span seed) + { + while (!seed.IsEmpty) + { + int len = entropySource.GetEntropy(seed); + seed = seed[len..]; + } + } +#endif } } diff --git a/crypto/src/crypto/prng/SP800SecureRandom.cs b/crypto/src/crypto/prng/SP800SecureRandom.cs index a18576d03..4fbbc927f 100644 --- a/crypto/src/crypto/prng/SP800SecureRandom.cs +++ b/crypto/src/crypto/prng/SP800SecureRandom.cs @@ -113,6 +113,13 @@ namespace Org.BouncyCastle.Crypto.Prng return EntropyUtilities.GenerateSeed(mEntropySource, numBytes); } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public override void GenerateSeed(Span seed) + { + EntropyUtilities.GenerateSeed(mEntropySource, seed); + } +#endif + /// Force a reseed of the DRBG. /// optional additional input public virtual void Reseed(byte[] additionalInput) diff --git a/crypto/src/crypto/prng/X931SecureRandom.cs b/crypto/src/crypto/prng/X931SecureRandom.cs index d40134851..6c0114cb2 100644 --- a/crypto/src/crypto/prng/X931SecureRandom.cs +++ b/crypto/src/crypto/prng/X931SecureRandom.cs @@ -96,5 +96,12 @@ namespace Org.BouncyCastle.Crypto.Prng { return EntropyUtilities.GenerateSeed(mDrbg.EntropySource, numBytes); } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public override void GenerateSeed(Span seed) + { + EntropyUtilities.GenerateSeed(mDrbg.EntropySource, seed); + } +#endif } } diff --git a/crypto/test/src/crypto/prng/test/TestEntropySourceProvider.cs b/crypto/test/src/crypto/prng/test/TestEntropySourceProvider.cs index ae80b3dbe..1c0d24dba 100644 --- a/crypto/test/src/crypto/prng/test/TestEntropySourceProvider.cs +++ b/crypto/test/src/crypto/prng/test/TestEntropySourceProvider.cs @@ -53,7 +53,7 @@ namespace Org.BouncyCastle.Crypto.Prng.Test #if NET6_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER int IEntropySource.GetEntropy(Span output) { - int length = bitsRequired / 8; + int length = System.Math.Min(output.Length, bitsRequired / 8); data.AsSpan(index, length).CopyTo(output); index += length; return length; diff --git a/crypto/test/src/util/test/FixedSecureRandom.cs b/crypto/test/src/util/test/FixedSecureRandom.cs index a7f3c1f3b..a23438794 100644 --- a/crypto/test/src/util/test/FixedSecureRandom.cs +++ b/crypto/test/src/util/test/FixedSecureRandom.cs @@ -213,6 +213,15 @@ namespace Org.BouncyCastle.Utilities.Test return GetNextBytes(this, numBytes); } + // NOTE: .NET Core 3.1 has Span, but is tested against our .NET Standard 2.0 assembly. +//#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER +#if NET6_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public override void GenerateSeed(Span seed) + { + NextBytes(seed); + } +#endif + public override void NextBytes(byte[] buf) { NextBytes(buf, 0, buf.Length); -- cgit 1.4.1