-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRNGExtensions.cs
More file actions
69 lines (61 loc) · 2.61 KB
/
RNGExtensions.cs
File metadata and controls
69 lines (61 loc) · 2.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
using System;
using System.Numerics;
using System.Security.Cryptography;
namespace MetalWorker.Cryptography
{
/// <summary>
/// Extensions for RandomNumberGenerator to easily create random BigIntegers
/// </summary>
public static class RandomNumberGeneratorExtensions
{
public static BigInteger NextBigInteger(this RandomNumberGenerator rng, BigInteger minValue, BigInteger maxValue)
{
return minValue + NextBigInteger(rng, maxValue - minValue);
}
public static BigInteger NextBigInteger(this RandomNumberGenerator rng, BigInteger bound)
{
//Get a byte buffer capable of holding any value below the bound
var buffer = (bound << 16).ToByteArray(); // << 16 adds two bytes, which decrease the chance of a retry later on
//Compute where the last partial fragment starts, in order to retry if we end up in it
var generatedValueBound = BigInteger.One << (buffer.Length * 8 - 1); //-1 accounts for the sign bit
var validityBound = generatedValueBound - generatedValueBound % bound;
while (true)
{
//generate a uniformly random value in [0, 2^(buffer.Length * 8 - 1))
rng.GetBytes(buffer);
buffer[buffer.Length - 1] &= 0x7F; //force sign bit to positive
var r = new BigInteger(buffer);
//return unless in the partial fragment
if (r >= validityBound) continue;
return r % bound;
}
}
public static BigInteger NextUnsignedBigInteger(this RandomNumberGenerator rng, uint bytesCount)
{
if (bytesCount == 0)
throw new ArgumentException();
var buffer = new byte[bytesCount];
rng.GetBytes(buffer);
buffer[buffer.Length - 1] &= 0x7F; //force sign bit to positive
return new BigInteger(buffer);
}
public static BigInteger NextUnsignedBigInteger(this RandomNumberGenerator rng, uint bytesCount, BigInteger min)
{
BigInteger result;
do
{
result = rng.NextUnsignedBigInteger(bytesCount);
} while (result < min);
return result;
}
public static BigInteger NextUnsignedBigInteger(this RandomNumberGenerator rng, uint bytesCount, BigInteger min, BigInteger max)
{
BigInteger result;
do
{
result = rng.NextUnsignedBigInteger(bytesCount);
} while (result < min || result > max);
return result;
}
}
}