Class: Crypt::ISAAC
- Inherits:
-
Object
- Object
- Crypt::ISAAC
- Defined in:
- lib/crypt/isaac/pure.rb,
ext/crypt/isaac/isaac.c
Overview
ISAAC is a fast, cryptographically secure pseudo-random number generator. Details on the algorithm can be found here: burtleburtle.net/bob/rand/isaac.html This provides a consistent and capable algorithm for producing independent streams of quality random numbers.
Constant Summary collapse
- DEFAULT =
ISAAC.new
Instance Attribute Summary collapse
-
#aa ⇒ Object
Returns the value of attribute aa.
-
#bb ⇒ Object
Returns the value of attribute bb.
-
#cc ⇒ Object
Returns the value of attribute cc.
-
#mm ⇒ Object
Returns the value of attribute mm.
-
#randcnt ⇒ Object
Returns the value of attribute randcnt.
-
#randrsl ⇒ Object
Returns the value of attribute randrsl.
Class Method Summary collapse
- .new_seed(args) ⇒ Object
-
.rand(args) ⇒ Object
When a Crypt::ISAAC object is created, it needs to be seeded for random number generation.
- .srand(args) ⇒ Object
Instance Method Summary collapse
- #==(v) ⇒ Object
- #bytes(count) ⇒ Object
-
#initialize(args) ⇒ ISAAC
constructor
A new instance of ISAAC.
- #initialize_copy(from) ⇒ Object
- #isaac ⇒ Object
-
#rand(args) ⇒ Object
Works just like the standard rand() function.
- #randinit(flag) ⇒ Object
- #seed ⇒ Object
-
#srand(args) ⇒ Object
If seeded with an integer, use that to seed a standard Ruby Mersenne Twister PRNG, and then use that to generate seed value for ISAAC.
- #state ⇒ Object
Constructor Details
#initialize(args) ⇒ ISAAC
Returns a new instance of ISAAC.
84 85 86 87 88 |
# File 'ext/crypt/isaac/isaac.c', line 84 def initialize(seed = true) @mm = [] self.srand( seed ) end |
Instance Attribute Details
#aa ⇒ Object
Returns the value of attribute aa.
12 13 14 |
# File 'lib/crypt/isaac/pure.rb', line 12 def aa @aa end |
#bb ⇒ Object
Returns the value of attribute bb.
12 13 14 |
# File 'lib/crypt/isaac/pure.rb', line 12 def bb @bb end |
#cc ⇒ Object
Returns the value of attribute cc.
12 13 14 |
# File 'lib/crypt/isaac/pure.rb', line 12 def cc @cc end |
#mm ⇒ Object
Returns the value of attribute mm.
12 13 14 |
# File 'lib/crypt/isaac/pure.rb', line 12 def mm @mm end |
#randcnt ⇒ Object
Returns the value of attribute randcnt.
11 12 13 |
# File 'lib/crypt/isaac/pure.rb', line 11 def randcnt @randcnt end |
#randrsl ⇒ Object
Returns the value of attribute randrsl.
11 12 13 |
# File 'lib/crypt/isaac/pure.rb', line 11 def randrsl @randrsl end |
Class Method Details
.new_seed(args) ⇒ Object
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'ext/crypt/isaac/isaac.c', line 8 def self.new_seed( seed = true ) seed_array = Array.new( 256, 0) rnd_source = nil rnd_source = seed ? '/dev/urandom' : '/dev/random' if ( ( seed == true ) || ( seed == false ) ) if ( seed.respond_to?(:each) ) ( seed.length > 255 ? 256 : seed.length ).times {|s| seed_array[s] = seed[s] } elsif rnd_source && ( FileTest.exist? rnd_source ) File.open( rnd_source, 'r' ) do |r| 256.times do |t| z = r.read(4) x = z.unpack('V')[0] seed_array[t] = x end end else seed = nil if rnd_source if seed.respond_to?( :rand ) seed_prng = seed else seed_prng = Crypt::Xorshift64Star.new( seed ) end 256.times do |t| seed_array[t] = seed_prng.rand(4294967296) end end seed_array end |
.rand(args) ⇒ Object
When a Crypt::ISAAC object is created, it needs to be seeded for random number generation. If the system has a /dev/urandom file, that will be used to do the seeding by default. If false is explictly passed when creating the object, it will instead use /dev/random to generate its seeds. Be warned that this may make for SLOW initialization - if there isn’t enough entropy in the system, reads from /dev/random will block while waiting for more entropy, causing initialization to wait, as well. If the requested source (/dev/urandom or /dev/random) do not exist, the system will fall back to a simplistic initialization mechanism using a pseudo-random number generator. By default, it will use an xorshift* generator, but anything that responds to #rand can be passed as a seed.
28 29 30 |
# File 'lib/crypt/isaac/pure.rb', line 28 def self.rand( arg = nil ) DEFAULT.rand( arg ) end |
.srand(args) ⇒ Object
146 147 148 |
# File 'ext/crypt/isaac/isaac.c', line 146 def self.srand( seed = true ) DEFAULT.srand( seed ) end |
Instance Method Details
#==(v) ⇒ Object
240 241 242 |
# File 'ext/crypt/isaac/isaac.c', line 240 def ==(gen) self.state == gen.state end |
#bytes(count) ⇒ Object
250 251 252 253 254 255 256 257 258 259 |
# File 'ext/crypt/isaac/isaac.c', line 250 def bytes(size) buffer = "" ( size / 4 ).times { buffer << [rand(4294967295)].pack("L").unpack("aaaa").join } if size % 4 != 0 buffer << [rand(4294967295)].pack("L").unpack("aaaa")[0..(size % 4 - 1)].join end buffer end |
#initialize_copy(from) ⇒ Object
98 99 100 101 102 103 104 105 106 107 |
# File 'ext/crypt/isaac/isaac.c', line 98 def initialize_copy( from ) @aa = from.aa @bb = from.bb @cc = from.cc @mm = from.mm.dup @randcnt = from.randcnt @randrsl = from.randrsl.dup self end |
#isaac ⇒ Object
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/crypt/isaac/pure.rb', line 139 def isaac i = 0 x = 0 y = 0 @cc += 1 @bb += @cc @bb = @bb & 0xffffffff while (i < 256) do x = @mm[i] @aa = (@mm[(i + 128) & 255] + (@aa^(@aa << 13)) ) & 0xffffffff @mm[i] = y = (@mm[(x>>2)&255] + @aa + @bb ) & 0xffffffff @randrsl[i] = @bb = (@mm[(y>>10)&255] + x ) & 0xffffffff i += 1 x = @mm[i] @aa = (@mm[(i+128)&255] + (@aa^(0x03ffffff & (@aa >> 6))) ) & 0xffffffff @mm[i] = y = (@mm[(x>>2)&255] + @aa + @bb ) & 0xffffffff @randrsl[i] = @bb = (@mm[(y>>10)&255] + x ) & 0xffffffff i += 1 x = @mm[i] @aa = (@mm[(i + 128)&255] + (@aa^(@aa << 2)) ) & 0xffffffff @mm[i] = y = (@mm[(x>>2)&255] + @aa + @bb ) & 0xffffffff @randrsl[i] = @bb = (@mm[(y>>10)&255] + x ) & 0xffffffff i += 1 x = @mm[i] @aa = (@mm[(i+128)&255] + (@aa^(0x0000ffff & (@aa >> 16))) ) & 0xffffffff @mm[i] = y = (@mm[(x>>2)&255] + @aa + @bb ) & 0xffffffff @randrsl[i] = @bb = (@mm[(y>>10)&255] + x ) & 0xffffffff i += 1 end end |
#rand(args) ⇒ Object
Works just like the standard rand() function. If called with an integer argument, rand() will return positive random number in the range of 0 to (argument - 1). If called without an integer argument, rand() returns a positive floating point number less than 1. If called with a Range, returns a number that is in the range.
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/crypt/isaac/pure.rb', line 99 def rand(arg = nil) if (@randcnt == 1) isaac @randcnt = 256 end @randcnt -= 1 if arg.nil? ( @randrsl[@randcnt] / 536870912.0 ) % 1 elsif Integer === arg @randrsl[@randcnt] % arg elsif Range === arg arg.min + @randrsl[@randcnt] % (arg.max - arg.min) else @randrsl[@randcnt] % arg.to_i end end |
#randinit(flag) ⇒ Object
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 |
# File 'lib/crypt/isaac/pure.rb', line 175 def randinit(flag) i = 0 a = 0 b = 0 c = 0 d = 0 e = 0 f = 0 g = 0 @aa = @bb = @cc = 0 a = b = c = d = e = f = g = h = 0x9e3779b9 while (i < 4) do a ^= b<<1; d += a; b += c b ^= 0x3fffffff & (c>>2); e += b; c += d c ^= d << 8; f += c; d += e d ^= 0x0000ffff & (e >> 16); g += d; e += f e ^= f << 10; h += e; f += g f ^= 0x0fffffff & (g >> 4); a += f; g += h g ^= h << 8; b += g; h += a h ^= 0x007fffff & (a >> 9); c += h; a += b i += 1 end i = 0 while (i < 256) do if (flag) a+=@randrsl[i ].to_i; b+=@randrsl[i+1].to_i; c+=@randrsl[i+2]; d+=@randrsl[i+3]; e+=@randrsl[i+4]; f+=@randrsl[i+5]; g+=@randrsl[i+6]; h+=@randrsl[i+7]; end a^=b<<11; d+=a; b+=c; b^=0x3fffffff & (c>>2); e+=b; c+=d; c^=d<<8; f+=c; d+=e; d^=0x0000ffff & (e>>16); g+=d; e+=f; e^=f<<10; h+=e; f+=g; f^=0x0fffffff & (g>>4); a+=f; g+=h; g^=h<<8; b+=g; h+=a; h^=0x007fffff & (a>>9); c+=h; a+=b; @mm[i]=a;@mm[i+1]=b; @mm[i+2]=c; @mm[i+3]=d; @mm[i+4]=e; @mm[i+5]=f; @mm[i+6]=g; @mm[i+7]=h; i += 8 end if flag i = 0 while (i < 256) a+=@mm[i ]; b+=@mm[i+1]; c+=@mm[i+2]; d+=@mm[i+3]; e+=@mm[i+4]; f+=@mm[i+5]; g+=@mm[i+6]; h+=@mm[i+7]; a^=b<<11; d+=a; b+=c; b^=0x3fffffff & (c>>2); e+=b; c+=d; c^=d<<8; f+=c; d+=e; d^=0x0000ffff & (e>>16); g+=d; e+=f; e^=f<<10; h+=e; f+=g; f^=0x0fffffff & (g>>4); a+=f; g+=h; g^=h<<8; b+=g; h+=a; h^=0x007fffff & (a>>9); c+=h; a+=b; @mm[i ]=a; @mm[i+1]=b; @mm[i+2]=c; @mm[i+3]=d; @mm[i+4]=e; @mm[i+5]=f; @mm[i+6]=g; @mm[i+7]=h; i += 8 end end isaac() @randcnt=256; # /* prepare to use the first set of results */ end |
#seed ⇒ Object
226 227 228 |
# File 'ext/crypt/isaac/isaac.c', line 226 def seed @seed end |
#srand(args) ⇒ Object
If seeded with an integer, use that to seed a standard Ruby Mersenne Twister PRNG, and then use that to generate seed value for ISAAC. This is mostly useful for producing repeated, deterministic results, which may be needed for testing.
86 87 88 89 90 91 |
# File 'lib/crypt/isaac/pure.rb', line 86 def srand(seed = true) @randrsl = self.class.new_seed( seed ) @seed = @randrsl.dup randinit(true) @seed end |
#state ⇒ Object
120 121 122 |
# File 'lib/crypt/isaac/pure.rb', line 120 def state @randrsl + [@randcnt] end |