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.
@@ -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
@@ -1,5 +1,5 @@
1
1
  module Crypt
2
2
  module Isaac
3
- VERSION = "1.0.0"
3
+ VERSION = "1.1.0"
4
4
  end
5
5
  end
@@ -0,0 +1,5 @@
1
+ begin
2
+ require 'crypt/isaac/xorshift/ext'
3
+ rescue LoadError
4
+ require 'crypt/isaac/xorshift/pure'
5
+ end
@@ -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.0.0
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: 2015-11-11 00:00:00.000000000 Z
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 cryptgraphically secure pseudorandom number generator. This
56
- is a Ruby implementation of the algorithm.
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.4.5.1
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: []