Skip to content

Instantly share code, notes, and snippets.

@mjs3339
Created February 21, 2019 15:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mjs3339/ad9d8002d7102f557f316c0b538a6823 to your computer and use it in GitHub Desktop.
Save mjs3339/ad9d8002d7102f557f316c0b538a6823 to your computer and use it in GitHub Desktop.
C# Crypto Random Number Generator
[Serializable]
public class CryptoRandomNumberGeneratorExperimental : RandomNumberGenerator
{
private const double DBi = 1.0 / ulong.MaxValue;
private readonly CryptoGetBytesExperimental crng = new CryptoGetBytesExperimental();
public bool NextBool()
{
return Sample() < .5;
}
/// <summary>
/// Returns a random character value.
/// </summary>
public char NextChar()
{
return(char) (Sample() * char.MaxValue);
}
/// <summary>
/// </summary>
/// <param name="maxValue">Exclusive value</param>
/// <returns></returns>
public char NextChar(char maxValue)
{
if(maxValue == 0)
throw new ArgumentException("maxValue must be greater than zero.");
return(char) (Sample() * maxValue);
}
/// <summary>
/// Returns a random character value.
/// </summary>
/// <param name="minValue">Inclusive value.</param>
/// <param name="maxValue">Exclusive value.</param>
/// <returns></returns>
public char NextChar(char minValue, char maxValue)
{
if(maxValue < minValue)
throw new ArgumentException("maxValue must be greater than or equal to minValue");
return(char) (Sample() * (maxValue - minValue) + minValue);
}
/// <summary>
/// Returns a random short byte value.
/// </summary>
public sbyte NextSByte()
{
return(sbyte) (Sample() * sbyte.MaxValue);
}
/// <summary>
/// returns a short byte value
/// </summary>
/// <param name="maxValue">Exclusive value</param>
/// <returns></returns>
public sbyte NextSByte(int maxValue)
{
if(maxValue == 0)
throw new ArgumentException("maxValue must be greater than zero.");
return(sbyte) (Sample() * maxValue);
}
/// <summary>
/// Returns a random Short Byte value.
/// </summary>
/// <param name="minValue">Inclusive value.</param>
/// <param name="maxValue">Exclusive value.</param>
/// <returns></returns>
public sbyte NextSByte(int minValue, int maxValue)
{
if(maxValue < minValue)
throw new ArgumentException("maxValue must be greater than or equal to minValue");
return(sbyte) (Sample() * (maxValue - minValue) + minValue);
}
/// <summary>
/// Returns a random byte value.
/// </summary>
public byte NextByte()
{
return(byte) (Sample() * byte.MaxValue);
}
/// <summary>
/// returns a byte value
/// </summary>
/// <param name="maxValue">Exclusive value</param>
/// <returns></returns>
public byte NextByte(int maxValue)
{
if(maxValue == 0)
throw new ArgumentException("maxValue must be greater than zero.");
return(byte) (Sample() * maxValue);
}
/// <summary>
/// Returns a random Byte value.
/// </summary>
/// <param name="minValue">Inclusive value.</param>
/// <param name="maxValue">Exclusive value.</param>
/// <returns></returns>
public byte NextByte(int minValue, int maxValue)
{
if(maxValue < minValue)
throw new ArgumentException("maxValue must be greater than or equal to minValue");
return(byte) (Sample() * (maxValue - minValue) + minValue);
}
/// <summary>
/// Returns a random short value.
/// </summary>
public short NextShort()
{
return(short) (Sample() * short.MaxValue);
}
/// <summary>
/// returns a short value
/// </summary>
/// <param name="maxValue">Exclusive value</param>
/// <returns></returns>
public short NextShort(int maxValue)
{
if(maxValue == 0)
throw new ArgumentException("maxValue must be greater than zero.");
return(short) (Sample() * maxValue);
}
/// <summary>
/// Returns a random Short value.
/// </summary>
/// <param name="minValue">Inclusive value.</param>
/// <param name="maxValue">Exclusive value.</param>
/// <returns></returns>
public short NextShort(int minValue, int maxValue)
{
if(maxValue < minValue)
throw new ArgumentException("maxValue must be greater than or equal to minValue");
return(short) (Sample() * (maxValue - minValue) + minValue);
}
/// <summary>
/// Returns a random unsigned short value.
/// </summary>
public ushort NextUShort()
{
return(ushort) (Sample() * ushort.MaxValue);
}
/// <summary>
/// returns a unsigned short value between 0 and maxValue exclusively.
/// </summary>
/// <param name="maxValue">Exclusive value</param>
/// <returns></returns>
public ushort NextUShort(int maxValue)
{
if(maxValue == 0)
throw new ArgumentException("maxValue must be greater than zero.");
return(ushort) (Sample() * maxValue);
}
/// <summary>
/// Returns a random unsigned short value.
/// </summary>
/// <param name="minValue">Inclusive value.</param>
/// <param name="maxValue">Exclusive value.</param>
/// <returns></returns>
public ushort NextUShort(int minValue, int maxValue)
{
if(maxValue < minValue)
throw new ArgumentException("maxValue must be greater than or equal to minValue");
return(ushort) (Sample() * (maxValue - minValue) + minValue);
}
/// <summary>
/// Returns a random integer value.
/// </summary>
public int Next()
{
return(int) (Sample() * int.MaxValue);
}
/// <summary>
/// returns a integer value between 0 and maxValue exclusively.
/// </summary>
/// <param name="maxValue">Exclusive value</param>
/// <returns></returns>
public int Next(int maxValue)
{
if(maxValue == 0)
throw new ArgumentException("maxValue must be greater than zero.");
return(int) (Sample() * maxValue);
}
/// <summary>
/// Returns a random integer value.
/// </summary>
/// <param name="minValue">Inclusive value.</param>
/// <param name="maxValue">Exclusive value.</param>
/// <returns></returns>
public int Next(int minValue, int maxValue)
{
if(maxValue < minValue)
throw new ArgumentException("maxValue must be greater than or equal to minValue");
return(int) (Sample() * (maxValue - minValue) + minValue);
}
/// <summary>
/// Returns a random integer value.
/// </summary>
public int NextInt()
{
return(int) (Sample() * int.MaxValue);
}
/// <summary>
/// returns a integer value between 0 and maxValue exclusively.
/// </summary>
/// <param name="maxValue">Exclusive value</param>
/// <returns></returns>
public int NextInt(int maxValue)
{
if(maxValue == 0)
throw new ArgumentException("maxValue must be greater than zero.");
return(int) (Sample() * maxValue);
}
/// <summary>
/// Returns a random integer value.
/// </summary>
/// <param name="minValue">Inclusive value.</param>
/// <param name="maxValue">Exclusive value.</param>
/// <returns></returns>
public int NextInt(int minValue, int maxValue)
{
if(maxValue < minValue)
throw new ArgumentException("maxValue must be greater than or equal to minValue");
return(int) (Sample() * (maxValue - minValue) + minValue);
}
/// <summary>
/// Returns a random unsigned integer value.
/// </summary>
public uint NextUInt()
{
return(uint) (Sample() * uint.MaxValue);
}
/// <summary>
/// returns a unsigned integer value between 0 and maxValue exclusively.
/// </summary>
/// <param name="maxValue">Exclusive value</param>
/// <returns></returns>
public uint NextUInt(uint maxValue)
{
if(maxValue == 0)
throw new ArgumentException("maxValue must be greater than zero.");
return(uint) (Sample() * maxValue);
}
/// <summary>
/// Returns a random unsigned integer value.
/// </summary>
/// <param name="minValue">Inclusive value.</param>
/// <param name="maxValue">Exclusive value.</param>
/// <returns></returns>
public uint NextUInt(uint minValue, uint maxValue)
{
if(maxValue < minValue)
throw new ArgumentException("maxValue must be greater than or equal to minValue");
return(uint) (Sample() * (maxValue - minValue) + minValue);
}
/// <summary>
/// Returns a random long value.
/// </summary>
public long NextLong()
{
return(long) (Sample() * long.MaxValue);
}
/// <summary>
/// returns a long value between 0 and maxValue exclusively.
/// </summary>
/// <param name="maxValue">Exclusive value</param>
/// <returns></returns>
public long NextLong(long maxValue)
{
if(maxValue == 0)
throw new ArgumentException("maxValue must be greater than zero.");
return(long) (Sample() * maxValue);
}
/// <summary>
/// Returns a random long value.
/// </summary>
/// <param name="minValue">Inclusive value.</param>
/// <param name="maxValue">Exclusive value.</param>
/// <returns></returns>
public long NextLong(long minValue, long maxValue)
{
if(maxValue < minValue)
throw new ArgumentException("maxValue must be greater than or equal to minValue");
return(long) (Sample() * (maxValue - minValue) + minValue);
}
/// <summary>
/// Returns a random unsigned long value.
/// </summary>
public ulong NextULong()
{
return(ulong) (Sample() * ulong.MaxValue);
}
/// <summary>
/// returns a unsigned long value between 0 and maxValue exclusively.
/// </summary>
/// <param name="maxValue">Exclusive value</param>
/// <returns></returns>
public ulong NextULong(ulong maxValue)
{
if(maxValue == 0)
throw new ArgumentException("maxValue must be greater than zero.");
return(ulong) (Sample() * maxValue);
}
/// <summary>
/// Returns a random unsigned long value.
/// </summary>
/// <param name="minValue">Inclusive value.</param>
/// <param name="maxValue">Exclusive value.</param>
/// <returns></returns>
public ulong NextULong(ulong minValue, ulong maxValue)
{
if(maxValue < minValue)
throw new ArgumentException("maxValue must be greater than or equal to minValue");
return(ulong) (Sample() * (maxValue - minValue) + minValue);
}
/// <summary>
/// Returns a random big integer value.
/// </summary>
public BigInteger NextBigInteger(int BitLength = 128)
{
return BigSample(BitLength);
}
/// <summary>
/// Returns a random unsigned big integer value.
/// </summary>
public BigInteger NextBigUnsignedInteger(int BitLength = 128)
{
return BigUSample(BitLength);
}
/// <summary>
/// Returns a random big integer value.
/// </summary>
public BigInteger NextBigInteger(int MinBitLength, int MaxBitLength)
{
return BigSample(MinBitLength, MaxBitLength);
}
/// <summary>
/// Returns a random unsigned big integer value.
/// </summary>
public BigInteger NextBigUnsignedInteger(int MinBitLength, int MaxBitLength)
{
return BigUSample(MinBitLength, MaxBitLength);
}
/// <summary>
/// Returns a random big rational value.
/// </summary>
public BigRational NextBigRational(int BitLength = 128)
{
return new BigRational(BigSample(BitLength));
}
/// <summary>
/// Returns a random big rational value. With lower and upper bit limits.
/// </summary>
public BigRational NextBigRational(int MinBitLength, int MaxBitLength)
{
return new BigRational(NextBigInteger(MinBitLength, MaxBitLength), NextBigInteger(MinBitLength, MaxBitLength));
}
/// <summary>
/// Returns a random unsigned big rational value.
/// </summary>
public BigRational NextUnsignedBigRational(int BitLength = 128)
{
return new BigRational(BigUSample(BitLength));
}
/// <summary>
/// Returns a random unsigned big rational value. With lower and upper bit limits.
/// </summary>
public BigRational NextUnsignedBigRational(int MinBitLength, int MaxBitLength)
{
return new BigRational(NextBigUnsignedInteger(MinBitLength, MaxBitLength), NextBigUnsignedInteger(MinBitLength, MaxBitLength));
}
/// <summary>
/// Returns a random float value.
/// </summary>
/// <param name="minValue">Inclusive value.</param>
/// <param name="maxValue">Exclusive value.</param>
/// <returns></returns>
public float NextFloat(float minValue, float maxValue)
{
if(maxValue < minValue)
throw new ArgumentException("maxValue must be greater than or equal to minValue");
while(true)
{
var value = (float) (Sample() * (maxValue - minValue) + minValue);
if(!float.IsNaN(value) && !float.IsInfinity(value))
return value;
}
}
/// <summary>
/// Returns a random float value.
/// </summary>
public float NextFloat()
{
return(float) Sample();
}
/// <summary>
/// Returns a random double value.
/// </summary>
/// <param name="minValue">Inclusive value.</param>
/// <param name="maxValue">Exclusive value.</param>
/// <returns></returns>
public double NextDouble(double minValue, double maxValue)
{
if(maxValue < minValue)
throw new ArgumentException("maxValue must be greater than or equal to minValue");
while(true)
{
var value = Sample() * (maxValue - minValue) + minValue;
if(!double.IsNaN(value) && !double.IsInfinity(value))
return value;
}
}
/// <summary>
/// Returns a random double value.
/// </summary>
public double NextDouble()
{
return Sample();
}
/// <summary>
/// Returns a random decimal value.
/// </summary>
public decimal NextDecimal()
{
return new decimal(Next(), Next(), Next(), NextBool(), NextByte(0, 29));
}
/// <summary>
/// returns a decimal value between 0 and maxValue exclusively.
/// </summary>
/// <param name="maxValue">Exclusive value</param>
/// <returns></returns>
public decimal NextDecimal(decimal maxValue)
{
return NextDecimal() * maxValue;
}
/// <summary>
/// Returns a random decimal value.
/// </summary>
/// <param name="minValue">Inclusive value.</param>
/// <param name="maxValue">Exclusive value.</param>
/// <returns></returns>
public decimal NextDecimal(decimal minValue, decimal maxValue)
{
return NextDecimal() * (maxValue - minValue) + minValue;
}
/// <summary>
/// Returns a value that is greater than or equal to 0.0 and less than 1.0
/// </summary>
private unsafe double Sample()
{
var buf = new byte[8];
GetBytes(buf);
fixed(byte* ptr = buf)
{
return*(ulong*) ptr * DBi;
}
}
private BigInteger BigSample(int BitLength)
{
var buf = new byte[BitLength >> 3];
GetBytes(buf);
var val = new BigInteger(buf);
return val;
}
private BigInteger BigUSample(int BitLength)
{
BigInteger n;
var buf = new byte[BitLength >> 3];
do
{
GetBytes(buf);
n = new BigInteger(buf);
} while(n.Sign == -1);
return n;
}
private BigInteger BigSample(int MinBitLength, int MaxBitLength)
{
if(MinBitLength % 8 != 0)
throw new Exception("The Minimum Bit Length must be a multiple of 8.");
if(MaxBitLength % 8 != 0)
throw new Exception("The Maximum Bit Length must be a multiple of 8.");
if(MinBitLength < 8)
throw new Exception("The Minimum Bit Length must be at least 8.");
if(MinBitLength > MaxBitLength)
throw new Exception("Minimum Bit Length Exceeds Maximum Bit Length.");
int BitLength;
if(MinBitLength == MaxBitLength)
BitLength = MaxBitLength;
else
BitLength = NextUShort(1, ((MaxBitLength - MinBitLength) >> 3) + 1) << 3;
var byteLength = BitLength >> 3;
if(byteLength <= 0)
byteLength = 1;
var buf = new byte[byteLength];
GetBytes(buf);
var val = new BigInteger(buf);
return val;
}
private BigInteger BigUSample(int MinBitLength, int MaxBitLength)
{
if(MinBitLength % 8 != 0)
throw new Exception("The Minimum Bit Length must be a multiple of 8.");
if(MaxBitLength % 8 != 0)
throw new Exception("The Maximum Bit Length must be a multiple of 8.");
if(MinBitLength < 8)
throw new Exception("The Minimum Bit Length must be at least 8.");
if(MinBitLength > MaxBitLength)
throw new Exception("Minimum Bit Length Exceeds Maximum Bit Length.");
int BitLength;
if(MinBitLength == MaxBitLength)
BitLength = MaxBitLength;
else
BitLength = NextUShort(1, ((MaxBitLength - MinBitLength) >> 3) + 1) << 3;
var byteLength = BitLength >> 3;
if(byteLength <= 0)
byteLength = 1;
var buf = new byte[byteLength];
BigInteger n;
do
{
GetBytes(buf);
n = new BigInteger(buf);
} while(n.Sign == -1);
return n;
}
/// <inheritdoc />
/// <summary>
/// returns a byte array.
/// </summary>
/// <param name="data"></param>
public override void GetBytes(byte[] data)
{
crng.GetBytes(data);
}
/// <summary>
/// return a byte value.
/// </summary>
/// <returns></returns>
public byte GetNextByte()
{
var xbc = new byte[1];
crng.GetBytes(xbc);
return xbc[0];
}
/// <summary>
/// return a character value
/// </summary>
/// <returns></returns>
public char GetNextChar()
{
var xbc = new byte[1];
while(true)
{
crng.GetBytes(xbc);
var c = xbc[0];
if(c >= 32 && c <= 127)
return(char) c;
}
}
/// <summary>
/// returns a byte array of size.
/// </summary>
/// <param name="size"></param>
/// <returns></returns>
public byte[] GetNextByteArray(int size)
{
var ba = new byte[size];
crng.GetBytes(ba);
return ba;
}
/// <summary>
/// returns a character array of size
/// </summary>
/// <param name="size"></param>
/// <returns></returns>
public char[] GetNextCharArray(int size)
{
var xbc = new byte[1];
var ca = new char[size];
var ptr = 0;
do
{
crng.GetBytes(xbc);
var c = xbc[0];
if(c >= 32 && c <= 127)
ca[ptr++] = (char) c;
} while(ptr < size);
return ca;
}
/// <summary>
/// Returns a random string value.
/// </summary>
/// <param name="minValue">Inclusive value.</param>
/// <param name="maxValue">Exclusive value.</param>
/// <returns></returns>
public string GetRandomString(int minLen, int maxLen)
{
if(minLen == maxLen)
return new string(GetNextCharArray(minLen));
return new string(GetNextCharArray(Next(minLen, maxLen)));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment