crypt-isaac 1.0.0 → 1.1.0
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/README.md +46 -4
- data/Rakefile +9 -0
- data/crypt-isaac.gemspec +3 -2
- data/ext/crypt/isaac/Makefile +260 -0
- data/ext/crypt/isaac/extconf.rb +3 -0
- data/ext/crypt/isaac/isaac.c +232 -0
- data/ext/crypt/isaac/rand.c +142 -0
- data/ext/crypt/isaac/rand.h +56 -0
- data/ext/crypt/isaac/standard.h +57 -0
- data/ext/crypt/isaac/xorshift/extconf.rb +3 -0
- data/ext/crypt/isaac/xorshift/xorshift.c +121 -0
- data/lib/crypt/isaac.rb +14 -211
- data/lib/crypt/isaac/pure.rb +218 -0
- data/lib/crypt/isaac/version.rb +1 -1
- data/lib/crypt/isaac/xorshift.rb +5 -0
- data/lib/crypt/isaac/xorshift/pure.rb +47 -0
- metadata +23 -7
@@ -0,0 +1,218 @@
|
|
1
|
+
module Crypt
|
2
|
+
|
3
|
+
# ISAAC is a fast, cryptographically secure pseudo-random number generator.
|
4
|
+
# Details on the algorithm can be found here:
|
5
|
+
# http://burtleburtle.net/bob/rand/isaac.html
|
6
|
+
# This provides a consistent and capable algorithm for producing
|
7
|
+
# independent streams of quality random numbers.
|
8
|
+
|
9
|
+
class ISAAC
|
10
|
+
|
11
|
+
attr_accessor :randrsl, :randcnt
|
12
|
+
attr_accessor :mm, :aa, :bb, :cc
|
13
|
+
|
14
|
+
# When a Crypt::ISAAC object is created, it needs to be seeded for
|
15
|
+
# random number generation. If the system has a /dev/urandom file,
|
16
|
+
# that will be used to do the seeding by default. If false is explictly
|
17
|
+
# passed when creating the object, it will instead use /dev/random to
|
18
|
+
# generate its seeds. Be warned that this may make for SLOW
|
19
|
+
# initialization - if there isn't enough entropy in the system, reads from
|
20
|
+
# /dev/random will block while waiting for more entropy, causing
|
21
|
+
# initialization to wait, as well.
|
22
|
+
# If the requested source (/dev/urandom or /dev/random) do not exist,
|
23
|
+
# the system will fall back to a simplistic initialization mechanism
|
24
|
+
# using a pseudo-random number generator. By default, it will use an
|
25
|
+
# xorshift* generator, but anything that responds to #rand can be passed
|
26
|
+
# as a seed.
|
27
|
+
|
28
|
+
def initialize(seed = true)
|
29
|
+
@mm = []
|
30
|
+
|
31
|
+
self.srand( seed )
|
32
|
+
end
|
33
|
+
|
34
|
+
# If seeded with an integer, use that to seed a standard Ruby Mersenne Twister
|
35
|
+
# PRNG, and then use that to generate seed value for ISAAC. This is mostly useful
|
36
|
+
# for producing repeated, deterministic results, which may be needed for testing.
|
37
|
+
def srand(seed = true)
|
38
|
+
rnd_source = nil
|
39
|
+
rnd_source = seed ? '/dev/urandom' : '/dev/random' if ( ( seed == true ) || ( seed == false ) )
|
40
|
+
if rnd_source && ( FileTest.exist? rnd_source )
|
41
|
+
@randrsl = []
|
42
|
+
File.open( rnd_source, 'r' ) do |r|
|
43
|
+
256.times do |t|
|
44
|
+
z = r.read(4)
|
45
|
+
x = z.unpack('V')[0]
|
46
|
+
@randrsl[t] = x
|
47
|
+
end
|
48
|
+
end
|
49
|
+
randinit( true )
|
50
|
+
else
|
51
|
+
seed = nil if rnd_source
|
52
|
+
|
53
|
+
@randrsl = []
|
54
|
+
if seed.respond_to?( :rand )
|
55
|
+
seed_prng = seed
|
56
|
+
else
|
57
|
+
seed_prng = Crypt::Xorshift64Star.new( seed )
|
58
|
+
end
|
59
|
+
|
60
|
+
256.times do |t|
|
61
|
+
@randrsl[t] = seed_prng.rand(4294967296)
|
62
|
+
end
|
63
|
+
randinit(true)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Works just like the standard rand() function. If called with an
|
68
|
+
# integer argument, rand() will return positive random number in
|
69
|
+
# the range of 0 to (argument - 1). If called without an integer
|
70
|
+
# argument, rand() returns a positive floating point number less than 1.
|
71
|
+
# If called with a Range, returns a number that is in the range.
|
72
|
+
|
73
|
+
def rand(arg = nil)
|
74
|
+
if (@randcnt == 1)
|
75
|
+
isaac
|
76
|
+
@randcnt = 256
|
77
|
+
end
|
78
|
+
@randcnt -= 1
|
79
|
+
if arg.nil?
|
80
|
+
( @randrsl[@randcnt] / 536870912.0 ) % 1
|
81
|
+
elsif Integer === arg || Float === arg
|
82
|
+
@randrsl[@randcnt] % arg
|
83
|
+
elsif Range === arg
|
84
|
+
arg.min + @randrsl[@randcnt] % (arg.max - arg.min)
|
85
|
+
else
|
86
|
+
@randrsl[@randcnt] % Integer(arg)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def seed
|
91
|
+
@seed.respond_to?(:seed) ? @seed.seed : @seed
|
92
|
+
end
|
93
|
+
|
94
|
+
def state
|
95
|
+
@randrsl + [@randcnt]
|
96
|
+
end
|
97
|
+
|
98
|
+
def ==(gen)
|
99
|
+
self.state == gen.state
|
100
|
+
end
|
101
|
+
|
102
|
+
def bytes(size)
|
103
|
+
buffer = ""
|
104
|
+
( size / 4 ).times { buffer << [rand(4294967295)].pack("L").unpack("aaaa").join }
|
105
|
+
|
106
|
+
if size % 4 != 0
|
107
|
+
buffer << [rand(4294967295)].pack("L").unpack("aaaa")[0..(size % 4 - 1)].join
|
108
|
+
end
|
109
|
+
|
110
|
+
buffer
|
111
|
+
end
|
112
|
+
|
113
|
+
def isaac
|
114
|
+
i = 0
|
115
|
+
x = 0
|
116
|
+
y = 0
|
117
|
+
|
118
|
+
@cc += 1
|
119
|
+
@bb += @cc
|
120
|
+
@bb & 0xffffffff
|
121
|
+
|
122
|
+
while (i < 256) do
|
123
|
+
x = @mm[i]
|
124
|
+
@aa = (@mm[(i + 128) & 255] + (@aa^(@aa << 13)) ) & 0xffffffff
|
125
|
+
@mm[i] = y = (@mm[(x>>2)&255] + @aa + @bb ) & 0xffffffff
|
126
|
+
@randrsl[i] = @bb = (@mm[(y>>10)&255] + x ) & 0xffffffff
|
127
|
+
i += 1
|
128
|
+
|
129
|
+
x = @mm[i]
|
130
|
+
@aa = (@mm[(i+128)&255] + (@aa^(0x03ffffff & (@aa >> 6))) ) & 0xffffffff
|
131
|
+
@mm[i] = y = (@mm[(x>>2)&255] + @aa + @bb ) & 0xffffffff
|
132
|
+
@randrsl[i] = @bb = (@mm[(y>>10)&255] + x ) & 0xffffffff
|
133
|
+
i += 1
|
134
|
+
|
135
|
+
x = @mm[i]
|
136
|
+
@aa = (@mm[(i + 128)&255] + (@aa^(@aa << 2)) ) & 0xffffffff
|
137
|
+
@mm[i] = y = (@mm[(x>>2)&255] + @aa + @bb ) & 0xffffffff
|
138
|
+
@randrsl[i] = @bb = (@mm[(y>>10)&255] + x ) & 0xffffffff
|
139
|
+
i += 1
|
140
|
+
|
141
|
+
x = @mm[i]
|
142
|
+
@aa = (@mm[(i+128)&255] + (@aa^(0x0000ffff & (@aa >> 16))) ) & 0xffffffff
|
143
|
+
@mm[i] = y = (@mm[(x>>2)&255] + @aa + @bb ) & 0xffffffff
|
144
|
+
@randrsl[i] = @bb = (@mm[(y>>10)&255] + x ) & 0xffffffff
|
145
|
+
i += 1
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def randinit(flag)
|
150
|
+
i = 0
|
151
|
+
a = 0
|
152
|
+
b = 0
|
153
|
+
c = 0
|
154
|
+
d = 0
|
155
|
+
e = 0
|
156
|
+
f = 0
|
157
|
+
g = 0
|
158
|
+
@aa = @bb = @cc = 0
|
159
|
+
a = b = c = d = e = f = g = h = 0x9e3779b9
|
160
|
+
|
161
|
+
while (i < 4) do
|
162
|
+
a ^= b<<1; d += a; b += c
|
163
|
+
b ^= 0x3fffffff & (c>>2); e += b; c += d
|
164
|
+
c ^= d << 8; f += c; d += e
|
165
|
+
d ^= 0x0000ffff & (e >> 16); g += d; e += f
|
166
|
+
e ^= f << 10; h += e; f += g
|
167
|
+
f ^= 0x0fffffff & (g >> 4); a += f; g += h
|
168
|
+
g ^= h << 8; b += g; h += a
|
169
|
+
h ^= 0x007fffff & (a >> 9); c += h; a += b
|
170
|
+
i += 1
|
171
|
+
end
|
172
|
+
|
173
|
+
i = 0
|
174
|
+
while (i < 256) do
|
175
|
+
if (flag)
|
176
|
+
a+=@randrsl[i ].to_i; b+=@randrsl[i+1].to_i;
|
177
|
+
c+=@randrsl[i+2]; d+=@randrsl[i+3];
|
178
|
+
e+=@randrsl[i+4]; f+=@randrsl[i+5];
|
179
|
+
g+=@randrsl[i+6]; h+=@randrsl[i+7];
|
180
|
+
end
|
181
|
+
|
182
|
+
a^=b<<11; d+=a; b+=c;
|
183
|
+
b^=0x3fffffff & (c>>2); e+=b; c+=d;
|
184
|
+
c^=d<<8; f+=c; d+=e;
|
185
|
+
d^=0x0000ffff & (e>>16); g+=d; e+=f;
|
186
|
+
e^=f<<10; h+=e; f+=g;
|
187
|
+
f^=0x0fffffff & (g>>4); a+=f; g+=h;
|
188
|
+
g^=h<<8; b+=g; h+=a;
|
189
|
+
h^=0x007fffff & (a>>9); c+=h; a+=b;
|
190
|
+
@mm[i]=a;@mm[i+1]=b; @mm[i+2]=c; @mm[i+3]=d;
|
191
|
+
@mm[i+4]=e; @mm[i+5]=f; @mm[i+6]=g; @mm[i+7]=h;
|
192
|
+
i += 8
|
193
|
+
end
|
194
|
+
|
195
|
+
if flag
|
196
|
+
i = 0
|
197
|
+
while (i < 256)
|
198
|
+
a+=@mm[i ]; b+=@mm[i+1]; c+=@mm[i+2]; d+=@mm[i+3];
|
199
|
+
e+=@mm[i+4]; f+=@mm[i+5]; g+=@mm[i+6]; h+=@mm[i+7];
|
200
|
+
a^=b<<11; d+=a; b+=c;
|
201
|
+
b^=0x3fffffff & (c>>2); e+=b; c+=d;
|
202
|
+
c^=d<<8; f+=c; d+=e;
|
203
|
+
d^=0x0000ffff & (e>>16); g+=d; e+=f;
|
204
|
+
e^=f<<10; h+=e; f+=g;
|
205
|
+
f^=0x0fffffff & (g>>4); a+=f; g+=h;
|
206
|
+
g^=h<<8; b+=g; h+=a;
|
207
|
+
h^=0x007fffff & (a>>9); c+=h; a+=b;
|
208
|
+
@mm[i ]=a; @mm[i+1]=b; @mm[i+2]=c; @mm[i+3]=d;
|
209
|
+
@mm[i+4]=e; @mm[i+5]=f; @mm[i+6]=g; @mm[i+7]=h;
|
210
|
+
i += 8
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
isaac()
|
215
|
+
@randcnt=256; # /* prepare to use the first set of results */
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
data/lib/crypt/isaac/version.rb
CHANGED
@@ -0,0 +1,47 @@
|
|
1
|
+
# A pure Ruby micro-implementation. Use crypt-xorshift if you want a complete implementation.
|
2
|
+
|
3
|
+
module Crypt
|
4
|
+
class Xorshift64Star
|
5
|
+
|
6
|
+
UINT32_C = 2**32
|
7
|
+
UINT64_C = 2**64
|
8
|
+
UINT64_Cf = UINT64_C.to_f
|
9
|
+
|
10
|
+
def initialize( seed = new_seed )
|
11
|
+
srand( seed )
|
12
|
+
@old_seed = @seed
|
13
|
+
end
|
14
|
+
|
15
|
+
def new_seed
|
16
|
+
n = Time.now
|
17
|
+
@@counter ||= 0
|
18
|
+
@@counter += 1
|
19
|
+
[n.usec % 65536, n.to_i % 65536, $$ ^ 65536, @@counter % 65536 ].collect {|x| x.to_s(16)}.join.to_i(16)
|
20
|
+
end
|
21
|
+
|
22
|
+
def srand( seed = new_seed )
|
23
|
+
@old_seed = @seed
|
24
|
+
@seed = seed % UINT64_C
|
25
|
+
end
|
26
|
+
|
27
|
+
def rand( n = 0)
|
28
|
+
@seed ^= @seed >> 12
|
29
|
+
@seed ^= @seed << 25
|
30
|
+
@seed ^= @seed >> 27
|
31
|
+
if n < 1
|
32
|
+
( ( @seed * 2685821657736338717 ) % UINT64_C ) / UINT64_Cf
|
33
|
+
else
|
34
|
+
( ( @seed * 2685821657736338717 ) % UINT64_C ) % Integer( n )
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def seed
|
39
|
+
@old_seed
|
40
|
+
end
|
41
|
+
|
42
|
+
def ==(v)
|
43
|
+
self.class == v.class && @old_seed == v.seed
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: crypt-isaac
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kirk Haines
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-10-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -52,12 +52,17 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
-
description: ISAAC is a
|
56
|
-
|
55
|
+
description: 'ISAAC is a fast, cryptographically secure pseudo random number generator
|
56
|
+
with strong statistical properties. This gem provides both a pure Ruby and a C extension
|
57
|
+
based implementation which conforms to the Ruby 2 api for Random, with some enhancements.
|
58
|
+
So, you should be able to use it as a drop in replacement for Ruby''s (Mersenne
|
59
|
+
Twister based) PRNG. '
|
57
60
|
email:
|
58
61
|
- wyhaines@gmail.com
|
59
62
|
executables: []
|
60
|
-
extensions:
|
63
|
+
extensions:
|
64
|
+
- ext/crypt/isaac/xorshift/extconf.rb
|
65
|
+
- ext/crypt/isaac/extconf.rb
|
61
66
|
extra_rdoc_files: []
|
62
67
|
files:
|
63
68
|
- CODE_OF_CONDUCT.md
|
@@ -68,8 +73,19 @@ files:
|
|
68
73
|
- bin/console
|
69
74
|
- bin/setup
|
70
75
|
- crypt-isaac.gemspec
|
76
|
+
- ext/crypt/isaac/Makefile
|
77
|
+
- ext/crypt/isaac/extconf.rb
|
78
|
+
- ext/crypt/isaac/isaac.c
|
79
|
+
- ext/crypt/isaac/rand.c
|
80
|
+
- ext/crypt/isaac/rand.h
|
81
|
+
- ext/crypt/isaac/standard.h
|
82
|
+
- ext/crypt/isaac/xorshift/extconf.rb
|
83
|
+
- ext/crypt/isaac/xorshift/xorshift.c
|
71
84
|
- lib/crypt/isaac.rb
|
85
|
+
- lib/crypt/isaac/pure.rb
|
72
86
|
- lib/crypt/isaac/version.rb
|
87
|
+
- lib/crypt/isaac/xorshift.rb
|
88
|
+
- lib/crypt/isaac/xorshift/pure.rb
|
73
89
|
homepage: http://github.com/wyhaines/crypt-isaac
|
74
90
|
licenses:
|
75
91
|
- MIT
|
@@ -91,8 +107,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
91
107
|
version: '0'
|
92
108
|
requirements: []
|
93
109
|
rubyforge_project:
|
94
|
-
rubygems_version: 2.
|
110
|
+
rubygems_version: 2.5.1
|
95
111
|
signing_key:
|
96
112
|
specification_version: 4
|
97
|
-
summary: An implementation of the ISAAC PRNG
|
113
|
+
summary: An implementation of the fast, cryptographically secure ISAAC PRNG
|
98
114
|
test_files: []
|