Created
February 21, 2019 15:35
-
-
Save mjs3339/ad9d8002d7102f557f316c0b538a6823 to your computer and use it in GitHub Desktop.
C# Crypto Random Number Generator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[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