pool_of_entropy 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Dependency Status](https://gemnasium.com/neilslater/pool_of_entropy.png)](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
|