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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 32721d59c293f47c17f554ec6d614a3dd6d9c223
|
4
|
+
data.tar.gz: 3b0bf2597824aa9e730ee2d314e96fbe028d489f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b43a59b1dffaf4f1326081fe7b4f935ad4ecb478c17e23d8f637d8e03f2d9a7166964f750eb93953e298ecb0d57754d0ad98d2524c316f0d20d09b2d0d66e7db
|
7
|
+
data.tar.gz: 9313d7ac00934839290713cef9b2c6a5cb13da38b1c21eaf7a0bfc5f4838860777516c8416f086fb7ec0d05c83d99c75f60cd27b3bd5319f47c11137f2d3b803
|
data/README.md
CHANGED
@@ -4,11 +4,25 @@ ISAAC is a cryptographically secure PRNG for generating high quality random numb
|
|
4
4
|
|
5
5
|
http://burtleburtle.net/bob/rand/isaac.html
|
6
6
|
|
7
|
-
This
|
7
|
+
This library combines a pure Ruby implementation with a C implementation bound to ruby as an extension. The C extension implementation currently runs many times faster than the pure ruby implementation.
|
8
8
|
|
9
|
-
When originally written, running on Ruby 1.8.2 under a venerable 800Mhz PIII Linux system, it could do 15000 to 16000 numbers per second. On Ruby 2.
|
9
|
+
When originally written, running on Ruby 1.8.2 under a venerable 800Mhz PIII Linux system, it could do 15000 to 16000 numbers per second. On Ruby 2.3.1, testing via an Ubuntu shell session on a Windows 10 system running a 2.3Ghz Intel i5 processor, the library will generate over ten million floats per second, or almost nine million integers per second:
|
10
10
|
|
11
|
-
|
11
|
+
```
|
12
|
+
Benchmark integer prng generation
|
13
|
+
user system total real
|
14
|
+
1.130000 0.000000 1.130000 ( 1.138785)
|
15
|
+
10000000 numbers generated in 1.1393164 seconds; 8777193 per second
|
16
|
+
|
17
|
+
Benchmark float prng generation
|
18
|
+
user system total real
|
19
|
+
0.950000 0.000000 0.950000 ( 0.967220)
|
20
|
+
10000000 numbers generated in 0.967398 seconds; 10337007 per second
|
21
|
+
```
|
22
|
+
|
23
|
+
Ruby uses the Mersenne Twister as its PRNG. This algorithm is used by many languages because it is relatively fast, and has a long period. It, however, is not cryptographically strong; observing a window of as few as 624 generated values is enough to establish the state of the generator and to predict all future numbers. Nor is it well suited to Monte Carlo type simulations unless the seeds are quite different (generators with similar keys tend to produce number sequences that are the same for quite a long time before diverging), and the generators are ran for a while to ensure strong divergence.
|
24
|
+
|
25
|
+
ISAAC is very fast. This implementation is currently very comparable to Random's performance for both floats and for integers. ISAAC has strong statistical properties, like the Mersenne Twister, but it is also cryptographically strong, and different generators produce completely unique streams of numbers, even if seeded with similar seeds (though the seed size is substantial, so good seeding should make it difficult for two generators to be similarly seeded).
|
12
26
|
|
13
27
|
## Installation
|
14
28
|
|
@@ -31,9 +45,35 @@ Or install it yourself as:
|
|
31
45
|
```ruby
|
32
46
|
require 'crypt/isaac'
|
33
47
|
|
34
|
-
rng = Crypt::ISAAC.new
|
48
|
+
rng = Crypt::ISAAC.new
|
49
|
+
```
|
50
|
+
ISAAC will seed itself, by default, using /dev/urandom, if the device exists on the system being used. This is the same as:
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
rng = Crypt::ISAAC.new( true )
|
54
|
+
```
|
55
|
+
|
56
|
+
If one wants to use /dev/random instead (though there is really no reason to do so), pass false instead:
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
rng = Crypt::ISAAC.new( false )
|
60
|
+
```
|
61
|
+
|
62
|
+
If /dev/urandom is not available, or nil is specifically passed, then Crypt::ISAAC will use Crypt::Xorshift, if it is installed, or a bundled microimplementation of Crypt::Xorshift64Star to generate a series of high quality pseudorandom numbers which will in turn be used to seed the ISAAC generator, as it produces better streams of numbers than the Mersenne Twister, in a very simple implementation.
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
rng = Crypt::ISAAC.new( nil )
|
66
|
+
```
|
67
|
+
|
68
|
+
Finally, ISAAC may be seeded deterministically by passing an integer seed into it. Any ISAAC generator seeded with the same value will produce the same sequence of random numbers.
|
69
|
+
|
70
|
+
```ruby
|
35
71
|
rng = Crypt::ISAAC.new(17773845992) # New ISAAC object, seeded from a deterministic point.
|
72
|
+
```
|
73
|
+
|
74
|
+
TODO: One should be able to seed an ISAAC PRNG with an array of seed values, as well.
|
36
75
|
|
76
|
+
```ruby
|
37
77
|
r1 = rng.rand() # returns a floating point number between 0 and 1
|
38
78
|
r2 = rng.rand(10.57) # returns a floating point number between 0 and 10.57
|
39
79
|
r2 = rnd.rand(1000) # returns an integer between 0 and 999
|
@@ -43,6 +83,8 @@ noise = rng.bytes(1024) # return a 1k string of random bytes
|
|
43
83
|
|
44
84
|
Crypt::ISAAC should provide the same API as the Ruby 2.2 version of Random.
|
45
85
|
|
86
|
+
This implementation returns 32 bit values. TODO is to add support for the 64 bit version of ISAAC.
|
87
|
+
|
46
88
|
Enjoy it. Let me know if you find anything that can be improved or that
|
47
89
|
needs to be fixed.
|
48
90
|
|
data/Rakefile
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
2
|
require "rake/testtask"
|
3
|
+
require "rake/extensiontask"
|
4
|
+
|
5
|
+
Rake::ExtensionTask.new "isaac" do |ext|
|
6
|
+
ext.lib_dir = "lib/crypt/"
|
7
|
+
end
|
8
|
+
|
9
|
+
Rake::ExtensionTask.new "xorshift" do |ext|
|
10
|
+
ext.lib_dir = "lib/crypt/xorshift"
|
11
|
+
end
|
3
12
|
|
4
13
|
Rake::TestTask.new(:test) do |t|
|
5
14
|
t.libs << "test"
|
data/crypt-isaac.gemspec
CHANGED
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["Kirk Haines"]
|
10
10
|
spec.email = ["wyhaines@gmail.com"]
|
11
11
|
|
12
|
-
spec.summary = %q{An implementation of the ISAAC PRNG}
|
13
|
-
spec.description = %q{ISAAC is a
|
12
|
+
spec.summary = %q{An implementation of the fast, cryptographically secure ISAAC PRNG}
|
13
|
+
spec.description = %q{ISAAC is a fast, cryptographically secure pseudo random number generator with strong statistical properties. This gem provides both a pure Ruby and a C extension based implementation which conforms to the Ruby 2 api for Random, with some enhancements. So, you should be able to use it as a drop in replacement for Ruby's (Mersenne Twister based) PRNG. }
|
14
14
|
spec.homepage = "http://github.com/wyhaines/crypt-isaac"
|
15
15
|
spec.license = "MIT"
|
16
16
|
|
@@ -25,6 +25,7 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
26
26
|
spec.bindir = "exe"
|
27
27
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
|
+
spec.extensions = %w[ext/crypt/isaac/xorshift/extconf.rb ext/crypt/isaac/extconf.rb]
|
28
29
|
spec.require_paths = ["lib"]
|
29
30
|
|
30
31
|
spec.add_development_dependency "bundler", "~> 1.10"
|
@@ -0,0 +1,260 @@
|
|
1
|
+
|
2
|
+
SHELL = /bin/sh
|
3
|
+
|
4
|
+
# V=0 quiet, V=1 verbose. other values don't work.
|
5
|
+
V = 0
|
6
|
+
Q1 = $(V:1=)
|
7
|
+
Q = $(Q1:0=@)
|
8
|
+
ECHO1 = $(V:1=@:)
|
9
|
+
ECHO = $(ECHO1:0=@echo)
|
10
|
+
NULLCMD = :
|
11
|
+
|
12
|
+
#### Start of system configuration section. ####
|
13
|
+
|
14
|
+
srcdir = .
|
15
|
+
topdir = /home/wyhaines/.rvm/rubies/ruby-2.3.1/include/ruby-2.3.0
|
16
|
+
hdrdir = $(topdir)
|
17
|
+
arch_hdrdir = /home/wyhaines/.rvm/rubies/ruby-2.3.1/include/ruby-2.3.0/x86_64-linux
|
18
|
+
PATH_SEPARATOR = :
|
19
|
+
VPATH = $(srcdir):$(arch_hdrdir)/ruby:$(hdrdir)/ruby
|
20
|
+
prefix = $(DESTDIR)/home/wyhaines/.rvm/rubies/ruby-2.3.1
|
21
|
+
rubysitearchprefix = $(rubylibprefix)/$(sitearch)
|
22
|
+
rubyarchprefix = $(rubylibprefix)/$(arch)
|
23
|
+
rubylibprefix = $(libdir)/$(RUBY_BASE_NAME)
|
24
|
+
exec_prefix = $(prefix)
|
25
|
+
vendorarchhdrdir = $(vendorhdrdir)/$(sitearch)
|
26
|
+
sitearchhdrdir = $(sitehdrdir)/$(sitearch)
|
27
|
+
rubyarchhdrdir = $(rubyhdrdir)/$(arch)
|
28
|
+
vendorhdrdir = $(rubyhdrdir)/vendor_ruby
|
29
|
+
sitehdrdir = $(rubyhdrdir)/site_ruby
|
30
|
+
rubyhdrdir = $(includedir)/$(RUBY_VERSION_NAME)
|
31
|
+
vendorarchdir = $(vendorlibdir)/$(sitearch)
|
32
|
+
vendorlibdir = $(vendordir)/$(ruby_version)
|
33
|
+
vendordir = $(rubylibprefix)/vendor_ruby
|
34
|
+
sitearchdir = $(sitelibdir)/$(sitearch)
|
35
|
+
sitelibdir = $(sitedir)/$(ruby_version)
|
36
|
+
sitedir = $(rubylibprefix)/site_ruby
|
37
|
+
rubyarchdir = $(rubylibdir)/$(arch)
|
38
|
+
rubylibdir = $(rubylibprefix)/$(ruby_version)
|
39
|
+
sitearchincludedir = $(includedir)/$(sitearch)
|
40
|
+
archincludedir = $(includedir)/$(arch)
|
41
|
+
sitearchlibdir = $(libdir)/$(sitearch)
|
42
|
+
archlibdir = $(libdir)/$(arch)
|
43
|
+
ridir = $(datarootdir)/$(RI_BASE_NAME)
|
44
|
+
mandir = $(datarootdir)/man
|
45
|
+
localedir = $(datarootdir)/locale
|
46
|
+
libdir = $(exec_prefix)/lib
|
47
|
+
psdir = $(docdir)
|
48
|
+
pdfdir = $(docdir)
|
49
|
+
dvidir = $(docdir)
|
50
|
+
htmldir = $(docdir)
|
51
|
+
infodir = $(datarootdir)/info
|
52
|
+
docdir = $(datarootdir)/doc/$(PACKAGE)
|
53
|
+
oldincludedir = $(DESTDIR)/usr/include
|
54
|
+
includedir = $(prefix)/include
|
55
|
+
localstatedir = $(prefix)/var
|
56
|
+
sharedstatedir = $(prefix)/com
|
57
|
+
sysconfdir = $(DESTDIR)/etc
|
58
|
+
datadir = $(datarootdir)
|
59
|
+
datarootdir = $(prefix)/share
|
60
|
+
libexecdir = $(exec_prefix)/libexec
|
61
|
+
sbindir = $(exec_prefix)/sbin
|
62
|
+
bindir = $(exec_prefix)/bin
|
63
|
+
archdir = $(rubyarchdir)
|
64
|
+
|
65
|
+
|
66
|
+
CC = gcc
|
67
|
+
CXX = g++
|
68
|
+
LIBRUBY = $(LIBRUBY_SO)
|
69
|
+
LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
|
70
|
+
LIBRUBYARG_SHARED = -Wl,-rpath,'$${ORIGIN}/../lib' -Wl,-R'$${ORIGIN}/../lib' -l$(RUBY_SO_NAME)
|
71
|
+
LIBRUBYARG_STATIC = -Wl,-rpath,'$${ORIGIN}/../lib' -Wl,-R'$${ORIGIN}/../lib' -l$(RUBY_SO_NAME)-static
|
72
|
+
empty =
|
73
|
+
OUTFLAG = -o $(empty)
|
74
|
+
COUTFLAG = -o $(empty)
|
75
|
+
|
76
|
+
RUBY_EXTCONF_H =
|
77
|
+
cflags = $(optflags) $(debugflags) $(warnflags)
|
78
|
+
cxxflags = $(optflags) $(debugflags) $(warnflags)
|
79
|
+
optflags = -O3 -fno-fast-math
|
80
|
+
debugflags = -ggdb3
|
81
|
+
warnflags = -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wunused-variable -Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Wimplicit-function-declaration -Wdeprecated-declarations -Wno-packed-bitfield-compat
|
82
|
+
CCDLFLAGS = -fPIC
|
83
|
+
CFLAGS = $(CCDLFLAGS) $(cflags) -fPIC $(ARCH_FLAG)
|
84
|
+
INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir)/ruby/backward -I$(hdrdir) -I$(srcdir)
|
85
|
+
DEFS =
|
86
|
+
CPPFLAGS = $(DEFS) $(cppflags)
|
87
|
+
CXXFLAGS = $(CCDLFLAGS) $(cxxflags) $(ARCH_FLAG)
|
88
|
+
ldflags = -L. -fstack-protector -rdynamic -Wl,-export-dynamic
|
89
|
+
dldflags =
|
90
|
+
ARCH_FLAG =
|
91
|
+
DLDFLAGS = $(ldflags) $(dldflags) $(ARCH_FLAG)
|
92
|
+
LDSHARED = $(CC) -shared
|
93
|
+
LDSHAREDXX = $(CXX) -shared
|
94
|
+
AR = ar
|
95
|
+
EXEEXT =
|
96
|
+
|
97
|
+
RUBY_INSTALL_NAME = $(RUBY_BASE_NAME)
|
98
|
+
RUBY_SO_NAME = ruby
|
99
|
+
RUBYW_INSTALL_NAME =
|
100
|
+
RUBY_VERSION_NAME = $(RUBY_BASE_NAME)-$(ruby_version)
|
101
|
+
RUBYW_BASE_NAME = rubyw
|
102
|
+
RUBY_BASE_NAME = ruby
|
103
|
+
|
104
|
+
arch = x86_64-linux
|
105
|
+
sitearch = $(arch)
|
106
|
+
ruby_version = 2.3.0
|
107
|
+
ruby = $(bindir)/$(RUBY_BASE_NAME)
|
108
|
+
RUBY = $(ruby)
|
109
|
+
ruby_headers = $(hdrdir)/ruby.h $(hdrdir)/ruby/ruby.h $(hdrdir)/ruby/defines.h $(hdrdir)/ruby/missing.h $(hdrdir)/ruby/intern.h $(hdrdir)/ruby/st.h $(hdrdir)/ruby/subst.h $(arch_hdrdir)/ruby/config.h
|
110
|
+
|
111
|
+
RM = rm -f
|
112
|
+
RM_RF = $(RUBY) -run -e rm -- -rf
|
113
|
+
RMDIRS = rmdir --ignore-fail-on-non-empty -p
|
114
|
+
MAKEDIRS = /bin/mkdir -p
|
115
|
+
INSTALL = /usr/bin/install
|
116
|
+
INSTALL_PROG = $(INSTALL) -m 0755
|
117
|
+
INSTALL_DATA = $(INSTALL) -m 644
|
118
|
+
COPY = cp
|
119
|
+
TOUCH = exit >
|
120
|
+
|
121
|
+
#### End of system configuration section. ####
|
122
|
+
|
123
|
+
preload =
|
124
|
+
|
125
|
+
libpath = . $(libdir)
|
126
|
+
LIBPATH = -L. -L$(libdir) -Wl,-R$(libdir)
|
127
|
+
DEFFILE =
|
128
|
+
|
129
|
+
CLEANFILES = mkmf.log
|
130
|
+
DISTCLEANFILES =
|
131
|
+
DISTCLEANDIRS =
|
132
|
+
|
133
|
+
extout =
|
134
|
+
extout_prefix =
|
135
|
+
target_prefix = /crypt/isaac
|
136
|
+
LOCAL_LIBS =
|
137
|
+
LIBS = $(LIBRUBYARG_SHARED) -lpthread -ldl -lcrypt -lm -lc
|
138
|
+
ORIG_SRCS = isaac.c rand.c
|
139
|
+
SRCS = $(ORIG_SRCS)
|
140
|
+
OBJS = isaac.o rand.o
|
141
|
+
HDRS = $(srcdir)/rand.h $(srcdir)/standard.h
|
142
|
+
TARGET = ext
|
143
|
+
TARGET_NAME = ext
|
144
|
+
TARGET_ENTRY = Init_$(TARGET_NAME)
|
145
|
+
DLLIB = $(TARGET).so
|
146
|
+
EXTSTATIC =
|
147
|
+
STATIC_LIB =
|
148
|
+
|
149
|
+
TIMESTAMP_DIR = .
|
150
|
+
BINDIR = $(bindir)
|
151
|
+
RUBYCOMMONDIR = $(sitedir)$(target_prefix)
|
152
|
+
RUBYLIBDIR = $(sitelibdir)$(target_prefix)
|
153
|
+
RUBYARCHDIR = $(sitearchdir)$(target_prefix)
|
154
|
+
HDRDIR = $(rubyhdrdir)/ruby$(target_prefix)
|
155
|
+
ARCHHDRDIR = $(rubyhdrdir)/$(arch)/ruby$(target_prefix)
|
156
|
+
|
157
|
+
TARGET_SO = $(DLLIB)
|
158
|
+
CLEANLIBS = $(TARGET).so
|
159
|
+
CLEANOBJS = *.o *.bak
|
160
|
+
|
161
|
+
all: $(DLLIB)
|
162
|
+
static: $(STATIC_LIB) install-rb
|
163
|
+
.PHONY: all install static install-so install-rb
|
164
|
+
.PHONY: clean clean-so clean-static clean-rb
|
165
|
+
|
166
|
+
clean-static::
|
167
|
+
clean-rb-default::
|
168
|
+
clean-rb::
|
169
|
+
clean-so::
|
170
|
+
clean: clean-so clean-static clean-rb-default clean-rb
|
171
|
+
-$(Q)$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES) .*.time
|
172
|
+
|
173
|
+
distclean-rb-default::
|
174
|
+
distclean-rb::
|
175
|
+
distclean-so::
|
176
|
+
distclean-static::
|
177
|
+
distclean: clean distclean-so distclean-static distclean-rb-default distclean-rb
|
178
|
+
-$(Q)$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
|
179
|
+
-$(Q)$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
|
180
|
+
-$(Q)$(RMDIRS) $(DISTCLEANDIRS) 2> /dev/null || true
|
181
|
+
|
182
|
+
realclean: distclean
|
183
|
+
install: install-so install-rb
|
184
|
+
|
185
|
+
install-so: $(DLLIB) $(TIMESTAMP_DIR)/.RUBYARCHDIR.-.crypt.-.isaac.time
|
186
|
+
$(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)
|
187
|
+
clean-static::
|
188
|
+
-$(Q)$(RM) $(STATIC_LIB)
|
189
|
+
install-rb: pre-install-rb install-rb-default
|
190
|
+
install-rb-default: pre-install-rb-default
|
191
|
+
pre-install-rb: Makefile
|
192
|
+
pre-install-rb-default: Makefile
|
193
|
+
pre-install-rb-default:
|
194
|
+
@$(NULLCMD)
|
195
|
+
$(TIMESTAMP_DIR)/.RUBYARCHDIR.-.crypt.-.isaac.time:
|
196
|
+
$(Q) $(MAKEDIRS) $(@D) $(RUBYARCHDIR)
|
197
|
+
$(Q) $(TOUCH) $@
|
198
|
+
|
199
|
+
site-install: site-install-so site-install-rb
|
200
|
+
site-install-so: install-so
|
201
|
+
site-install-rb: install-rb
|
202
|
+
|
203
|
+
.SUFFIXES: .c .m .cc .mm .cxx .cpp .o .S
|
204
|
+
|
205
|
+
.cc.o:
|
206
|
+
$(ECHO) compiling $(<)
|
207
|
+
$(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
|
208
|
+
|
209
|
+
.cc.S:
|
210
|
+
$(ECHO) translating $(<)
|
211
|
+
$(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $<
|
212
|
+
|
213
|
+
.mm.o:
|
214
|
+
$(ECHO) compiling $(<)
|
215
|
+
$(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
|
216
|
+
|
217
|
+
.mm.S:
|
218
|
+
$(ECHO) translating $(<)
|
219
|
+
$(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $<
|
220
|
+
|
221
|
+
.cxx.o:
|
222
|
+
$(ECHO) compiling $(<)
|
223
|
+
$(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
|
224
|
+
|
225
|
+
.cxx.S:
|
226
|
+
$(ECHO) translating $(<)
|
227
|
+
$(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $<
|
228
|
+
|
229
|
+
.cpp.o:
|
230
|
+
$(ECHO) compiling $(<)
|
231
|
+
$(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
|
232
|
+
|
233
|
+
.cpp.S:
|
234
|
+
$(ECHO) translating $(<)
|
235
|
+
$(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $<
|
236
|
+
|
237
|
+
.c.o:
|
238
|
+
$(ECHO) compiling $(<)
|
239
|
+
$(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $<
|
240
|
+
|
241
|
+
.c.S:
|
242
|
+
$(ECHO) translating $(<)
|
243
|
+
$(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -S $<
|
244
|
+
|
245
|
+
.m.o:
|
246
|
+
$(ECHO) compiling $(<)
|
247
|
+
$(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $<
|
248
|
+
|
249
|
+
.m.S:
|
250
|
+
$(ECHO) translating $(<)
|
251
|
+
$(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -S $<
|
252
|
+
|
253
|
+
$(DLLIB): $(OBJS) Makefile
|
254
|
+
$(ECHO) linking shared-object crypt/isaac/$(DLLIB)
|
255
|
+
-$(Q)$(RM) $(@)
|
256
|
+
$(Q) $(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
|
257
|
+
|
258
|
+
|
259
|
+
|
260
|
+
$(OBJS): $(HDRS) $(ruby_headers)
|
@@ -0,0 +1,232 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
#include "rand.h"
|
3
|
+
|
4
|
+
static VALUE CryptModule;
|
5
|
+
static VALUE ISAACClass;
|
6
|
+
|
7
|
+
static void ISAAC_free( randctx* ctx ) {
|
8
|
+
if ( ctx ) {
|
9
|
+
xfree( ctx );
|
10
|
+
}
|
11
|
+
}
|
12
|
+
|
13
|
+
static VALUE ISAAC_alloc( VALUE klass ) {
|
14
|
+
randctx *ctx;
|
15
|
+
|
16
|
+
return Data_Make_Struct( klass, randctx, NULL, ISAAC_free, ctx );
|
17
|
+
}
|
18
|
+
|
19
|
+
static VALUE ISAAC_initialize( VALUE self, VALUE args ) {
|
20
|
+
VALUE _seed ;
|
21
|
+
long len = RARRAY_LEN( args );
|
22
|
+
if ( len == 0 ) {
|
23
|
+
_seed = Qtrue;
|
24
|
+
} else {
|
25
|
+
_seed = rb_ary_entry( args, 0 );
|
26
|
+
}
|
27
|
+
|
28
|
+
return rb_funcall( self, rb_intern( "srand" ), 1, _seed );
|
29
|
+
}
|
30
|
+
|
31
|
+
static VALUE ISAAC_srand( VALUE self, VALUE args ) {
|
32
|
+
FILE *fh;
|
33
|
+
uint32_t num = 0;
|
34
|
+
size_t nread;
|
35
|
+
VALUE _seed;
|
36
|
+
VALUE old_seed;
|
37
|
+
VALUE seed_prng;
|
38
|
+
VALUE random_argv[1];
|
39
|
+
VALUE rnd_source = Qnil;
|
40
|
+
int x;
|
41
|
+
long len = RARRAY_LEN( args );
|
42
|
+
randctx *ctx;
|
43
|
+
|
44
|
+
if ( len == 0 ) {
|
45
|
+
_seed = Qtrue;
|
46
|
+
} else {
|
47
|
+
_seed = rb_ary_entry( args, 0 );
|
48
|
+
}
|
49
|
+
|
50
|
+
if ( ( _seed == Qtrue ) || ( _seed == Qfalse ) ) {
|
51
|
+
rnd_source = ( _seed == Qtrue ) ? rb_str_new2("/dev/urandom") : rb_str_new2("/dev/random");
|
52
|
+
}
|
53
|
+
|
54
|
+
Data_Get_Struct( self, randctx, ctx );
|
55
|
+
MEMZERO( ctx, randctx, 1 );
|
56
|
+
|
57
|
+
if ( ( rnd_source != Qnil ) && ( rb_funcall( rb_mFileTest, rb_intern("exist?"), 1, rnd_source ) == Qtrue ) ) {
|
58
|
+
fh = fopen("/dev/urandom","r");
|
59
|
+
for ( x = RANDSIZ - 1; x >= 0; x-- ) {
|
60
|
+
nread = fread(&num, sizeof(uint32_t), 1, fh);
|
61
|
+
if ( nread == 0 ) {
|
62
|
+
x++;
|
63
|
+
continue;
|
64
|
+
}
|
65
|
+
ctx->randrsl[x] = num;
|
66
|
+
}
|
67
|
+
fclose(fh);
|
68
|
+
} else {
|
69
|
+
if ( rnd_source != Qnil ) {
|
70
|
+
_seed = Qnil;
|
71
|
+
}
|
72
|
+
if ( rb_funcall( _seed, rb_intern( "respond_to?" ), 1, rb_str_new2("rand") ) == Qtrue ) {
|
73
|
+
seed_prng = _seed;
|
74
|
+
} else {
|
75
|
+
random_argv[0] = _seed;
|
76
|
+
seed_prng = rb_class_new_instance( 1, random_argv, rb_const_get( rb_const_get( rb_cObject, rb_intern( "Crypt" ) ), rb_intern( "Xorshift64Star" ) ) );
|
77
|
+
_seed = rb_funcall( seed_prng, rb_intern( "seed" ), 0 );
|
78
|
+
rb_iv_set( self, "@seed_prng", seed_prng );
|
79
|
+
}
|
80
|
+
for ( x = RANDSIZ - 1; x >= 0; x-- ) {
|
81
|
+
ctx->randrsl[x] = FIX2ULONG( rb_funcall( seed_prng, rb_intern( "rand" ), 1, ULONG2NUM(4294967296) ) );
|
82
|
+
}
|
83
|
+
}
|
84
|
+
randinit(ctx, 1);
|
85
|
+
|
86
|
+
rb_iv_set( self, "@seed", ( ( rnd_source == Qtrue ) || ( rnd_source == Qfalse ) ) ? rnd_source : _seed );
|
87
|
+
old_seed = rb_iv_get( self, "@seed");
|
88
|
+
|
89
|
+
return old_seed;
|
90
|
+
}
|
91
|
+
|
92
|
+
static VALUE ISAAC_rand( VALUE self, VALUE args ) {
|
93
|
+
uint32_t limit;
|
94
|
+
long len = RARRAY_LEN( args );
|
95
|
+
VALUE arg;
|
96
|
+
short arg_is_a_range = 0;
|
97
|
+
ID id_min;
|
98
|
+
VALUE val_min = 0;
|
99
|
+
ID id_max;
|
100
|
+
randctx *ctx;
|
101
|
+
|
102
|
+
arg = rb_ary_entry( args, 0 );
|
103
|
+
|
104
|
+
if ( len == 0 ) {
|
105
|
+
limit = 0;
|
106
|
+
} else if ( rb_obj_class( arg ) == rb_cRange ) {
|
107
|
+
arg_is_a_range = 1;
|
108
|
+
id_min = rb_intern("min");
|
109
|
+
id_max = rb_intern("max");
|
110
|
+
val_min = rb_funcall( arg, id_min, 0 );
|
111
|
+
limit = NUM2ULONG( rb_funcall( arg, id_max, 0 ) ) - NUM2ULONG( val_min );
|
112
|
+
} else {
|
113
|
+
limit = NUM2ULONG( rb_ary_entry( args, 0 ) );
|
114
|
+
}
|
115
|
+
|
116
|
+
Data_Get_Struct( self, randctx, ctx );
|
117
|
+
if ( !ctx->randcnt-- ) {
|
118
|
+
isaac( ctx );
|
119
|
+
ctx->randcnt = RANDSIZ - 1;
|
120
|
+
}
|
121
|
+
|
122
|
+
if ( limit == 0 ) {
|
123
|
+
return rb_float_new( ctx->randrsl[ctx->randcnt] / 4294967296.0 );
|
124
|
+
} else if ( arg_is_a_range ) {
|
125
|
+
return ULONG2NUM( NUM2ULONG( val_min ) + ( ctx->randrsl[ctx->randcnt] % limit ) );
|
126
|
+
} else {
|
127
|
+
return ULONG2NUM( ctx->randrsl[ctx->randcnt] % limit );
|
128
|
+
}
|
129
|
+
}
|
130
|
+
|
131
|
+
static VALUE ISAAC_marshal_dump( VALUE self ) {
|
132
|
+
randctx *ctx;
|
133
|
+
int i;
|
134
|
+
int ary_size = sizeof( randctx ) / sizeof( ub4 );
|
135
|
+
VALUE ary;
|
136
|
+
|
137
|
+
Data_Get_Struct( self, randctx, ctx );
|
138
|
+
|
139
|
+
ary = rb_ary_new2( ary_size );
|
140
|
+
for ( i = 0; i < ary_size; i++ ) {
|
141
|
+
rb_ary_push( ary, ULONG2NUM(((ub4 *)ctx)[i]));
|
142
|
+
}
|
143
|
+
|
144
|
+
return ary;
|
145
|
+
}
|
146
|
+
|
147
|
+
static VALUE ISAAC_marshal_load( VALUE self, VALUE ary ) {
|
148
|
+
randctx *ctx;
|
149
|
+
int i;
|
150
|
+
int ary_size = sizeof( randctx ) / sizeof( ub4 );
|
151
|
+
|
152
|
+
Data_Get_Struct( self, randctx, ctx );
|
153
|
+
|
154
|
+
if ( RARRAY_LEN(ary) != ary_size )
|
155
|
+
rb_raise( rb_eArgError, "bad length in loaded ISAAC data" );
|
156
|
+
|
157
|
+
for ( i = 0; i < ary_size; i++ ) {
|
158
|
+
((ub4 *)ctx)[i] = NUM2ULONG(RARRAY_PTR(ary)[i] );
|
159
|
+
}
|
160
|
+
|
161
|
+
return self;
|
162
|
+
}
|
163
|
+
|
164
|
+
static VALUE ISAAC_seed( VALUE self ) {
|
165
|
+
return rb_iv_get( self, "@seed");
|
166
|
+
}
|
167
|
+
|
168
|
+
static VALUE ISAAC_new_seed( VALUE self ) {
|
169
|
+
return rb_funcall( rb_iv_get( self, "@seed_prng" ), rb_intern("new_seed"), 0 );
|
170
|
+
}
|
171
|
+
|
172
|
+
int compare_ctx( randctx* ctx1, randctx* ctx2 ) {
|
173
|
+
int x;
|
174
|
+
for ( x = RANDSIZ - 1; x >= 0; x-- ) {
|
175
|
+
if ( ctx1->randrsl[x] != ctx2->randrsl[x] ) return 0;
|
176
|
+
}
|
177
|
+
|
178
|
+
return 1;
|
179
|
+
}
|
180
|
+
|
181
|
+
static VALUE ISAAC_eq( VALUE self, VALUE v ) {
|
182
|
+
randctx* ctx1;
|
183
|
+
randctx* ctx2;
|
184
|
+
|
185
|
+
Data_Get_Struct( self, randctx, ctx1 );
|
186
|
+
Data_Get_Struct( v, randctx, ctx2 );
|
187
|
+
|
188
|
+
return ( ( rb_obj_classname( self ) == rb_obj_classname( v ) ) && ( compare_ctx( ctx1, ctx2 ) ) ) ? Qtrue : Qfalse ;
|
189
|
+
}
|
190
|
+
|
191
|
+
static VALUE ISAAC_bytes( VALUE self, VALUE count ) {
|
192
|
+
uint64_t bytes = NUM2ULL( count );
|
193
|
+
char buf[ bytes + 5 ];
|
194
|
+
uint64_t i = 0;
|
195
|
+
randctx* ctx;
|
196
|
+
|
197
|
+
Data_Get_Struct( self, randctx, ctx );
|
198
|
+
for( i = 0; i < bytes; i = i + 4 ) {
|
199
|
+
|
200
|
+
if ( !ctx->randcnt-- ) {
|
201
|
+
isaac( ctx );
|
202
|
+
ctx->randcnt = RANDSIZ - 1;
|
203
|
+
}
|
204
|
+
|
205
|
+
// snprintf( &buf[ i ], 5, "%lu", ctx->randrsl[ctx->randcnt] );
|
206
|
+
buf[ i ] = ctx->randrsl[ctx->randcnt];
|
207
|
+
buf[ i + 1 ] = ctx->randrsl[ctx->randcnt] >> 8;
|
208
|
+
buf[ i + 2 ] = ctx->randrsl[ctx->randcnt] >> 16;
|
209
|
+
buf[ i + 3 ] = ctx->randrsl[ctx->randcnt] >> 24;
|
210
|
+
}
|
211
|
+
|
212
|
+
return rb_str_new( buf, bytes );
|
213
|
+
}
|
214
|
+
|
215
|
+
void Init_ext() {
|
216
|
+
CryptModule = rb_define_module( "Crypt" );
|
217
|
+
ISAACClass = rb_define_class_under( CryptModule, "ISAAC", rb_cObject );
|
218
|
+
|
219
|
+
rb_define_alloc_func( ISAACClass, ISAAC_alloc );
|
220
|
+
rb_define_method( ISAACClass, "initialize", ISAAC_initialize, -2 );
|
221
|
+
rb_define_method( ISAACClass, "srand", ISAAC_srand, -2 );
|
222
|
+
rb_define_method( ISAACClass, "rand", ISAAC_rand, -2 );
|
223
|
+
rb_define_method( ISAACClass, "seed", ISAAC_seed, 0 );
|
224
|
+
rb_define_method( ISAACClass, "new_seed", ISAAC_new_seed, 0 );
|
225
|
+
rb_define_method( ISAACClass, "==", ISAAC_eq, 1 );
|
226
|
+
rb_define_method( ISAACClass, "bytes", ISAAC_bytes, 1 );
|
227
|
+
rb_define_method( ISAACClass, "marshal_dump", ISAAC_marshal_dump, 0 );
|
228
|
+
rb_define_method( ISAACClass, "marshal_load", ISAAC_marshal_load, 1 );
|
229
|
+
|
230
|
+
rb_const_set( ISAACClass, rb_intern("RANDSIZ"), ULONG2NUM(RANDSIZ) );
|
231
|
+
rb_require( "crypt/isaac/version.rb" );
|
232
|
+
}
|