crypt-isaac 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|