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.
@@ -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: []