mirror of
https://github.com/ShareX/ShareX.git
synced 2024-10-04 12:14:45 +13:00
MathHelpers: add CryptoRandom()
Random() is biased and generates predictable numbers (seeded with time by default), using RNGCryptoServiceProvider fixes this.
This commit is contained in:
parent
52e3ec4a87
commit
ed40360491
2 changed files with 64 additions and 2 deletions
|
@ -243,7 +243,7 @@ public static string HourTo12(int hour)
|
||||||
|
|
||||||
public static char GetRandomChar(string chars)
|
public static char GetRandomChar(string chars)
|
||||||
{
|
{
|
||||||
return chars[MathHelpers.Random(chars.Length - 1)];
|
return chars[MathHelpers.CryptoRandom(chars.Length - 1)];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetRandomString(string chars, int length)
|
public static string GetRandomString(string chars, int length)
|
||||||
|
@ -283,7 +283,7 @@ public static string GetRandomLine(string text)
|
||||||
string[] lines = text.Trim().Lines();
|
string[] lines = text.Trim().Lines();
|
||||||
if (lines != null && lines.Length > 0)
|
if (lines != null && lines.Length > 0)
|
||||||
{
|
{
|
||||||
return lines[MathHelpers.Random(0, lines.Length - 1)];
|
return lines[MathHelpers.CryptoRandom(0, lines.Length - 1)];
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ You should have received a copy of the GNU General Public License
|
||||||
#endregion License Information (GPL v3)
|
#endregion License Information (GPL v3)
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
namespace ShareX.HelpersLib
|
namespace ShareX.HelpersLib
|
||||||
{
|
{
|
||||||
|
@ -36,6 +37,19 @@ public static class MathHelpers
|
||||||
private static readonly object randomLock = new object();
|
private static readonly object randomLock = new object();
|
||||||
private static readonly Random random = new Random();
|
private static readonly Random random = new Random();
|
||||||
|
|
||||||
|
private static readonly object cryptoRandomLock = new object();
|
||||||
|
private static readonly RNGCryptoServiceProvider cryptoRandom = new RNGCryptoServiceProvider();
|
||||||
|
private static byte[] rngBuf = new byte[4];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a random number between 0 and <c>max</c> (inclusive).
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This uses <c>System.Random()</c>, which does not provide safe random numbers. This function
|
||||||
|
/// should not be used to generate things that should be unique, like random file names.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="max">The upper limit of the number (inclusive).</param>
|
||||||
|
/// <returns>A random number.</returns>
|
||||||
public static int Random(int max)
|
public static int Random(int max)
|
||||||
{
|
{
|
||||||
lock (randomLock)
|
lock (randomLock)
|
||||||
|
@ -52,6 +66,54 @@ public static int Random(int min, int max)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a random number between 0 and <c>max</c> (inclusive) generated with a cryptographic PRNG.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="max">The upper limit of the number (inclusive).</param>
|
||||||
|
/// <returns>A cryptographically random number.</returns>
|
||||||
|
public static int CryptoRandom(int max)
|
||||||
|
{
|
||||||
|
return CryptoRandom(0, max);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a random number between <c>min</c> and <c>max</c> (inclusive) generated with a cryptographic PRNG.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="min">The lower limit of the number.</param>
|
||||||
|
/// <param name="max">The upper limit of the number (inclusive).</param>
|
||||||
|
/// <returns>A cryptographically random number.</returns>
|
||||||
|
public static int CryptoRandom(int min, int max)
|
||||||
|
{
|
||||||
|
// this code avoids bias in random number generation, which is important when generating random filenames, etc.
|
||||||
|
// adapted from https://web.archive.org/web/20150114085328/http://msdn.microsoft.com:80/en-us/magazine/cc163367.aspx
|
||||||
|
if (min > max)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException("min");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (min == max)
|
||||||
|
{
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock (cryptoRandomLock)
|
||||||
|
{
|
||||||
|
var diff = (long)max - min;
|
||||||
|
long ceiling = (1 + (long)uint.MaxValue);
|
||||||
|
long remainder = ceiling % diff;
|
||||||
|
// this should only iterate once unless we generate really large numbers
|
||||||
|
uint r;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
cryptoRandom.GetBytes(rngBuf);
|
||||||
|
r = BitConverter.ToUInt32(rngBuf, 0);
|
||||||
|
} while (r >= ceiling - remainder);
|
||||||
|
|
||||||
|
return (int)(min + (r % diff));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static float RadianToDegree(float radian)
|
public static float RadianToDegree(float radian)
|
||||||
{
|
{
|
||||||
return radian * RadianPI;
|
return radian * RadianPI;
|
||||||
|
|
Loading…
Reference in a new issue