Repository navigation
Expand file tree
/
Copy pathCryptoRandomRange.cs
More file actions
executable file
·59 lines (53 loc) · 2.03 KB
/
Copy pathCryptoRandomRange.cs
File metadata and controls
executable file
·59 lines (53 loc) · 2.03 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
using KeePassLib.Cryptography;
using KeePassLib.Cryptography.PasswordGenerator;
namespace Sequencer
{
/* This class exists to restrict the 64-bit random provided by the KeePass
* library to a range, without bias. Probably this should be built into
* KeePass...but it's not for now.
*
* Note, the naïve approach would be to do min + (rand % max), but if the
* maximum value of the random does not evenly divide by max, this will cause
* biases toward the smaller numbers.
*/
public class CryptoRandomRange
{
public CryptoRandomRange(CryptoRandomStream randStream)
{
this.BaseCryptoRandom = randStream;
}
/* returns a random number without bias from within a range */
public ulong GetRandomInRange(ulong min, ulong max)
{
if (min > max)
{
System.ArgumentException argEx =
new System.ArgumentException("Random number range: max smaller than min");
throw argEx;
}
else if (max == min)
{
/* Needed for init time because for some reason this function gets
* called before any actual limits are set up, or something, and max and
* min are both zero.
*/
return min;
}
ulong maxOffset = max - min;
ulong numIntervals = maxOffset+1;
ulong maxValid = System.UInt64.MaxValue - (System.UInt64.MaxValue % numIntervals);
ulong intervalSize = maxValid / numIntervals;
ulong trialNum;
/* keep trying random numbers until we get one within the range that won't
* causes biases
*/
do
{
trialNum = this.BaseCryptoRandom.GetRandomUInt64();
} while(trialNum > maxValid);
return min + (trialNum / intervalSize);
}
private CryptoRandomStream BaseCryptoRandom;
}
}
/* vim: set ts=4 sw=4 et: */