diff options
Diffstat (limited to 'crypto/src')
-rw-r--r-- | crypto/src/crypto/prng/CryptoApiRandomGenerator.cs | 13 | ||||
-rw-r--r-- | crypto/src/crypto/prng/DigestRandomGenerator.cs | 22 | ||||
-rw-r--r-- | crypto/src/crypto/prng/IRandomGenerator.cs | 4 | ||||
-rw-r--r-- | crypto/src/crypto/prng/SP800SecureRandom.cs | 7 | ||||
-rw-r--r-- | crypto/src/crypto/prng/VMPCRandomGenerator.cs | 18 | ||||
-rw-r--r-- | crypto/src/crypto/prng/X931Rng.cs | 61 | ||||
-rw-r--r-- | crypto/src/crypto/prng/X931SecureRandom.cs | 15 | ||||
-rw-r--r-- | crypto/src/security/SecureRandom.cs | 16 |
8 files changed, 155 insertions, 1 deletions
diff --git a/crypto/src/crypto/prng/CryptoApiRandomGenerator.cs b/crypto/src/crypto/prng/CryptoApiRandomGenerator.cs index 7803ddd3d..11d29a818 100644 --- a/crypto/src/crypto/prng/CryptoApiRandomGenerator.cs +++ b/crypto/src/crypto/prng/CryptoApiRandomGenerator.cs @@ -45,6 +45,9 @@ namespace Org.BouncyCastle.Crypto.Prng if (bytes.Length < (start + len)) throw new ArgumentException("Byte array too small for requested offset and length"); +#if NETCOREAPP2_0_OR_GREATER || NETSTANDARD2_0_OR_GREATER + rndProv.GetBytes(bytes, start, len); +#else if (bytes.Length == len && start == 0) { NextBytes(bytes); @@ -55,8 +58,16 @@ namespace Org.BouncyCastle.Crypto.Prng NextBytes(tmpBuf); Array.Copy(tmpBuf, 0, bytes, start, len); } +#endif } - #endregion +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public virtual void NextBytes(Span<byte> bytes) + { + rndProv.GetBytes(bytes); + } +#endif + +#endregion } } diff --git a/crypto/src/crypto/prng/DigestRandomGenerator.cs b/crypto/src/crypto/prng/DigestRandomGenerator.cs index 024db2852..3587956b6 100644 --- a/crypto/src/crypto/prng/DigestRandomGenerator.cs +++ b/crypto/src/crypto/prng/DigestRandomGenerator.cs @@ -90,6 +90,28 @@ namespace Org.BouncyCastle.Crypto.Prng } } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public virtual void NextBytes(Span<byte> bytes) + { + lock (this) + { + int stateOff = 0; + + GenerateState(); + + for (int i = 0; i < bytes.Length; ++i) + { + if (stateOff == state.Length) + { + GenerateState(); + stateOff = 0; + } + bytes[i] = state[stateOff++]; + } + } + } +#endif + private void CycleSeed() { DigestUpdate(seed); diff --git a/crypto/src/crypto/prng/IRandomGenerator.cs b/crypto/src/crypto/prng/IRandomGenerator.cs index 8dbe4068f..051f8f8c6 100644 --- a/crypto/src/crypto/prng/IRandomGenerator.cs +++ b/crypto/src/crypto/prng/IRandomGenerator.cs @@ -22,5 +22,9 @@ namespace Org.BouncyCastle.Crypto.Prng /// <param name="start">Index to start filling at.</param> /// <param name="len">Length of segment to fill.</param> void NextBytes(byte[] bytes, int start, int len); + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + void NextBytes(Span<byte> bytes); +#endif } } diff --git a/crypto/src/crypto/prng/SP800SecureRandom.cs b/crypto/src/crypto/prng/SP800SecureRandom.cs index 2e1484125..fb5c3a677 100644 --- a/crypto/src/crypto/prng/SP800SecureRandom.cs +++ b/crypto/src/crypto/prng/SP800SecureRandom.cs @@ -70,6 +70,13 @@ namespace Org.BouncyCastle.Crypto.Prng } } + // TODO Add efficient override (needs ISP80090Drbg support for spans) +//#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER +// public override void NextBytes(Span<byte> buffer) +// { +// } +//#endif + public override byte[] GenerateSeed(int numBytes) { return EntropyUtilities.GenerateSeed(mEntropySource, numBytes); diff --git a/crypto/src/crypto/prng/VMPCRandomGenerator.cs b/crypto/src/crypto/prng/VMPCRandomGenerator.cs index 64f287d13..72e6b5e7d 100644 --- a/crypto/src/crypto/prng/VMPCRandomGenerator.cs +++ b/crypto/src/crypto/prng/VMPCRandomGenerator.cs @@ -110,5 +110,23 @@ namespace Org.BouncyCastle.Crypto.Prng } } } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public virtual void NextBytes(Span<byte> bytes) + { + lock (P) + { + for (int i = 0; i != bytes.Length; i++) + { + s = P[(s + P[n & 0xff]) & 0xff]; + bytes[i] = P[(P[(P[s & 0xff]) & 0xff] + 1) & 0xff]; + byte temp = P[n & 0xff]; + P[n & 0xff] = P[s & 0xff]; + P[s & 0xff] = temp; + n = (byte) ((n + 1) & 0xff); + } + } + } +#endif } } diff --git a/crypto/src/crypto/prng/X931Rng.cs b/crypto/src/crypto/prng/X931Rng.cs index 53c982c25..f0bfdc9f1 100644 --- a/crypto/src/crypto/prng/X931Rng.cs +++ b/crypto/src/crypto/prng/X931Rng.cs @@ -103,6 +103,67 @@ namespace Org.BouncyCastle.Crypto.Prng return outputLen * 8; } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + internal int Generate(Span<byte> output, bool predictionResistant) + { + int outputLen = output.Length; + + if (mR.Length == 8) // 64 bit block size + { + if (mReseedCounter > BLOCK64_RESEED_MAX) + return -1; + + if (outputLen > BLOCK64_MAX_BITS_REQUEST / 8) + throw new ArgumentException("Number of bits per request limited to " + BLOCK64_MAX_BITS_REQUEST, "output"); + } + else + { + if (mReseedCounter > BLOCK128_RESEED_MAX) + return -1; + + if (outputLen > BLOCK128_MAX_BITS_REQUEST / 8) + throw new ArgumentException("Number of bits per request limited to " + BLOCK128_MAX_BITS_REQUEST, "output"); + } + + if (predictionResistant || mV == null) + { + mV = mEntropySource.GetEntropy(); + if (mV.Length != mEngine.GetBlockSize()) + throw new InvalidOperationException("Insufficient entropy returned"); + } + + int m = outputLen / mR.Length; + + for (int i = 0; i < m; i++) + { + mEngine.ProcessBlock(mDT, 0, mI, 0); + Process(mR, mI, mV); + Process(mV, mR, mI); + + mR.CopyTo(output[(i * mR.Length)..]); + + Increment(mDT); + } + + int bytesToCopy = (outputLen - m * mR.Length); + + if (bytesToCopy > 0) + { + mEngine.ProcessBlock(mDT, 0, mI, 0); + Process(mR, mI, mV); + Process(mV, mR, mI); + + mR.AsSpan(0, bytesToCopy).CopyTo(output[(m * mR.Length)..]); + + Increment(mDT); + } + + mReseedCounter++; + + return outputLen * 8; + } +#endif + /** * Reseed the RNG. */ diff --git a/crypto/src/crypto/prng/X931SecureRandom.cs b/crypto/src/crypto/prng/X931SecureRandom.cs index 1402e5c31..01678af8f 100644 --- a/crypto/src/crypto/prng/X931SecureRandom.cs +++ b/crypto/src/crypto/prng/X931SecureRandom.cs @@ -60,6 +60,21 @@ namespace Org.BouncyCastle.Crypto.Prng } } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public override void NextBytes(Span<byte> buffer) + { + lock (this) + { + // check if a reseed is required... + if (mDrbg.Generate(buffer, mPredictionResistant) < 0) + { + mDrbg.Reseed(); + mDrbg.Generate(buffer, mPredictionResistant); + } + } + } +#endif + public override byte[] GenerateSeed(int numBytes) { return EntropyUtilities.GenerateSeed(mDrbg.EntropySource, numBytes); diff --git a/crypto/src/security/SecureRandom.cs b/crypto/src/security/SecureRandom.cs index e8cac56f5..4e118e77a 100644 --- a/crypto/src/security/SecureRandom.cs +++ b/crypto/src/security/SecureRandom.cs @@ -181,6 +181,22 @@ namespace Org.BouncyCastle.Security generator.NextBytes(buf, off, len); } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public override void NextBytes(Span<byte> buffer) + { + if (generator != null) + { + generator.NextBytes(buffer); + } + else + { + byte[] tmp = new byte[buffer.Length]; + NextBytes(tmp); + tmp.CopyTo(buffer); + } + } +#endif + private static readonly double DoubleScale = 1.0 / Convert.ToDouble(1L << 53); public override double NextDouble() |