Advertisement
ibrahim_elsakka

SecureStaticRandom.cs

Nov 4th, 2020
2,126
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 7.49 KB | None | 0 0
  1. using System;
  2.  
  3. namespace System.Security.Cryptography
  4. {
  5.     /// <summary>
  6.     /// Represents a static and thread safe cryptographic Random Number Generator (RNG) using the implementation provided by the cryptographic service provider (CSP).
  7.     /// </summary>
  8.     public static class SecureStaticRandom
  9.     {
  10.         private const long MAX_EXCLUSIVE_UINT = 1 + (long)uint.MaxValue;
  11.         private const double MAX_EXCLUSIVE_UINT_DOUBLE = 1.0d + uint.MaxValue;
  12.  
  13.         [ThreadStatic] private static RNGCryptoServiceProvider random;
  14.         [ThreadStatic] private static byte[] uintBuffer;
  15.  
  16.         /// <summary>
  17.         /// Returns a non-negative random integer.
  18.         /// </summary>
  19.         /// <returns>A 32-bit signed integer that is greater than or equal to 0 and less than <see cref="F:System.Int32.MaxValue" />.</returns>
  20.         public static int Next()
  21.         {
  22.             return (int)GetRandomUInt32() & 0x7FFFFFFF;
  23.         }
  24.  
  25.         /// <summary>
  26.         /// Returns a non-negative random integer that is less than the specified maximum.
  27.         /// </summary>
  28.         /// <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>
  29.         /// <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>
  30.         /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="maxValue" /> is less than 0. </exception>
  31.         public static int Next(int maxValue)
  32.         {
  33.             return Next(0, maxValue);
  34.         }
  35.  
  36.         /// <summary>
  37.         /// Returns a random integer that is within a specified range.
  38.         /// </summary>
  39.         /// <param name="minValue">The inclusive lower bound of the random number returned.</param>
  40.         /// <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>
  41.         /// <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>
  42.         /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="minValue" /> is greater than <paramref name="maxValue" />. </exception>
  43.         public static int Next(int minValue, int maxValue)
  44.         {
  45.             if (minValue > maxValue) throw new ArgumentOutOfRangeException(nameof(minValue));
  46.             if (maxValue < 1) throw new ArgumentOutOfRangeException(nameof(maxValue));
  47.  
  48.             if (minValue == maxValue) return minValue;
  49.  
  50.             long delta = maxValue - minValue;
  51.  
  52.             while (true)
  53.             {
  54.                 uint number = GetRandomUInt32();
  55.  
  56.                 long remainder = MAX_EXCLUSIVE_UINT % delta;
  57.  
  58.                 if (number < MAX_EXCLUSIVE_UINT - remainder)
  59.                 {
  60.                     return (int)(minValue + (number % delta));
  61.                 }
  62.             }
  63.         }
  64.  
  65.         /// <summary>
  66.         /// Fills an array of bytes with a cryptographically strong sequence of random values.
  67.         /// </summary>
  68.         /// <param name="data">An array of bytes to contain random numbers.</param>
  69.         /// /// <exception cref="T:System.ArgumentNullException"><paramref name="data" /> is <see langword="null" />. </exception>
  70.         public static void GetBytes(byte[] data)
  71.         {
  72.             if (random == null) InitThreadStaticFields();
  73.  
  74.             random.GetBytes(data);
  75.         }
  76.  
  77.         /// <summary>
  78.         /// Returns a random boolean.
  79.         /// </summary>
  80.         /// <returns>A boolean value.</returns>
  81.         public static bool NextBool()
  82.         {
  83.             return NextDouble() >= 0.5;
  84.         }
  85.  
  86.         /// <summary>
  87.         /// Returns a random floating-point number that is greater than or equal to 0.0, and less than 1.0.
  88.         /// </summary>
  89.         /// <returns>A double-precision floating point number that is greater than or equal to 0.0, and less than 1.0.</returns>
  90.         public static double NextDouble()
  91.         {
  92.             return GetRandomUInt32() / MAX_EXCLUSIVE_UINT_DOUBLE;
  93.         }
  94.  
  95.         /// <summary>
  96.         /// Returns a random floating-point number that is greater than or equal to 0.0, and less than <paramref name="maxValue" />.
  97.         /// </summary>
  98.         /// <param name="maxValue">The exclusive upper bound of the random number returned.</param>
  99.         /// <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>
  100.         public static double NextDouble(int maxValue)
  101.         {
  102.             if (double.IsInfinity(maxValue)
  103.                 || double.IsNaN(maxValue)
  104.                 || maxValue < 1.0d) throw new ArgumentOutOfRangeException(nameof(maxValue));
  105.  
  106.             return NextDouble() * maxValue;
  107.         }
  108.  
  109.         /// <summary>
  110.         /// Returns a random floating-point number that is within a specified range.
  111.         /// </summary>
  112.         /// <param name="minValue">The inclusive lower bound of the random number returned.</param>
  113.         /// <param name="maxValue">The exclusive upper bound of the random number returned.</param>
  114.         /// <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>
  115.         public static double NextDouble(double minValue, double maxValue)
  116.         {
  117.             if (double.IsInfinity(minValue)
  118.                 || double.IsNaN(minValue)
  119.                 || minValue >= maxValue) throw new ArgumentOutOfRangeException(nameof(maxValue));
  120.  
  121.             if (double.IsInfinity(maxValue)
  122.                 || double.IsNaN(maxValue)
  123.                 || maxValue < 1.0d) throw new ArgumentOutOfRangeException(nameof(maxValue));
  124.  
  125.             return minValue + NextDouble() * (maxValue - minValue);
  126.         }
  127.  
  128.         /// <summary>
  129.         /// Fills the elements of a specified array of bytes with a cryptographically strong sequence of random nonzero values.
  130.         /// </summary>
  131.         /// <param name="data">An array of bytes to contain random numbers.</param>
  132.         /// /// <exception cref="T:System.ArgumentNullException"><paramref name="data" /> is <see langword="null" />. </exception>
  133.         public static void GetNonZeroBytes(byte[] data)
  134.         {
  135.             if (random == null) InitThreadStaticFields();
  136.  
  137.             random.GetNonZeroBytes(data);
  138.         }
  139.  
  140.         private static uint GetRandomUInt32()
  141.         {
  142.             if (random == null) InitThreadStaticFields();
  143.  
  144.             random.GetBytes(uintBuffer);
  145.  
  146.             return BitConverter.ToUInt32(uintBuffer, 0);
  147.         }
  148.  
  149.         private static void InitThreadStaticFields()
  150.         {
  151.             random = new RNGCryptoServiceProvider();
  152.  
  153.             uintBuffer = new byte[4];
  154.         }
  155.     }
  156. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement