pool_of_entropy 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.yardopts +2 -0
- data/RATIONALE.md +28 -8
- data/README.md +42 -10
- data/RECIPES.md +70 -0
- data/lib/pool_of_entropy/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9282759abb1c13fd70a45b27da5f58030107bc23
|
4
|
+
data.tar.gz: 88da59e58548d584b72df4640be40be61aef9b37
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b158c97ffc614e6f40c5f769812a5f1441877e96c429e525875639c18f3c1a6f8699341bf81c062981e7eac2a2e986120718029facdb8bfe135e5ad8fc140d7f
|
7
|
+
data.tar.gz: c68191705fce736800291804d24d30c46e74be13906cde6cae5e46983ae1afaeaeb6d72aa5b4e4cb72110b06d2d9751b32034c3e2424381378f13d8fdf08518a
|
data/.yardopts
CHANGED
data/RATIONALE.md
CHANGED
@@ -9,8 +9,8 @@ psuedo random data that has no discernable pattern.
|
|
9
9
|
|
10
10
|
Generators used for games also need another trait - they need to be unpredictable to the end users.
|
11
11
|
Often that is not strictly true in the academic sense, for example a well-informed user with enough
|
12
|
-
time and skill could predict the next output from Ruby's rand() method. However, when
|
13
|
-
|
12
|
+
time and skill could predict the next output from Ruby's rand() method. However, when your really
|
13
|
+
need secure numbers, you can use a Crytogaphically Secure PRNG (CSPRNG). Ruby's SecureRandom cannot
|
14
14
|
be predicted from outside the system. Part of how CSPRNGs achieve unpredicatbility is by collecting
|
15
15
|
entropy from sources within the computer - this might be timing of events from network cards and
|
16
16
|
keyboard presses, or by sampling from deliberately noisy circuits.
|
@@ -44,8 +44,8 @@ Truly unpredictable sources are also easy enough to find. They make themselves u
|
|
44
44
|
by collecting entropy from sources on the machines where they run, that no-one can predict.
|
45
45
|
|
46
46
|
However, there has been a cost to the user's agency. If I was playing a game
|
47
|
-
using one of these sources, even though it was fair in the sense that the outcomes
|
48
|
-
|
47
|
+
using one of these sources, even though it was fair in the sense that the outcomes were chosen
|
48
|
+
with equal chances, it gives me the same feeling as if another player was rolling all the dice.
|
49
49
|
In a role-playing game, it feels the same as if the DM was rolling all the dice. Now sometimes
|
50
50
|
and for some (many/most?) people that's OK. But other times, part of the fun is in rolling
|
51
51
|
the dice yourself. I would be happy rolling computer dice, but only if somehow it was
|
@@ -63,12 +63,32 @@ regular CSPRNGs used to protect your computer on the internet is how this "entro
|
|
63
63
|
In a secure system, entropy is sourced from multiple places - anywhere that data can be
|
64
64
|
gathered that an imagined attacker will have a hard time guessing the value. In PoolOfEntropy
|
65
65
|
this is subverted - the end user supplies any data they like, and the gem treats it
|
66
|
-
as
|
67
|
-
all (because you know
|
68
|
-
player in a dice game, it counts just fine.
|
66
|
+
as entropy. Technically, if you were an attacker, this would not be called entropy at
|
67
|
+
all (because you know the exact value) - however, to the machinery of the PRNG, or
|
68
|
+
to me as a fellow player in a dice game, it counts just fine.
|
69
69
|
|
70
70
|
By default PoolOfEntropy objects start off with some machine-collected entropy from SecureRandom
|
71
71
|
to avoid trivial attacks (of always using the dice in the exact same way). You could view this
|
72
72
|
as representing the environment or the die itself (all the scratches and imperfections that
|
73
73
|
you cannot control, and have no influence over). Or, under an honour system of not repeating
|
74
|
-
yourself you can switch off that default.
|
74
|
+
yourself you can switch off that default.
|
75
|
+
|
76
|
+
## What PoolOfEntropy Does Not Do: Superstition
|
77
|
+
|
78
|
+
PoolOfEntropy will happily eat any string data and use it to help generate random numbers. It
|
79
|
+
cannot tell, and therefore does not care, what the *meaning* of that data is. It cannot
|
80
|
+
tell what you wish for, it is not "lady luck" in code form.
|
81
|
+
|
82
|
+
Superstition is a natural human feeling. We blow on dice before throwing them to encourage results
|
83
|
+
that we want, we avoid saying things lest we "tempt fate", and perform a thousand other
|
84
|
+
minor rites in order to get supposed good luck. This is true even when intellectually we
|
85
|
+
understand that truly random events are unbiased and there is no predictable cause and effect.
|
86
|
+
You cannot be a "lucky person" in the sense that random number generators will somehow
|
87
|
+
favour you. But the feeling is persistent, it seems inherent to human nature.
|
88
|
+
|
89
|
+
You can bring superstition into your interactions with a computer PRNG; you may already do,
|
90
|
+
if you play any computer game that uses random numbers. In some ways this gem encourages that,
|
91
|
+
by giving you the ability to set things up with data that is meaningful for you. But bear
|
92
|
+
in mind, that like a well-rolled die, the computer doesn't understand or care. The difference
|
93
|
+
between PoolOfEntropy and most other PRNGs is supposed to be the difference between you
|
94
|
+
rolling a die and someone else rolling it for you.
|
data/README.md
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
[](https://gemnasium.com/neilslater/pool_of_entropy)
|
7
7
|
|
8
8
|
PoolOfEntropy is a pseudo random number generator (PRNG) based on secure hashes,
|
9
|
-
intended to bring back the feeling of 'personal
|
9
|
+
intended to bring back the feeling of 'personal agency' that some gamers may feel when rolling
|
10
10
|
their *own* dice. An instance of the PoolOfEntropy class could be assigned to a player, or
|
11
11
|
to each die in a game, and it can be influenced (similar to throwing a die differently), or
|
12
12
|
personalised by feeding in arbitrary data (e.g. a picture of the player, a favourite saying).
|
@@ -40,17 +40,40 @@ Or install it yourself as:
|
|
40
40
|
|
41
41
|
## Usage
|
42
42
|
|
43
|
-
Create a new generator:
|
43
|
+
### Create a new generator:
|
44
44
|
|
45
45
|
pool = PoolOfEntropy.new
|
46
46
|
|
47
|
-
|
47
|
+
Or
|
48
|
+
|
49
|
+
pool = PoolOfEntropy.new :size => 24
|
50
|
+
|
51
|
+
Or
|
52
|
+
|
53
|
+
pool = PoolOfEntropy.new :size => 24, :blank => true
|
54
|
+
|
55
|
+
The :size parameter sets the amount of randomness that the pool
|
56
|
+
can store, in multiples of 512 bits (or 64 bytes). The default
|
57
|
+
size of 1 is fastest, and has a good distribution of values
|
58
|
+
statistically. Larger pool sizes (up to 256) will calculate a
|
59
|
+
little slower, but can be used to buffer more entropy from
|
60
|
+
the #add_to_pool method.
|
61
|
+
|
62
|
+
Setting :blank to true starts the pool with the entire pool
|
63
|
+
zero, so that repeatedly using the generator in exactly the
|
64
|
+
same way will return the same values.
|
65
|
+
|
66
|
+
### Get a random number.
|
67
|
+
|
68
|
+
Not feeding the generator with any customisation
|
48
69
|
means it is completely deterministic based on current internal state. The
|
49
70
|
analogy here might be "trusting to Fate":
|
50
71
|
|
51
72
|
pool.rand( 20 )
|
52
73
|
|
53
|
-
Influence the next random number (but not any others).
|
74
|
+
### Influence the next random number (but not any others).
|
75
|
+
|
76
|
+
This is analogous to
|
54
77
|
shaking or throwing dice in a certain way. Only the next result from rand()
|
55
78
|
is affected:
|
56
79
|
|
@@ -64,7 +87,9 @@ is affected:
|
|
64
87
|
# we re-join the deterministic sequence of the PRNG:
|
65
88
|
pool.rand
|
66
89
|
|
67
|
-
Influence the next three random numbers.
|
90
|
+
### Influence the next three random numbers.
|
91
|
+
|
92
|
+
Data supplied to modify_next is
|
68
93
|
put in a queue, first in, first out:
|
69
94
|
|
70
95
|
pool.modify_next( 'Shake the die lots.' )
|
@@ -77,7 +102,9 @@ put in a queue, first in, first out:
|
|
77
102
|
|
78
103
|
pool.rand # . . . and back to main sequence
|
79
104
|
|
80
|
-
Influence all random numbers from this point forward.
|
105
|
+
### Influence all random numbers from this point forward.
|
106
|
+
|
107
|
+
This is analogous to
|
81
108
|
having a personal style of throwing dice, or perhaps a different environment
|
82
109
|
to throw them in.
|
83
110
|
|
@@ -90,7 +117,7 @@ to throw them in.
|
|
90
117
|
# The two modifier types "stack", and this is modified twice
|
91
118
|
pool.modify_next( 'And I really mean it!' ).rand( 20 )
|
92
119
|
|
93
|
-
Remove modfiers
|
120
|
+
### Remove modfiers.
|
94
121
|
|
95
122
|
# Just the "all" modifier
|
96
123
|
pool.modify_all( nil )
|
@@ -101,7 +128,9 @@ Remove modfiers:
|
|
101
128
|
# Re-set "next" and "all" modifiers
|
102
129
|
pool.clear_all_modifiers
|
103
130
|
|
104
|
-
Alter internal state of pool.
|
131
|
+
### Alter internal state of pool.
|
132
|
+
|
133
|
+
This mixes in any entropy in the supplied
|
105
134
|
data, and changes the deterministic sequence going forward. This is
|
106
135
|
analogous to long-term alterations to dice, the environment, or
|
107
136
|
person throwing the dice.
|
@@ -111,14 +140,17 @@ person throwing the dice.
|
|
111
140
|
All the inputs can be any length String, from any source. If the data
|
112
141
|
contains *any* "true randomness" (however you want to define it, and however
|
113
142
|
the String is formatted), then PoolOfEntropy
|
114
|
-
will process that (using SHA-512) into unbiased results.
|
143
|
+
will process that (using SHA-512) into unbiased results.
|
144
|
+
|
145
|
+
If you care
|
115
146
|
about your own source of randomness being more "important" than
|
116
|
-
the initial state of the PRNG
|
147
|
+
the initial state of the PRNG or its deterministic progression,
|
117
148
|
then make use of the modifiers and/or add data to the pool frequently.
|
118
149
|
|
119
150
|
## More information
|
120
151
|
|
121
152
|
* [Rationale](RATIONALE.md)
|
153
|
+
* [Recipes and Suggestions](RECIPES.md)
|
122
154
|
* [Dieharder test of statistical randomness](DIEHARDER_TEST.md)
|
123
155
|
|
124
156
|
## Contributing
|
data/RECIPES.md
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
# Uses for PoolOfEntropy
|
2
|
+
|
3
|
+
## DO NOT USE FOR: Monte-Carlo Simulations
|
4
|
+
|
5
|
+
Although PoolOfEntropy can be seeded for repeatable sequences, and produces random numbers of
|
6
|
+
suitable quality, it is a lot slower than other equally good options. Use Ruby's built in
|
7
|
+
rand() or the Random class instead.
|
8
|
+
|
9
|
+
## DO NOT USE FOR: Communications Security
|
10
|
+
|
11
|
+
Although PoolOfEntropy can produce numbers of suitable quality, and is based
|
12
|
+
on a secure hash design, it is not proven secure and is never likely to be. In
|
13
|
+
addition, it operates on the application level in a Ruby process, and direct access
|
14
|
+
to that process would allow it to be compromised very easily. Use SecureRandom
|
15
|
+
instead.
|
16
|
+
|
17
|
+
## Dice for Play-by-Mail
|
18
|
+
|
19
|
+
This was one of the original design goals for the gem. One problem with games
|
20
|
+
played where events happen offline is that random numbers may be required when
|
21
|
+
a player is not present. By assigning an instance of PoolOfEntropy to each
|
22
|
+
player, and letting the player provide data for modifiers or the pool, it
|
23
|
+
allows the game to simulate fair dice rolls, and for the players to have influenced
|
24
|
+
those rolls in advance. In a philosophical sense you could say the players
|
25
|
+
have rolled the dice themselves.
|
26
|
+
|
27
|
+
To create and use a pool for a player:
|
28
|
+
|
29
|
+
# Depending on how many dice rolls will be made offline, I recommend
|
30
|
+
# a largish pool here. This 4KB pool, if completely filled with
|
31
|
+
# quality random data for a player, could generate over 6500 rolls of a d20
|
32
|
+
# that you might consider to be "rolled by the player" (in the sense that
|
33
|
+
# an infinitely powerful machine that knew the initial state before user
|
34
|
+
# data was added would need to see the results from that many rolls before it
|
35
|
+
# could figure out what the new state was)
|
36
|
+
|
37
|
+
freds_entropy = PoolOfEntropy.new :size => 64
|
38
|
+
|
39
|
+
# Add Fred's data, assuming freds_input is an Array of Strings. Ideally you
|
40
|
+
# have at least same number of strings as :size param above. You can split
|
41
|
+
# large files into chunks for processing e.g. images or videos
|
42
|
+
|
43
|
+
freds_input.each do |data|
|
44
|
+
freds_entropy.add_to_pool( data )
|
45
|
+
end
|
46
|
+
|
47
|
+
# Save the pool for later use (example to file, but binary blob in database
|
48
|
+
# is also fine). Note you should encrypt this if players have access to the
|
49
|
+
# data and would know how to use PoolOfEntropy themselves.
|
50
|
+
|
51
|
+
File.open( 'fred.pool', 'wb' ) { |file| file.write Marshal.dump( freds_entropy ) }
|
52
|
+
|
53
|
+
# Open the pool up later to use it
|
54
|
+
|
55
|
+
freds_entropy = File.open( 'fred.pool', 'rb' ) { |file| Marshal.load( file.read ) }
|
56
|
+
|
57
|
+
# During the game, Fred rolls a die:
|
58
|
+
|
59
|
+
result = freds_entropy.rand( 20 ) + 1
|
60
|
+
|
61
|
+
The gem games_dice will accept a PoolOfEntropy object as a generator for a dice object:
|
62
|
+
|
63
|
+
require 'games_dice'
|
64
|
+
|
65
|
+
freds_attack = GamesDice.create '1d20 + 6', freds_entropy
|
66
|
+
|
67
|
+
freds_attack.roll
|
68
|
+
# => 21
|
69
|
+
freds_attack.explain_result
|
70
|
+
# => "1d20: 15. 15 + 6 = 21"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pool_of_entropy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Neil Slater
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-05-
|
11
|
+
date: 2014-05-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: yard
|
@@ -97,6 +97,7 @@ files:
|
|
97
97
|
- LICENSE.txt
|
98
98
|
- RATIONALE.md
|
99
99
|
- README.md
|
100
|
+
- RECIPES.md
|
100
101
|
- Rakefile
|
101
102
|
- lib/pool_of_entropy.rb
|
102
103
|
- lib/pool_of_entropy/core_prng.rb
|