mirror of
https://github.com/ShareX/ShareX.git
synced 2024-07-05 06:30:36 +12: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
|
@ -243,7 +243,7 @@ public static string HourTo12(int hour)
|
|||
|
||||
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)
|
||||
|
@ -283,7 +283,7 @@ public static string GetRandomLine(string text)
|
|||
string[] lines = text.Trim().Lines();
|
||||
if (lines != null && lines.Length > 0)
|
||||
{
|
||||
return lines[MathHelpers.Random(0, lines.Length - 1)];
|
||||
return lines[MathHelpers.CryptoRandom(0, lines.Length - 1)];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#endregion License Information (GPL v3)
|
||||
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace ShareX.HelpersLib
|
||||
{
|
||||
|
@ -36,6 +37,19 @@ public static class MathHelpers
|
|||
private static readonly object randomLock = new object();
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
return radian * RadianPI;
|
||||
|
|
Loading…
Reference in a new issue