-
-
Save codeyu/7d2171c304078bd4a4af0b63c51dfebe to your computer and use it in GitHub Desktop.
Cryptographically-strong random number generator in C#.
This file contains 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
// Cryptographically-strong random number generator | |
// Source: MSDN Magazine > 2007 > September > .NET Matters: Tales from the CryptoRandom | |
// Source URL: http://msdn.microsoft.com/en-us/magazine/cc163367.aspx | |
// Authors: Stephen Toub & Shawn Farkas | |
public class CryptoRandom : Random | |
{ | |
private RNGCryptoServiceProvider cryptoProvider = new RNGCryptoServiceProvider(); | |
private byte[] uint32Buffer = new byte[4]; | |
/// <summary> | |
/// An implementation of System.Random used for cryptographically-strong random number generation. | |
/// </summary> | |
public CryptoRandom() { } | |
/// <summary> | |
/// An implementation of System.Random used for cryptographically-strong random number generation. | |
/// </summary> | |
public CryptoRandom(Int32 seedIgnored) { } | |
/// <summary> | |
/// Returns a nonnegative random number. | |
/// </summary> | |
/// <returns> | |
/// A 32-bit signed integer greater than or equal to zero and less than <see cref="F:System.Int32.MaxValue"/>. | |
/// </returns> | |
public override Int32 Next() | |
{ | |
cryptoProvider.GetBytes(uint32Buffer); | |
return BitConverter.ToInt32(uint32Buffer, 0) & 0x7FFFFFFF; | |
} | |
/// <summary> | |
/// Returns a nonnegative random number less than the specified maximum. | |
/// </summary> | |
/// <returns> | |
/// A 32-bit signed integer greater than or equal to zero, and less than <paramref name="maxValue"/>; that is, the range of return values ordinarily includes zero but not <paramref name="maxValue"/>. However, if <paramref name="maxValue"/> equals zero, <paramref name="maxValue"/> is returned. | |
/// </returns> | |
/// <param name="maxValue">The exclusive upper bound of the random number to be generated. <paramref name="maxValue"/> must be greater than or equal to zero.</param> | |
/// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="maxValue"/> is less than zero.</exception> | |
public override Int32 Next(Int32 maxValue) | |
{ | |
if (maxValue < 0) throw new ArgumentOutOfRangeException("maxValue"); | |
return Next(0, maxValue); | |
} | |
/// <summary> | |
/// Returns a random number within a specified range. | |
/// </summary> | |
/// <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> | |
/// <param name="minValue">The inclusive lower bound of the random number returned.</param> | |
/// <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> | |
/// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="minValue"/> is greater than <paramref name="maxValue"/>.</exception> | |
public override Int32 Next(Int32 minValue, Int32 maxValue) | |
{ | |
if (minValue > maxValue) throw new ArgumentOutOfRangeException("minValue"); | |
if (minValue == maxValue) return minValue; | |
Int64 diff = maxValue - minValue; | |
while (true) | |
{ | |
cryptoProvider.GetBytes(uint32Buffer); | |
UInt32 rand = BitConverter.ToUInt32(uint32Buffer, 0); | |
Int64 max = (1 + (Int64)UInt32.MaxValue); | |
Int64 remainder = max % diff; | |
if (rand < max - remainder) | |
{ | |
return (Int32)(minValue + (rand % diff)); | |
} | |
} | |
} | |
/// <summary> | |
/// Returns a random number between 0.0 and 1.0. | |
/// </summary> | |
/// <returns> | |
/// A double-precision floating point number greater than or equal to 0.0, and less than 1.0. | |
/// </returns> | |
public override double NextDouble() | |
{ | |
cryptoProvider.GetBytes(uint32Buffer); | |
UInt32 rand = BitConverter.ToUInt32(uint32Buffer, 0); | |
return rand / (1.0 + UInt32.MaxValue); | |
} | |
/// <summary> | |
/// Fills the elements of a specified array of bytes with random numbers. | |
/// </summary> | |
/// <param name="buffer">An array of bytes to contain random numbers.</param> | |
/// <exception cref="T:System.ArgumentNullException"><paramref name="buffer"/> is null. | |
public override void NextBytes(byte[] buffer) | |
{ | |
if (buffer == null) throw new ArgumentNullException("buffer"); | |
cryptoProvider.GetBytes(buffer); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment