Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- namespace System.Security.Cryptography
- {
- /// <summary>
- /// Represents a static and thread safe cryptographic Random Number Generator (RNG) using the implementation provided by the cryptographic service provider (CSP).
- /// </summary>
- public static class SecureStaticRandom
- {
- private const long MAX_EXCLUSIVE_UINT = 1 + (long)uint.MaxValue;
- private const double MAX_EXCLUSIVE_UINT_DOUBLE = 1.0d + uint.MaxValue;
- [ThreadStatic] private static RNGCryptoServiceProvider random;
- [ThreadStatic] private static byte[] uintBuffer;
- /// <summary>
- /// Returns a non-negative random integer.
- /// </summary>
- /// <returns>A 32-bit signed integer that is greater than or equal to 0 and less than <see cref="F:System.Int32.MaxValue" />.</returns>
- public static int Next()
- {
- return (int)GetRandomUInt32() & 0x7FFFFFFF;
- }
- /// <summary>
- /// Returns a non-negative random integer that is less than the specified maximum.
- /// </summary>
- /// <param name="maxValue">The exclusive upper bound of the random number to be generated. <paramref name="maxValue" /> must be greater than or equal to 0.</param>
- /// <returns>A 32-bit signed integer that is greater than or equal to 0, and less than <paramref name="maxValue" />; that is, the range of return values ordinarily includes 0 but not <paramref name="maxValue" />. However, if <paramref name="maxValue" /> equals 0, <paramref name="maxValue" /> is returned.</returns>
- /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="maxValue" /> is less than 0. </exception>
- public static int Next(int maxValue)
- {
- return Next(0, maxValue);
- }
- /// <summary>
- /// Returns a random integer that is within a specified range.
- /// </summary>
- /// <param name="minValue">The inclusive lower bound of the random number returned.</param>
- /// <param name="maxValue">The exclusive upper bound of the random number returned. <paramref name="maxValue" /> must be greater than or equal to <paramref name="minValue" />.</param>
- /// <returns>A 32-bit signed integer greater than or equal to <paramref name="minValue" /> and less than <paramref name="maxValue" />; that is, the range of return values includes <paramref name="minValue" /> but not <paramref name="maxValue" />. If <paramref name="minValue" /> equals <paramref name="maxValue" />, <paramref name="minValue" /> is returned.</returns>
- /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="minValue" /> is greater than <paramref name="maxValue" />. </exception>
- public static int Next(int minValue, int maxValue)
- {
- if (minValue > maxValue) throw new ArgumentOutOfRangeException(nameof(minValue));
- if (maxValue < 1) throw new ArgumentOutOfRangeException(nameof(maxValue));
- if (minValue == maxValue) return minValue;
- long delta = maxValue - minValue;
- while (true)
- {
- uint number = GetRandomUInt32();
- long remainder = MAX_EXCLUSIVE_UINT % delta;
- if (number < MAX_EXCLUSIVE_UINT - remainder)
- {
- return (int)(minValue + (number % delta));
- }
- }
- }
- /// <summary>
- /// Fills an array of bytes with a cryptographically strong sequence of random values.
- /// </summary>
- /// <param name="data">An array of bytes to contain random numbers.</param>
- /// /// <exception cref="T:System.ArgumentNullException"><paramref name="data" /> is <see langword="null" />. </exception>
- public static void GetBytes(byte[] data)
- {
- if (random == null) InitThreadStaticFields();
- random.GetBytes(data);
- }
- /// <summary>
- /// Returns a random boolean.
- /// </summary>
- /// <returns>A boolean value.</returns>
- public static bool NextBool()
- {
- return NextDouble() >= 0.5;
- }
- /// <summary>
- /// Returns a random floating-point number that is greater than or equal to 0.0, and less than 1.0.
- /// </summary>
- /// <returns>A double-precision floating point number that is greater than or equal to 0.0, and less than 1.0.</returns>
- public static double NextDouble()
- {
- return GetRandomUInt32() / MAX_EXCLUSIVE_UINT_DOUBLE;
- }
- /// <summary>
- /// Returns a random floating-point number that is greater than or equal to 0.0, and less than <paramref name="maxValue" />.
- /// </summary>
- /// <param name="maxValue">The exclusive upper bound of the random number returned.</param>
- /// <returns>A double-precision floating point number that is greater than or equal to 0, and less than <paramref name="maxValue" />; that is, the range of return values ordinarily includes 0 but not <paramref name="maxValue" />.</returns>
- public static double NextDouble(int maxValue)
- {
- if (double.IsInfinity(maxValue)
- || double.IsNaN(maxValue)
- || maxValue < 1.0d) throw new ArgumentOutOfRangeException(nameof(maxValue));
- return NextDouble() * maxValue;
- }
- /// <summary>
- /// Returns a random floating-point number that is within a specified range.
- /// </summary>
- /// <param name="minValue">The inclusive lower bound of the random number returned.</param>
- /// <param name="maxValue">The exclusive upper bound of the random number returned.</param>
- /// <returns>A double-precision floating point number that is greater than or equal to <paramref name="minValue" />, and less than <paramref name="maxValue" />; that is, the range of return values ordinarily includes 0 but not <paramref name="maxValue" />.</returns>
- public static double NextDouble(double minValue, double maxValue)
- {
- if (double.IsInfinity(minValue)
- || double.IsNaN(minValue)
- || minValue >= maxValue) throw new ArgumentOutOfRangeException(nameof(maxValue));
- if (double.IsInfinity(maxValue)
- || double.IsNaN(maxValue)
- || maxValue < 1.0d) throw new ArgumentOutOfRangeException(nameof(maxValue));
- return minValue + NextDouble() * (maxValue - minValue);
- }
- /// <summary>
- /// Fills the elements of a specified array of bytes with a cryptographically strong sequence of random nonzero values.
- /// </summary>
- /// <param name="data">An array of bytes to contain random numbers.</param>
- /// /// <exception cref="T:System.ArgumentNullException"><paramref name="data" /> is <see langword="null" />. </exception>
- public static void GetNonZeroBytes(byte[] data)
- {
- if (random == null) InitThreadStaticFields();
- random.GetNonZeroBytes(data);
- }
- private static uint GetRandomUInt32()
- {
- if (random == null) InitThreadStaticFields();
- random.GetBytes(uintBuffer);
- return BitConverter.ToUInt32(uintBuffer, 0);
- }
- private static void InitThreadStaticFields()
- {
- random = new RNGCryptoServiceProvider();
- uintBuffer = new byte[4];
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement