diff --git a/crypto/src/crypto/CipherKeyGenerator.cs b/crypto/src/crypto/CipherKeyGenerator.cs
index 5d00d34dd..d8d9b29b5 100644
--- a/crypto/src/crypto/CipherKeyGenerator.cs
+++ b/crypto/src/crypto/CipherKeyGenerator.cs
@@ -75,9 +75,9 @@ namespace Org.BouncyCastle.Crypto
return engineGenerateKey();
}
- protected virtual byte[] engineGenerateKey()
+ protected virtual byte[] engineGenerateKey()
{
- return random.GenerateSeed(strength);
+ return SecureRandom.GetNextBytes(random, strength);
}
}
}
diff --git a/crypto/src/crypto/encodings/OaepEncoding.cs b/crypto/src/crypto/encodings/OaepEncoding.cs
index a4d2f0e36..95814ef25 100644
--- a/crypto/src/crypto/encodings/OaepEncoding.cs
+++ b/crypto/src/crypto/encodings/OaepEncoding.cs
@@ -161,7 +161,7 @@ namespace Org.BouncyCastle.Crypto.Encodings
//
// generate the seed.
//
- byte[] seed = random.GenerateSeed(defHash.Length);
+ byte[] seed = SecureRandom.GetNextBytes(random, defHash.Length);
//
// mask the message block.
diff --git a/crypto/src/crypto/prng/CryptoApiEntropySourceProvider.cs b/crypto/src/crypto/prng/CryptoApiEntropySourceProvider.cs
new file mode 100644
index 000000000..68579aaf4
--- /dev/null
+++ b/crypto/src/crypto/prng/CryptoApiEntropySourceProvider.cs
@@ -0,0 +1,70 @@
+#if !(NETCF_1_0 || PORTABLE)
+using System;
+using System.Security.Cryptography;
+
+namespace Org.BouncyCastle.Crypto.Prng
+{
+ public class CryptoApiEntropySourceProvider
+ : IEntropySourceProvider
+ {
+ private readonly RandomNumberGenerator mRng;
+ private readonly bool mPredictionResistant;
+
+ public CryptoApiEntropySourceProvider()
+ : this(new RNGCryptoServiceProvider(), true)
+ {
+ }
+
+ public CryptoApiEntropySourceProvider(RandomNumberGenerator rng, bool isPredictionResistant)
+ {
+ if (rng == null)
+ throw new ArgumentNullException("rng");
+
+ mRng = rng;
+ mPredictionResistant = isPredictionResistant;
+ }
+
+ public IEntropySource Get(int bitsRequired)
+ {
+ return new CryptoApiEntropySource(mRng, mPredictionResistant, bitsRequired);
+ }
+
+ private class CryptoApiEntropySource
+ : IEntropySource
+ {
+ private readonly RandomNumberGenerator mRng;
+ private readonly bool mPredictionResistant;
+ private readonly int mEntropySize;
+
+ internal CryptoApiEntropySource(RandomNumberGenerator rng, bool predictionResistant, int entropySize)
+ {
+ this.mRng = rng;
+ this.mPredictionResistant = predictionResistant;
+ this.mEntropySize = entropySize;
+ }
+
+ #region IEntropySource Members
+
+ bool IEntropySource.IsPredictionResistant
+ {
+ get { return mPredictionResistant; }
+ }
+
+ byte[] IEntropySource.GetEntropy()
+ {
+ byte[] result = new byte[(mEntropySize + 7) / 8];
+ mRng.GetBytes(result);
+ return result;
+ }
+
+ int IEntropySource.EntropySize
+ {
+ get { return mEntropySize; }
+ }
+
+ #endregion
+ }
+ }
+}
+
+#endif
diff --git a/crypto/src/crypto/prng/DigestRandomGenerator.cs b/crypto/src/crypto/prng/DigestRandomGenerator.cs
index cbd2ef060..f5a29952a 100644
--- a/crypto/src/crypto/prng/DigestRandomGenerator.cs
+++ b/crypto/src/crypto/prng/DigestRandomGenerator.cs
@@ -1,6 +1,7 @@
using System;
using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Utilities;
namespace Org.BouncyCastle.Crypto.Prng
{
@@ -108,15 +109,12 @@ namespace Org.BouncyCastle.Crypto.Prng
private void DigestAddCounter(long seedVal)
{
- ulong seed = (ulong)seedVal;
- for (int i = 0; i != 8; i++)
- {
- digest.Update((byte)seed);
- seed >>= 8;
- }
+ byte[] bytes = new byte[8];
+ Pack.UInt64_To_LE((ulong)seedVal, bytes);
+ digest.BlockUpdate(bytes, 0, bytes.Length);
}
- private void DigestUpdate(byte[] inSeed)
+ private void DigestUpdate(byte[] inSeed)
{
digest.BlockUpdate(inSeed, 0, inSeed.Length);
}
diff --git a/crypto/src/crypto/prng/EntropyUtilities.cs b/crypto/src/crypto/prng/EntropyUtilities.cs
new file mode 100644
index 000000000..58c8703f4
--- /dev/null
+++ b/crypto/src/crypto/prng/EntropyUtilities.cs
@@ -0,0 +1,30 @@
+using System;
+
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Prng
+{
+ public abstract class EntropyUtilities
+ {
+ /**
+ * Generate numBytes worth of entropy from the passed in entropy source.
+ *
+ * @param entropySource the entropy source to request the data from.
+ * @param numBytes the number of bytes of entropy requested.
+ * @return a byte array populated with the random data.
+ */
+ public static byte[] GenerateSeed(IEntropySource entropySource, int numBytes)
+ {
+ byte[] bytes = new byte[numBytes];
+ int count = 0;
+ while (count < numBytes)
+ {
+ byte[] entropy = entropySource.GetEntropy();
+ int toCopy = System.Math.Min(bytes.Length, numBytes - count);
+ Array.Copy(entropy, 0, bytes, count, toCopy);
+ count += toCopy;
+ }
+ return bytes;
+ }
+ }
+}
diff --git a/crypto/src/crypto/prng/SP800SecureRandom.cs b/crypto/src/crypto/prng/SP800SecureRandom.cs
index 996ba0846..5c5bda399 100644
--- a/crypto/src/crypto/prng/SP800SecureRandom.cs
+++ b/crypto/src/crypto/prng/SP800SecureRandom.cs
@@ -74,9 +74,7 @@ namespace Org.BouncyCastle.Crypto.Prng
public override byte[] GenerateSeed(int numBytes)
{
- byte[] bytes = new byte[numBytes];
- NextBytes(bytes);
- return bytes;
+ return EntropyUtilities.GenerateSeed(mEntropySource, numBytes);
}
}
}
diff --git a/crypto/src/crypto/prng/X931Rng.cs b/crypto/src/crypto/prng/X931Rng.cs
index d09cc6618..987379d4b 100644
--- a/crypto/src/crypto/prng/X931Rng.cs
+++ b/crypto/src/crypto/prng/X931Rng.cs
@@ -10,7 +10,7 @@ namespace Org.BouncyCastle.Crypto.Prng
private const int BLOCK128_MAX_BITS_REQUEST = 1 << (19 - 1);
private readonly IBlockCipher mEngine;
- private readonly IEntropySource mEntropySource;
+ internal readonly IEntropySource mEntropySource;
private readonly byte[] mDT;
private readonly byte[] mI;
diff --git a/crypto/src/crypto/prng/X931SecureRandom.cs b/crypto/src/crypto/prng/X931SecureRandom.cs
index a87bf1567..bce8d2cf1 100644
--- a/crypto/src/crypto/prng/X931SecureRandom.cs
+++ b/crypto/src/crypto/prng/X931SecureRandom.cs
@@ -64,9 +64,7 @@ namespace Org.BouncyCastle.Crypto.Prng
public override byte[] GenerateSeed(int numBytes)
{
- byte[] bytes = new byte[numBytes];
- NextBytes(bytes);
- return bytes;
+ return EntropyUtilities.GenerateSeed(mDrbg.mEntropySource, numBytes);
}
}
}
diff --git a/crypto/src/security/SecureRandom.cs b/crypto/src/security/SecureRandom.cs
index 8683b4729..cb831acc2 100644
--- a/crypto/src/security/SecureRandom.cs
+++ b/crypto/src/security/SecureRandom.cs
@@ -68,11 +68,18 @@ namespace Org.BouncyCastle.Security
if (autoSeed)
{
prng.AddSeedMaterial(NextCounterValue());
- prng.AddSeedMaterial(GetSeed(digest.GetDigestSize()));
+ prng.AddSeedMaterial(GetNextBytes(Master, digest.GetDigestSize()));
}
return prng;
}
+ public static byte[] GetNextBytes(SecureRandom secureRandom, int length)
+ {
+ byte[] result = new byte[length];
+ secureRandom.NextBytes(result);
+ return result;
+ }
+
/// <summary>
/// Create and auto-seed an instance based on the given algorithm.
/// </summary>
@@ -104,12 +111,10 @@ namespace Org.BouncyCastle.Security
throw new ArgumentException("Unrecognised PRNG algorithm: " + algorithm, "algorithm");
}
+ [Obsolete("Call GenerateSeed() on a SecureRandom instance instead")]
public static byte[] GetSeed(int length)
{
-#if NETCF_1_0 || PORTABLE
- lock (master)
-#endif
- return Master.GenerateSeed(length);
+ return GetNextBytes(Master, length);
}
protected readonly IRandomGenerator generator;
@@ -145,11 +150,7 @@ namespace Org.BouncyCastle.Security
public virtual byte[] GenerateSeed(int length)
{
- SetSeed(DateTime.Now.Ticks);
-
- byte[] rv = new byte[length];
- NextBytes(rv);
- return rv;
+ return GetNextBytes(Master, length);
}
public virtual void SetSeed(byte[] seed)
|