diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2015-11-17 18:57:14 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2015-11-17 18:57:14 +0700 |
commit | ced92a086526c85e31842aaa60ede4c4b8e0fdb9 (patch) | |
tree | 15b6cba6381bb5ee611fd5873c46b3ee37163889 | |
parent | Port some DES/DESEDE changes from Java (diff) | |
download | BouncyCastle.NET-ed25519-ced92a086526c85e31842aaa60ede4c4b8e0fdb9.tar.xz |
Improve usage/behaviour of SecureRandom.GenerateSeed
-rw-r--r-- | crypto/crypto.csproj | 10 | ||||
-rw-r--r-- | crypto/src/crypto/CipherKeyGenerator.cs | 4 | ||||
-rw-r--r-- | crypto/src/crypto/encodings/OaepEncoding.cs | 2 | ||||
-rw-r--r-- | crypto/src/crypto/prng/CryptoApiEntropySourceProvider.cs | 70 | ||||
-rw-r--r-- | crypto/src/crypto/prng/DigestRandomGenerator.cs | 12 | ||||
-rw-r--r-- | crypto/src/crypto/prng/EntropyUtilities.cs | 30 | ||||
-rw-r--r-- | crypto/src/crypto/prng/SP800SecureRandom.cs | 4 | ||||
-rw-r--r-- | crypto/src/crypto/prng/X931Rng.cs | 2 | ||||
-rw-r--r-- | crypto/src/crypto/prng/X931SecureRandom.cs | 4 | ||||
-rw-r--r-- | crypto/src/security/SecureRandom.cs | 21 | ||||
-rw-r--r-- | crypto/test/src/security/test/SecureRandomTest.cs | 41 | ||||
-rw-r--r-- | crypto/test/src/test/BlockCipherTest.cs | 2 | ||||
-rw-r--r-- | crypto/test/src/util/test/FixedSecureRandom.cs | 7 |
13 files changed, 178 insertions, 31 deletions
diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index 395ea08df..ecfdc7311 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -4319,6 +4319,11 @@ BuildAction = "Compile" /> <File + RelPath = "src\crypto\prng\CryptoApiEntropySourceProvider.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "src\crypto\prng\CryptoApiRandomGenerator.cs" SubType = "Code" BuildAction = "Compile" @@ -4329,6 +4334,11 @@ BuildAction = "Compile" /> <File + RelPath = "src\crypto\prng\EntropyUtilities.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "src\crypto\prng\IDrbgProvider.cs" SubType = "Code" BuildAction = "Compile" 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) diff --git a/crypto/test/src/security/test/SecureRandomTest.cs b/crypto/test/src/security/test/SecureRandomTest.cs index f93afc0aa..f1d83b29c 100644 --- a/crypto/test/src/security/test/SecureRandomTest.cs +++ b/crypto/test/src/security/test/SecureRandomTest.cs @@ -3,7 +3,12 @@ using System.Text; using NUnit.Framework; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Macs; using Org.BouncyCastle.Crypto.Prng; +using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Security.Tests @@ -61,6 +66,30 @@ namespace Org.BouncyCastle.Security.Tests } [Test] + public void TestSP800Ctr() + { + SecureRandom random = new SP800SecureRandomBuilder().BuildCtr(new AesFastEngine(), 256, new byte[32], false); + + CheckSecureRandom(random); + } + + [Test] + public void TestSP800Hash() + { + SecureRandom random = new SP800SecureRandomBuilder().BuildHash(new Sha256Digest(), new byte[32], false); + + CheckSecureRandom(random); + } + + [Test] + public void TestSP800HMac() + { + SecureRandom random = new SP800SecureRandomBuilder().BuildHMac(new HMac(new Sha256Digest()), new byte[32], false); + + CheckSecureRandom(random); + } + + [Test] public void TestThreadedSeed() { SecureRandom random = SecureRandom.GetInstance("SHA1PRNG", false); @@ -73,7 +102,15 @@ namespace Org.BouncyCastle.Security.Tests public void TestVmpcPrng() { SecureRandom random = new SecureRandom(new VmpcRandomGenerator()); - random.SetSeed(SecureRandom.GetSeed(32)); + random.SetSeed(random.GenerateSeed(32)); + + CheckSecureRandom(random); + } + + [Test] + public void TestX931() + { + SecureRandom random = new X931SecureRandomBuilder().Build(new AesFastEngine(), new KeyParameter(new byte[16]), false); CheckSecureRandom(random); } @@ -106,7 +143,7 @@ namespace Org.BouncyCastle.Security.Tests private static double MeasureChiSquared(SecureRandom random, int rounds) { - byte[] opts = SecureRandom.GetSeed(2); + byte[] opts = random.GenerateSeed(2); int[] counts = new int[256]; byte[] bs = new byte[256]; diff --git a/crypto/test/src/test/BlockCipherTest.cs b/crypto/test/src/test/BlockCipherTest.cs index 93cf2b0a5..fc3a99f4e 100644 --- a/crypto/test/src/test/BlockCipherTest.cs +++ b/crypto/test/src/test/BlockCipherTest.cs @@ -410,7 +410,7 @@ namespace Org.BouncyCastle.Tests else { // NB: rand always generates same values each test run - iv = rand.GenerateSeed(ivLength); + iv = SecureRandom.GetNextBytes(rand, ivLength); } parameters = new ParametersWithIV(key, iv); diff --git a/crypto/test/src/util/test/FixedSecureRandom.cs b/crypto/test/src/util/test/FixedSecureRandom.cs index 15a2e9bb3..d8598ac24 100644 --- a/crypto/test/src/util/test/FixedSecureRandom.cs +++ b/crypto/test/src/util/test/FixedSecureRandom.cs @@ -38,7 +38,12 @@ namespace Org.BouncyCastle.Utilities.Test return new FixedSecureRandom(bOut.ToArray()); } - public override void NextBytes( + public override byte[] GenerateSeed(int numBytes) + { + return SecureRandom.GetNextBytes(this, numBytes); + } + + public override void NextBytes( byte[] buf) { Array.Copy(_data, _index, buf, 0, buf.Length); |