raptcha 0.0.1 → 2.0.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.
- data/README +0 -88
- data/Rakefile +364 -0
- data/image.sh +24 -0
- data/images/raptcha.png +0 -0
- data/lib/raptcha.rb +377 -2063
- metadata +56 -128
- data/bin/raptcha +0 -2225
- data/gemspec.rb +0 -28
- data/install.rb +0 -210
- data/out +0 -0
- data/rails/README +0 -182
- data/rails/Rakefile +0 -10
- data/rails/app/controllers/application.rb +0 -7
- data/rails/app/controllers/raptcha_controller.rb +0 -43
- data/rails/app/helpers/application_helper.rb +0 -3
- data/rails/config/boot.rb +0 -45
- data/rails/config/database.yml +0 -36
- data/rails/config/environment.rb +0 -62
- data/rails/config/environments/development.rb +0 -21
- data/rails/config/environments/production.rb +0 -18
- data/rails/config/environments/test.rb +0 -19
- data/rails/config/lighttpd.conf +0 -54
- data/rails/config/routes.rb +0 -23
- data/rails/doc/README_FOR_APP +0 -2
- data/rails/lib/raptcha.rb +0 -2225
- data/rails/log/development.log +0 -16
- data/rails/log/fastcgi.crash.log +0 -4
- data/rails/log/lighttpd.access.log +0 -2
- data/rails/log/lighttpd.error.log +0 -3
- data/rails/log/production.log +0 -0
- data/rails/log/server.log +0 -0
- data/rails/log/test.log +0 -0
- data/rails/public/404.html +0 -30
- data/rails/public/500.html +0 -30
- data/rails/public/dispatch.cgi +0 -10
- data/rails/public/dispatch.fcgi +0 -24
- data/rails/public/dispatch.rb +0 -10
- data/rails/public/favicon.ico +0 -0
- data/rails/public/images/rails.png +0 -0
- data/rails/public/index.html +0 -277
- data/rails/public/javascripts/application.js +0 -2
- data/rails/public/javascripts/controls.js +0 -833
- data/rails/public/javascripts/dragdrop.js +0 -942
- data/rails/public/javascripts/effects.js +0 -1088
- data/rails/public/javascripts/prototype.js +0 -2515
- data/rails/public/robots.txt +0 -1
- data/rails/script/about +0 -3
- data/rails/script/breakpointer +0 -3
- data/rails/script/console +0 -3
- data/rails/script/destroy +0 -3
- data/rails/script/generate +0 -3
- data/rails/script/performance/benchmarker +0 -3
- data/rails/script/performance/profiler +0 -3
- data/rails/script/plugin +0 -3
- data/rails/script/process/inspector +0 -3
- data/rails/script/process/reaper +0 -3
- data/rails/script/process/spawner +0 -3
- data/rails/script/runner +0 -3
- data/rails/script/server +0 -3
- data/rails/test/test_helper.rb +0 -28
- data/rails/tmp/sessions/ruby_sess.04085f44b9141c9d +0 -0
- data/raptcha-0.0.1.gem +0 -0
- data/samples.rb +0 -19
data/image.sh
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
word="A R A H O W"
|
4
|
+
|
5
|
+
convert \
|
6
|
+
-size '300x50' \
|
7
|
+
-strokewidth 1 \
|
8
|
+
-gravity center \
|
9
|
+
-fill '#ffa500' \
|
10
|
+
-family 'monoco' \
|
11
|
+
-pointsize 42 \
|
12
|
+
-bordercolor white \
|
13
|
+
-border 5 \
|
14
|
+
-annotate "0x0" "$word" \
|
15
|
+
-wave '3x50' \
|
16
|
+
-implode 0.2 \
|
17
|
+
-strokewidth 10 \
|
18
|
+
-draw 'line 5 25 295 25' \
|
19
|
+
-draw 'line 5 35 295 35' \
|
20
|
+
xc:white jpg:- > raptcha.jpg
|
21
|
+
|
22
|
+
open raptcha.jpg
|
23
|
+
|
24
|
+
#-draw 'point 3,2' \
|
data/images/raptcha.png
ADDED
Binary file
|
data/lib/raptcha.rb
CHANGED
@@ -1,126 +1,205 @@
|
|
1
1
|
#! /usr/bin/env ruby
|
2
2
|
|
3
3
|
module Raptcha
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
|
5
|
+
README = <<-__
|
6
|
+
NAME
|
7
|
+
raptcha.rb
|
8
|
+
|
9
|
+
SYNOPSIS
|
10
|
+
super low drain bamage, K.I.S.S., storage-less, session-less,
|
11
|
+
plugin-less, dependency-less, zero admin, single-source-file secure
|
12
|
+
captcha system for ruby and/or rails.
|
13
|
+
|
14
|
+
bitchin.
|
15
|
+
|
16
|
+
DESCRIPTION
|
17
|
+
raptcha manages image generation via a streaming controller. the result
|
18
|
+
is that *no* disk storage is ever needed for captcha images. it also
|
19
|
+
manages authentication via openssl(aes-256) encoded hidden fields which
|
20
|
+
are relayed through the form submission process, obviating the need for
|
21
|
+
session/database interaction for captcha validation. the library is
|
22
|
+
useful outside of rails, even from the command line.
|
23
|
+
|
24
|
+
what this means to you is that you can have a nice looking, and easy to
|
25
|
+
customize, safe captcha solution in about 1 minute that requires zero
|
26
|
+
maintenance moving forward.
|
27
|
+
|
28
|
+
see a sample image here
|
29
|
+
http://github.com/ahoward/raptcha/blob/master/images/raptcha.png
|
30
|
+
|
31
|
+
INSTALL
|
32
|
+
1) INSTALL Image Magick
|
33
|
+
~> which convert
|
34
|
+
|
35
|
+
2) COPY A SINGLE FILE INTO YOUR RAILS APP
|
36
|
+
~> cp raptcha.rb ./app/lib/
|
37
|
+
|
38
|
+
3) GENERATE THE CONROLLER
|
39
|
+
ruby lib/raptcha.rb generate controller
|
40
|
+
|
41
|
+
4) ADD A ROUTE
|
42
|
+
match 'raptcha(/:action)', :controller => 'raptcha'
|
43
|
+
|
44
|
+
5) PUT A RAPTCHA IMAGE AND FORM INPUT IN YOUR VIEW
|
45
|
+
<%= Raptcha.input %>
|
46
|
+
|
47
|
+
6) REQUIRE VALID RAPTCHA INPUT IN A CONTROLLER ACTION
|
48
|
+
class SessionsController < ApplicationController
|
49
|
+
def create
|
50
|
+
unless Raptcha.valid?(params)
|
51
|
+
# ...
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
7) TRY THE EXAMPLES LOCALLY AT
|
57
|
+
http://0.0.0.0:3000/raptcha/form
|
58
|
+
http://0.0.0.0:3000/raptcha/inline
|
59
|
+
|
60
|
+
URIS
|
61
|
+
http://github.com/ahoward/raptcha
|
62
|
+
http://codforpeople.com
|
63
|
+
|
64
|
+
|
65
|
+
COMMAND LINE USAGE
|
66
|
+
* make an image by hand
|
67
|
+
~> ruby lib/raptcha.rb image foreground:pink raptcha.png && open raptcha.png
|
68
|
+
|
69
|
+
* generate the controller
|
70
|
+
~> ruby lib/rapcha.rb generate controller
|
71
|
+
|
72
|
+
DOC
|
73
|
+
less lib/raptcha.rb
|
74
|
+
__
|
75
|
+
|
76
|
+
Version = '2.0.0' unless defined? Raptcha::Version
|
77
|
+
def Raptcha.version() Version end
|
7
78
|
|
8
79
|
require 'base64'
|
9
80
|
require 'socket'
|
81
|
+
require 'openssl'
|
10
82
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
end
|
83
|
+
module Image
|
84
|
+
class << Image
|
85
|
+
def create(options = {})
|
86
|
+
options = Raptcha.normalize(options)
|
16
87
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
rescue LoadError
|
23
|
-
require 'rmagick'
|
24
|
-
end
|
25
|
-
end
|
88
|
+
word = options[:word] || options[:w]
|
89
|
+
encrypted = options[:encrypted] || options[:e]
|
90
|
+
word ||= Encryptor.decrypt(encrypted) if encrypted
|
91
|
+
word ||= Raptcha.word
|
92
|
+
word = word.split(%r"").join(" ").strip.upcase
|
26
93
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
94
|
+
Image.for(word)
|
95
|
+
end
|
96
|
+
|
97
|
+
def for(word)
|
98
|
+
command = %W(
|
99
|
+
convert
|
100
|
+
-size '242x42'
|
101
|
+
-strokewidth 1
|
102
|
+
-gravity center
|
103
|
+
-fill '#333'
|
104
|
+
-family 'monoco'
|
105
|
+
-pointsize 42
|
106
|
+
-bordercolor white
|
107
|
+
-border 10
|
108
|
+
-annotate "0x0" #{ word.inspect }
|
109
|
+
-implode 0.2
|
110
|
+
-strokewidth 10
|
111
|
+
-draw 'line 5 25 295 25'
|
112
|
+
-draw 'line 5 35 295 35'
|
113
|
+
-wave '3x50'
|
114
|
+
xc:white jpg:-
|
115
|
+
)
|
116
|
+
command = command.join(' ')
|
117
|
+
IO.popen(command){|pipe| pipe.read}
|
118
|
+
end
|
119
|
+
|
120
|
+
def inline(options = {})
|
121
|
+
Base64.encode64(create(options))
|
122
|
+
end
|
123
|
+
end
|
39
124
|
end
|
40
|
-
#--}}}
|
41
|
-
=end
|
42
125
|
|
43
|
-
module
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
126
|
+
module Encoder
|
127
|
+
def encode(string)
|
128
|
+
return nil if string.nil?
|
129
|
+
Base64.encode64(string.to_s).gsub(/[\s=]+/, "").gsub("+", "-").gsub("/", "_")
|
130
|
+
end
|
131
|
+
|
132
|
+
def decode(string)
|
133
|
+
return nil if string.nil?
|
134
|
+
case string.length.modulo(4)
|
135
|
+
when 2
|
136
|
+
string += '=='
|
137
|
+
when 3
|
138
|
+
string += '='
|
48
139
|
end
|
140
|
+
Base64.decode64(string.gsub("-", "+").gsub("_", "/"))
|
141
|
+
end
|
49
142
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
attribute('distort'){ Hash[
|
54
|
-
:low => [0, 100],
|
55
|
-
:medium => [3, 50],
|
56
|
-
:high => [5, 30],
|
57
|
-
] }
|
58
|
-
|
59
|
-
attribute('default'){ Hash[
|
60
|
-
:width => 142,
|
61
|
-
:height => 30,
|
62
|
-
:distort => :medium,
|
63
|
-
#:background => 'black',
|
64
|
-
#:foreground => 'springgreen',
|
65
|
-
:background => 'white',
|
66
|
-
:foreground => 'springgreen3',
|
67
|
-
:format => 'png',
|
68
|
-
:font_family => 'monoco',
|
69
|
-
:pointsize => 22,
|
70
|
-
:implode => 0.2,
|
71
|
-
] }
|
72
|
-
|
73
|
-
|
74
|
-
def create kw = {}
|
75
|
-
kw = default.update kw.to_options
|
76
|
-
|
77
|
-
word = kw[:word]
|
78
|
-
encrypted = kw[:encrypted] || kw[:e]
|
79
|
-
word ||= Raptcha.decrypt(encrypted, :key => key) if encrypted
|
80
|
-
word ||= Raptcha.word
|
81
|
-
word = word.split(%r"").join(" ")
|
143
|
+
extend(Encoder)
|
144
|
+
end
|
82
145
|
|
83
|
-
|
84
|
-
|
85
|
-
|
146
|
+
module Encryptor
|
147
|
+
def encrypt(plaintext, options = {})
|
148
|
+
plaintext = plaintext.to_s
|
149
|
+
key = options[:key] || options['key'] || Encryptor.key
|
150
|
+
alg = options[:alg] || options['alg'] || Encryptor.alg
|
151
|
+
salt = options[:salt] || options['salt'] || Encryptor.salt
|
152
|
+
enc = OpenSSL::Cipher::Cipher.new(alg)
|
153
|
+
enc.encrypt
|
154
|
+
enc.pkcs5_keyivgen(key, salt)
|
155
|
+
ciphertext = enc.update(plaintext)
|
156
|
+
ciphertext << enc.final
|
157
|
+
Encoder.encode(ciphertext)
|
158
|
+
end
|
86
159
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
160
|
+
def decrypt(ciphertext, options = {})
|
161
|
+
ciphertext = Encoder.decode(ciphertext.to_s)
|
162
|
+
key = options[:key] || options['key'] || Encryptor.key
|
163
|
+
alg = options[:alg] || options['alg'] || Encryptor.alg
|
164
|
+
salt = options[:salt] || options['salt'] || Encryptor.salt
|
165
|
+
dec = OpenSSL::Cipher::Cipher.new(alg)
|
166
|
+
dec.decrypt
|
167
|
+
dec.pkcs5_keyivgen(key, salt)
|
168
|
+
plaintext = dec.update(ciphertext)
|
169
|
+
plaintext << dec.final
|
170
|
+
end
|
91
171
|
|
92
|
-
|
172
|
+
def cycle(plaintext, options = {})
|
173
|
+
decrypt(encrypt(plaintext, options), options)
|
174
|
+
end
|
93
175
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
#draw.pointsize = kw[:height] * 0.75
|
100
|
-
draw.fill = kw[:foreground]
|
101
|
-
draw.gravity = Magick::NorthGravity
|
102
|
-
draw.annotate img, 0, 0, 5, 5, word
|
176
|
+
def key(*key)
|
177
|
+
self.key = key.first.to_s unless key.empty?
|
178
|
+
self.key = default_key unless defined?(@key)
|
179
|
+
@key
|
180
|
+
end
|
103
181
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
#draw.line 5, kw[:height]*0.33, kw[:width]-5, kw[:height]*0.33
|
108
|
-
#draw.line 5, kw[:height]*0.66, kw[:width]-5, kw[:height]*0.66
|
109
|
-
draw.line 5, kw[:height]*0.65, kw[:width]-5, kw[:height]*0.65
|
182
|
+
def default_key
|
183
|
+
Rails.application.config.secret_token
|
184
|
+
end
|
110
185
|
|
111
|
-
|
186
|
+
def key=(key)
|
187
|
+
@key = key.to_s[0, 56]
|
188
|
+
end
|
112
189
|
|
113
|
-
|
114
|
-
|
190
|
+
def alg
|
191
|
+
@alg ||= 'AES-256-CBC'
|
192
|
+
end
|
115
193
|
|
116
|
-
|
117
|
-
|
194
|
+
def salt
|
195
|
+
@salt ||= nil
|
196
|
+
end
|
118
197
|
|
119
|
-
|
120
|
-
|
121
|
-
end
|
198
|
+
def salt=(salt)
|
199
|
+
@salt = salt
|
122
200
|
end
|
123
|
-
|
201
|
+
|
202
|
+
extend(self)
|
124
203
|
end
|
125
204
|
|
126
205
|
class Error < ::StandardError; end
|
@@ -128,2098 +207,333 @@ module Raptcha
|
|
128
207
|
class BadInput < Error; end
|
129
208
|
class Expired < Error; end
|
130
209
|
|
131
|
-
|
132
|
-
|
133
|
-
|
210
|
+
class << Raptcha
|
211
|
+
def key
|
212
|
+
@key ||= Rails::Application.config.secret_token
|
134
213
|
end
|
135
214
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
215
|
+
def route
|
216
|
+
@route ||= '/raptcha'
|
217
|
+
end
|
218
|
+
|
219
|
+
def gravity
|
220
|
+
@gravity ||= 'north'
|
221
|
+
end
|
222
|
+
|
223
|
+
def ttl
|
224
|
+
@ttl ||= 30 * 60
|
225
|
+
end
|
226
|
+
|
227
|
+
def close_enough
|
228
|
+
@close_enough ||= {
|
229
|
+
'0OoQ' => '0',
|
230
|
+
'1l' => '1',
|
231
|
+
'2zZ' => '2',
|
232
|
+
'5sS' => '5',
|
233
|
+
'kKxX' => 'x',
|
234
|
+
}
|
235
|
+
end
|
236
|
+
|
237
|
+
def normalize(options)
|
238
|
+
options.inject({}){|h, kv| h.update(kv.first.to_s.to_sym => kv.last) }
|
239
|
+
end
|
240
|
+
|
241
|
+
def valid?(params)
|
155
242
|
begin
|
156
|
-
validate!
|
157
|
-
rescue NoInput
|
243
|
+
validate!(params)
|
244
|
+
rescue NoInput
|
158
245
|
nil
|
159
|
-
rescue BadInput
|
160
|
-
false
|
161
|
-
rescue Expired
|
246
|
+
rescue BadInput, Expired
|
162
247
|
false
|
163
248
|
end
|
164
|
-
#--}}}
|
165
249
|
end
|
166
250
|
|
167
|
-
def validate!
|
168
|
-
|
169
|
-
|
170
|
-
|
251
|
+
def validate!(params)
|
252
|
+
params = Raptcha.normalize(params)
|
253
|
+
|
254
|
+
if params.has_key?(:raptcha)
|
255
|
+
raptcha = params[:raptcha]
|
171
256
|
|
172
|
-
textarea = raptcha[
|
173
|
-
word = raptcha[
|
174
|
-
timebomb = raptcha[
|
257
|
+
textarea = raptcha[:t]
|
258
|
+
word = raptcha[:w]
|
259
|
+
timebomb = raptcha[:b]
|
175
260
|
|
176
|
-
raise NoInput unless
|
261
|
+
raise NoInput unless(textarea and word and timebomb)
|
177
262
|
|
178
|
-
word = decrypt
|
179
|
-
timebomb = decrypt
|
263
|
+
word = Encryptor.decrypt(word)
|
264
|
+
timebomb = Encryptor.decrypt(timebomb)
|
180
265
|
|
181
266
|
begin
|
182
|
-
timebomb = Integer
|
267
|
+
timebomb = Integer(timebomb)
|
183
268
|
timebomb = Time.at(timebomb).utc
|
184
269
|
now = Time.now.utc
|
185
|
-
raise Expired unless now < timebomb
|
270
|
+
raise Expired unless now < timebomb
|
186
271
|
rescue
|
187
272
|
raise Expired
|
188
273
|
end
|
189
274
|
|
190
|
-
raise BadInput unless
|
275
|
+
raise BadInput unless fuzzy_match(word, textarea)
|
191
276
|
|
192
277
|
textarea
|
193
278
|
else
|
194
|
-
validate!
|
279
|
+
validate!(:raptcha => params)
|
195
280
|
end
|
196
|
-
#--}}}
|
197
281
|
end
|
198
282
|
|
199
|
-
def fuzzy
|
200
|
-
#--{{{
|
283
|
+
def fuzzy(word)
|
201
284
|
result = word.to_s.downcase
|
202
285
|
close_enough.each do |charset, replace|
|
203
|
-
result.gsub!
|
286
|
+
result.gsub!(%r"[#{ charset }]", replace)
|
204
287
|
end
|
205
|
-
result
|
206
|
-
#--}}}
|
288
|
+
result.upcase.strip
|
207
289
|
end
|
208
290
|
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
attribute 'input_west'
|
291
|
+
def fuzzy_match(a, b)
|
292
|
+
fuzzy(a) == fuzzy(b)
|
293
|
+
end
|
213
294
|
|
214
|
-
def input
|
215
|
-
|
216
|
-
kw.to_options!
|
295
|
+
def input(options = {})
|
296
|
+
options = Raptcha.normalize(options)
|
217
297
|
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
298
|
+
options[:route] ||= Raptcha.route
|
299
|
+
options[:word] ||= Raptcha.word
|
300
|
+
options[:timebomb] ||= Raptcha.timebomb
|
301
|
+
options[:gravity] ||= Raptcha.gravity
|
222
302
|
|
223
|
-
encrypted_word = encrypt
|
224
|
-
encrypted_timebomb = encrypt
|
303
|
+
encrypted_word = Encryptor.encrypt(options[:word])
|
304
|
+
encrypted_timebomb = Encryptor.encrypt(options[:timebomb])
|
225
305
|
|
226
306
|
west = north = east = south = nil
|
307
|
+
|
227
308
|
case gravity.to_s
|
228
309
|
when /w(est)?/
|
229
|
-
west = Raptcha.img(
|
310
|
+
west = Raptcha.img(options)
|
230
311
|
when /n(orth)?/
|
231
|
-
north = Raptcha.img(
|
312
|
+
north = Raptcha.img(options) + '<br>'
|
232
313
|
when /e(ast)?/
|
233
|
-
east = Raptcha.img(
|
314
|
+
east = Raptcha.img(options)
|
234
315
|
when /s(outh)?/
|
235
|
-
south = '<br>' + Raptcha.img(
|
316
|
+
south = '<br>' + Raptcha.img(options)
|
236
317
|
end
|
237
318
|
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
319
|
+
html =
|
320
|
+
<<-html
|
321
|
+
<div class="raptcha">
|
322
|
+
#{ north } #{ west }
|
323
|
+
<input type="textarea" name="raptcha[t]" value="" class="raptcha-input"/>
|
324
|
+
<input type="hidden" name="raptcha[w]" value="#{ encrypted_word }" class="raptcha-word"/>
|
325
|
+
<input type="hidden" name="raptcha[b]" value="#{ encrypted_timebomb }" class="raptcha-timebomb"/>
|
326
|
+
#{ east } #{ south }
|
327
|
+
</div>
|
328
|
+
html
|
329
|
+
|
330
|
+
singleton_class =
|
331
|
+
class << html
|
332
|
+
self
|
333
|
+
end
|
334
|
+
word = options[:word]
|
335
|
+
singleton_class.send(:define_method, :word){ word }
|
249
336
|
|
250
|
-
|
337
|
+
html
|
251
338
|
end
|
252
339
|
alias_method "tag", "input"
|
253
340
|
|
254
|
-
def img
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
html
|
264
|
-
#--}}}
|
341
|
+
def img(options = {})
|
342
|
+
options = Raptcha.normalize(options)
|
343
|
+
return(inline(options)) if options[:inline]
|
344
|
+
route = options[:route] || Raptcha.route
|
345
|
+
word = options[:word] || Raptcha.word
|
346
|
+
encrypted_word = Encryptor.encrypt(word)
|
347
|
+
%[
|
348
|
+
<img src="#{ route }?e=#{ encrypted_word }" alt="raptcha.png" class="raptcha-image"/>
|
349
|
+
]
|
265
350
|
end
|
266
351
|
|
267
|
-
def inline
|
268
|
-
|
269
|
-
|
270
|
-
<img src="data:image/png;base64,#{ Image.inline
|
271
|
-
|
272
|
-
#--}}}
|
352
|
+
def inline(options = {})
|
353
|
+
options = Raptcha.normalize(options)
|
354
|
+
%[
|
355
|
+
<img src="data:image/png;base64,#{ Image.inline(options) }" alt="raptcha.png" class="raptcha-image"/>
|
356
|
+
]
|
273
357
|
end
|
274
358
|
|
275
359
|
def timebomb
|
276
|
-
#--{{{
|
277
360
|
Time.now.utc.to_i + Raptcha.ttl
|
278
|
-
#--}}}
|
279
361
|
end
|
280
362
|
|
281
|
-
def word
|
282
|
-
|
283
|
-
|
284
|
-
|
363
|
+
def word(size = 6)
|
364
|
+
word = ''
|
365
|
+
size.times{ word << alphabet[rand(alphabet.size - 1)]}
|
366
|
+
word
|
285
367
|
end
|
286
368
|
|
287
|
-
def
|
288
|
-
|
289
|
-
Raptcha::Image.create *a, &b
|
290
|
-
#--}}}
|
369
|
+
def alphabet
|
370
|
+
@alphabet ||= ('A' .. 'Z').to_a
|
291
371
|
end
|
292
372
|
|
293
|
-
def
|
294
|
-
|
295
|
-
return @mac_address if defined? @mac_address
|
296
|
-
re = %r/[^:\-](?:[0-9A-F][0-9A-F][:\-]){5}[0-9A-F][0-9A-F][^:\-]/io
|
297
|
-
cmds = '/sbin/ifconfig', '/bin/ifconfig', 'ifconfig', 'ipconfig /all'
|
298
|
-
|
299
|
-
null = test(?e, '/dev/null') ? '/dev/null' : 'NUL'
|
300
|
-
|
301
|
-
lines = nil
|
302
|
-
cmds.each do |cmd|
|
303
|
-
stdout = IO.popen("#{ cmd } 2> #{ null }"){|fd| fd.readlines} rescue next
|
304
|
-
next unless stdout and stdout.size > 0
|
305
|
-
lines = stdout and break
|
306
|
-
end
|
307
|
-
raise "all of #{ cmds.join ' ' } failed" unless lines
|
308
|
-
|
309
|
-
candidates = lines.select{|line| line =~ re}
|
310
|
-
raise 'no mac address candidates' unless candidates.first
|
311
|
-
candidates.map!{|c| c[re]}
|
312
|
-
|
313
|
-
maddr = candidates.first
|
314
|
-
raise 'no mac address found' unless maddr
|
315
|
-
|
316
|
-
maddr.strip!
|
317
|
-
maddr.instance_eval{ @list = candidates; def list() @list end }
|
318
|
-
|
319
|
-
@mac_address = maddr
|
320
|
-
#--}}}
|
321
|
-
end
|
322
|
-
|
323
|
-
def blowfish
|
324
|
-
#--{{{
|
325
|
-
@blowfish ||= Hash.new{|h,k| h[k] = Crypt::Blowfish.new(k)}
|
326
|
-
#--}}}
|
327
|
-
end
|
328
|
-
|
329
|
-
def encrypt string, kw = {}
|
330
|
-
#--{{{
|
331
|
-
kw.to_options!
|
332
|
-
k = kw[:key] || key
|
333
|
-
Base64.encode64(blowfish[k].encrypt_string(string.to_s)).chop # kill "\n"
|
334
|
-
#--}}}
|
335
|
-
end
|
336
|
-
|
337
|
-
def decrypt string, kw = {}
|
338
|
-
#--{{{
|
339
|
-
kw.to_options!
|
340
|
-
k = kw[:key] || key
|
341
|
-
blowfish[k].decrypt_string(Base64.decode64("#{ string }\n")).strip
|
342
|
-
#--}}}
|
373
|
+
def image(*args, &block)
|
374
|
+
Raptcha::Image.create(*args, &block)
|
343
375
|
end
|
344
376
|
|
345
|
-
|
346
|
-
def render controller, params
|
347
|
-
#--{{{
|
377
|
+
def render(controller, params)
|
348
378
|
controller.instance_eval do
|
349
|
-
send_data
|
379
|
+
send_data(Raptcha.image(params), :type => 'image/png', :disposition => 'inline', :filename => 'raptcha.png')
|
350
380
|
end
|
351
|
-
#--}}}
|
352
381
|
end
|
353
382
|
end
|
354
|
-
#--}}}
|
355
383
|
end
|
356
384
|
|
357
385
|
|
358
|
-
if $0 == __FILE__
|
359
|
-
#--{{{
|
360
|
-
(( Main = Object.new )).instance_eval do
|
361
|
-
def run
|
362
|
-
@argv = ARGV.dup
|
363
|
-
mode = @argv.detect{|arg| arg !~ %r"[=:]"} || 'raptcha'
|
364
|
-
@argv.delete mode
|
365
|
-
send mode
|
366
|
-
end
|
367
386
|
|
368
|
-
def raptcha
|
369
|
-
kw = {}
|
370
|
-
@argv.each{|kv| k, v = kv.split(%r"[=:]").map{|x| x.strip}; kw.update k => v}
|
371
|
-
STDOUT.write Raptcha.image(kw)
|
372
|
-
end
|
373
387
|
|
374
|
-
def generate
|
375
|
-
what = @argv.shift
|
376
|
-
send "generate_#{ what }"
|
377
|
-
end
|
378
388
|
|
379
|
-
def generate_controller
|
380
|
-
src = DATA.read
|
381
|
-
if test ?d, 'app'
|
382
|
-
path = File.join 'app', 'controllers', 'raptcha_controller.rb'
|
383
|
-
if test ?e, path
|
384
|
-
puts "exists #{ path }"
|
385
|
-
exit 1
|
386
|
-
end
|
387
|
-
open path, 'w' do |fd|
|
388
|
-
fd.puts src
|
389
|
-
end
|
390
|
-
puts "#{ path }"
|
391
|
-
else
|
392
|
-
puts "generated #{ src }"
|
393
|
-
end
|
394
|
-
end
|
395
389
|
|
396
|
-
def generate_lib
|
397
|
-
src = IO.read(__FILE__)
|
398
|
-
if test ?d, 'app'
|
399
|
-
path = File.join 'lib', 'raptcha.rb'
|
400
|
-
if test ?e, path
|
401
|
-
puts "exists #{ path }"
|
402
|
-
exit 1
|
403
|
-
end
|
404
|
-
open path, 'w' do |fd|
|
405
|
-
fd.puts src
|
406
|
-
end
|
407
|
-
puts "#{ path }"
|
408
|
-
else
|
409
|
-
puts "generated #{ src }"
|
410
|
-
end
|
411
|
-
end
|
412
|
-
end
|
413
|
-
Main.run
|
414
|
-
#--}}}
|
415
|
-
end
|
416
390
|
|
417
|
-
BEGIN {
|
418
|
-
#--{{{
|
419
|
-
unless Hash.new.respond_to? 'to_options' #--{{{
|
420
|
-
def to_options
|
421
|
-
inject(Hash.new){|h, kv| h.update kv.first.to_s.to_sym => kv.last}
|
422
|
-
end
|
423
|
-
def to_options!
|
424
|
-
h = to_options
|
425
|
-
clear
|
426
|
-
update h
|
427
|
-
end
|
428
|
-
end #--}}}
|
429
|
-
|
430
|
-
module Pervasives #--{{{
|
431
|
-
VERSION = "1.0.0" unless defined? Pervasives::VERSION
|
432
|
-
def self.version() VERSION end
|
433
|
-
class ::Class
|
434
|
-
def __pervasive__ m, *a, &b
|
435
|
-
(( Class.instance_method(m) rescue Module.instance_method(m) rescue Object.instance_method(m) )).bind(self).call(*a, &b)
|
436
|
-
end
|
437
|
-
end
|
438
|
-
class ::Module
|
439
|
-
def __pervasive__ m, *a, &b
|
440
|
-
(( Module.instance_method(m) rescue Object.instance_method(m) )).bind(self).call(*a, &b)
|
441
|
-
end
|
442
|
-
end
|
443
|
-
class ::Object
|
444
|
-
def __pervasive__ m, *a, &b
|
445
|
-
(( Object.instance_method(m) )).bind(self).call(*a, &b)
|
446
|
-
end
|
447
|
-
end
|
448
391
|
|
449
|
-
class Proxy
|
450
|
-
instance_methods.each{|m| undef_method m unless m[%r/__/]}
|
451
|
-
def initialize obj
|
452
|
-
@obj = obj
|
453
|
-
end
|
454
|
-
def method_missing m, *a, &b
|
455
|
-
@obj.__pervasive__ m, *a, &b
|
456
|
-
end
|
457
|
-
def __obj__
|
458
|
-
@obj
|
459
|
-
end
|
460
|
-
end
|
461
|
-
end #--}}}
|
462
392
|
|
463
|
-
|
464
|
-
VERSION = '3.5.0'
|
465
|
-
def self.version() VERSION end
|
466
|
-
|
467
|
-
def attributes *a, &b
|
468
|
-
unless a.empty?
|
469
|
-
hashes, names = a.partition{|x| Hash === x}
|
393
|
+
if $0 == __FILE__
|
470
394
|
|
471
|
-
|
472
|
-
|
473
|
-
|
395
|
+
# the command line code
|
396
|
+
#
|
397
|
+
module Raptcha
|
398
|
+
class CLI
|
399
|
+
def CLI.run
|
400
|
+
new.run
|
401
|
+
end
|
474
402
|
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
"@#{ name }", "#{ name }", "#{ name }=", "#{ name }?", "#{ name }!"
|
403
|
+
def initialize(argv = ARGV, env = ENV)
|
404
|
+
@argv = argv.map{|arg| arg.dup}
|
405
|
+
@env = env.to_hash.dup
|
479
406
|
|
480
|
-
|
481
|
-
__pervasive__('instance_variable_set', ivar, value)
|
482
|
-
end
|
407
|
+
@argv, kvs = @argv.partition{|arg| arg !~ /[=:]/}
|
483
408
|
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
defined = __pervasive__('instance_eval', "defined? #{ ivar }")
|
489
|
-
__pervasive__('send', setter, __pervasive__('instance_eval', &init)) unless defined
|
490
|
-
__pervasive__('instance_variable_get', ivar)
|
491
|
-
end
|
409
|
+
@opts = {}
|
410
|
+
kvs.each do |kv|
|
411
|
+
k, v = kv.split(/[=:]/)
|
412
|
+
@opts.update(k.strip => v.strip)
|
492
413
|
end
|
493
414
|
|
494
|
-
|
495
|
-
|
496
|
-
__pervasive__('instance_variable_get', ivar)
|
497
|
-
end
|
415
|
+
@mode = @argv.shift || 'help'
|
416
|
+
end
|
498
417
|
|
499
|
-
|
418
|
+
def run
|
419
|
+
respond_to?(@mode) ? send(@mode) : send(:help)
|
420
|
+
end
|
500
421
|
|
501
|
-
|
502
|
-
|
422
|
+
def help
|
423
|
+
STDERR.puts(README)
|
424
|
+
exit(42)
|
503
425
|
end
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
end
|
512
|
-
klass = self
|
513
|
-
singleton_class.module_eval do
|
514
|
-
attribute_list = []
|
515
|
-
define_method('attribute_list'){ klass == self ? attribute_list : raise(NameError) }
|
516
|
-
alias_method '__attribute_list__', 'attribute_list'
|
426
|
+
|
427
|
+
def image
|
428
|
+
io = @argv.shift || STDOUT
|
429
|
+
opened = false
|
430
|
+
unless io.respond_to?(:write)
|
431
|
+
io = open(io, 'w')
|
432
|
+
opened = true
|
517
433
|
end
|
518
|
-
|
434
|
+
io.write(Raptcha.image(@opts))
|
435
|
+
ensure
|
436
|
+
io.close if opened
|
519
437
|
end
|
520
|
-
end
|
521
|
-
end
|
522
|
-
|
523
|
-
%w( __attributes__ __attribute__ attribute ).each{|dst| alias_method dst, 'attributes'}
|
524
|
-
end
|
525
438
|
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
class << self
|
530
|
-
self
|
439
|
+
def generate
|
440
|
+
what = @argv.shift
|
441
|
+
send("generate_#{ what }")
|
531
442
|
end
|
532
|
-
sc.attributes *a, &b
|
533
|
-
end
|
534
|
-
%w( __attributes__ __attribute__ attribute ).each{|dst| alias_method dst, 'attributes'}
|
535
|
-
end
|
536
|
-
|
537
|
-
class Module
|
538
|
-
include Attributes
|
539
|
-
end #--}}}
|
540
|
-
|
541
|
-
# cbc.rb Richard Kernahan <kernighan_rich@rubyforge.org>
|
542
|
-
module Crypt #--{{{
|
543
|
-
module CBC
|
544
|
-
|
545
|
-
require 'stringio'
|
546
|
-
#require 'crypt/stringxor'
|
547
|
-
|
548
|
-
ULONG = 0x100000000
|
549
|
-
|
550
|
-
# When this module is mixed in with an encryption class, the class
|
551
|
-
# must provide three methods: encrypt_block(block) and decrypt_block(block)
|
552
|
-
# and block_size()
|
553
|
-
|
554
|
-
|
555
|
-
def generate_initialization_vector(words)
|
556
|
-
srand(Time.now.to_i)
|
557
|
-
vector = ""
|
558
|
-
words.times {
|
559
|
-
vector << [rand(ULONG)].pack('N')
|
560
|
-
}
|
561
|
-
return(vector)
|
562
|
-
end
|
563
|
-
|
564
|
-
|
565
|
-
def encrypt_stream(plainStream, cryptStream)
|
566
|
-
# Cypher-block-chain mode
|
567
|
-
|
568
|
-
initVector = generate_initialization_vector(block_size() / 4)
|
569
|
-
chain = encrypt_block(initVector)
|
570
|
-
cryptStream.write(chain)
|
571
|
-
|
572
|
-
while ((block = plainStream.read(block_size())) && (block.length == block_size()))
|
573
|
-
block = block ^ chain
|
574
|
-
encrypted = encrypt_block(block)
|
575
|
-
cryptStream.write(encrypted)
|
576
|
-
chain = encrypted
|
577
|
-
end
|
578
|
-
|
579
|
-
# write the final block
|
580
|
-
# At most block_size()-1 bytes can be part of the message.
|
581
|
-
# That means the final byte can be used to store the number of meaningful
|
582
|
-
# bytes in the final block
|
583
|
-
block = '' if block.nil?
|
584
|
-
buffer = block.split('')
|
585
|
-
remainingMessageBytes = buffer.length
|
586
|
-
# we use 7-bit characters to avoid possible strange behavior on the Mac
|
587
|
-
remainingMessageBytes.upto(block_size()-2) { buffer << rand(128).chr }
|
588
|
-
buffer << remainingMessageBytes.chr
|
589
|
-
block = buffer.join('')
|
590
|
-
block = block ^ chain
|
591
|
-
encrypted = encrypt_block(block)
|
592
|
-
cryptStream.write(encrypted)
|
593
|
-
end
|
594
|
-
|
595
|
-
|
596
|
-
def decrypt_stream(cryptStream, plainStream)
|
597
|
-
# Cypher-block-chain mode
|
598
|
-
chain = cryptStream.read(block_size())
|
599
|
-
|
600
|
-
while (block = cryptStream.read(block_size()))
|
601
|
-
decrypted = decrypt_block(block)
|
602
|
-
plainText = decrypted ^ chain
|
603
|
-
plainStream.write(plainText) unless cryptStream.eof?
|
604
|
-
chain = block
|
605
|
-
end
|
606
|
-
|
607
|
-
# write the final block, omitting the padding
|
608
|
-
buffer = plainText.split('')
|
609
|
-
remainingMessageBytes = buffer.last.unpack('C').first
|
610
|
-
remainingMessageBytes.times { plainStream.write(buffer.shift) }
|
611
|
-
end
|
612
|
-
|
613
|
-
|
614
|
-
def carefully_open_file(filename, mode)
|
615
|
-
begin
|
616
|
-
aFile = File.new(filename, mode)
|
617
|
-
rescue
|
618
|
-
puts "Sorry. There was a problem opening the file <#{filename}>."
|
619
|
-
aFile.close() unless aFile.nil?
|
620
|
-
raise
|
621
|
-
end
|
622
|
-
return(aFile)
|
623
|
-
end
|
624
|
-
|
625
|
-
|
626
|
-
def encrypt_file(plainFilename, cryptFilename)
|
627
|
-
plainFile = carefully_open_file(plainFilename, 'rb')
|
628
|
-
cryptFile = carefully_open_file(cryptFilename, 'wb+')
|
629
|
-
encrypt_stream(plainFile, cryptFile)
|
630
|
-
plainFile.close unless plainFile.closed?
|
631
|
-
cryptFile.close unless cryptFile.closed?
|
632
|
-
end
|
633
|
-
|
634
|
-
|
635
|
-
def decrypt_file(cryptFilename, plainFilename)
|
636
|
-
cryptFile = carefully_open_file(cryptFilename, 'rb')
|
637
|
-
plainFile = carefully_open_file(plainFilename, 'wb+')
|
638
|
-
decrypt_stream(cryptFile, plainFile)
|
639
|
-
cryptFile.close unless cryptFile.closed?
|
640
|
-
plainFile.close unless plainFile.closed?
|
641
|
-
end
|
642
|
-
|
643
|
-
|
644
|
-
def encrypt_string(plainText)
|
645
|
-
plainStream = StringIO.new(plainText)
|
646
|
-
cryptStream = StringIO.new('')
|
647
|
-
encrypt_stream(plainStream, cryptStream)
|
648
|
-
cryptText = cryptStream.string
|
649
|
-
return(cryptText)
|
650
|
-
end
|
651
|
-
|
652
|
-
|
653
|
-
def decrypt_string(cryptText)
|
654
|
-
cryptStream = StringIO.new(cryptText)
|
655
|
-
plainStream = StringIO.new('')
|
656
|
-
decrypt_stream(cryptStream, plainStream)
|
657
|
-
plainText = plainStream.string
|
658
|
-
return(plainText)
|
659
|
-
end
|
660
|
-
|
661
|
-
end
|
662
|
-
end #--}}}
|
663
|
-
|
664
|
-
# blowfish-tables.rb Richard Kernahan <kernighan_rich@rubyforge.org>
|
665
|
-
module Crypt #--{{{
|
666
|
-
module BlowfishTables
|
667
|
-
|
668
|
-
INITIALPARRAY = [
|
669
|
-
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
|
670
|
-
0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
|
671
|
-
0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b
|
672
|
-
]
|
673
|
-
|
674
|
-
INITIALSBOXES = [[
|
675
|
-
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96,
|
676
|
-
0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
|
677
|
-
0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658,
|
678
|
-
0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
|
679
|
-
0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e,
|
680
|
-
0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
|
681
|
-
0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6,
|
682
|
-
0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
|
683
|
-
0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c,
|
684
|
-
0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
|
685
|
-
0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1,
|
686
|
-
0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
|
687
|
-
0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a,
|
688
|
-
0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
|
689
|
-
0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176,
|
690
|
-
0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
|
691
|
-
0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706,
|
692
|
-
0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
|
693
|
-
0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b,
|
694
|
-
0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
|
695
|
-
0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c,
|
696
|
-
0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
|
697
|
-
0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a,
|
698
|
-
0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
|
699
|
-
0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760,
|
700
|
-
0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
|
701
|
-
0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8,
|
702
|
-
0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
|
703
|
-
0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33,
|
704
|
-
0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
|
705
|
-
0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0,
|
706
|
-
0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
|
707
|
-
0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777,
|
708
|
-
0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
|
709
|
-
0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705,
|
710
|
-
0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
|
711
|
-
0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e,
|
712
|
-
0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
|
713
|
-
0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9,
|
714
|
-
0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
|
715
|
-
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f,
|
716
|
-
0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
|
717
|
-
0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a], [
|
718
|
-
0x4b7a70e9, 0xb5b32944,
|
719
|
-
0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
|
720
|
-
0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29,
|
721
|
-
0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
|
722
|
-
0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, 0x4cdd2086, 0x8470eb26,
|
723
|
-
0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
|
724
|
-
0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c,
|
725
|
-
0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
|
726
|
-
0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, 0xd19113f9, 0x7ca92ff6,
|
727
|
-
0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
|
728
|
-
0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, 0xe238cd99, 0x3bea0e2f,
|
729
|
-
0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
|
730
|
-
0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, 0xde9a771f, 0xd9930810,
|
731
|
-
0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
|
732
|
-
0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 0xec7aec3a, 0xdb851dfa,
|
733
|
-
0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
|
734
|
-
0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, 0x71dff89e, 0x10314e55,
|
735
|
-
0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
|
736
|
-
0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, 0xeae96fb1,
|
737
|
-
0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
|
738
|
-
0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, 0xc6150eba, 0x94e2ea78,
|
739
|
-
0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
|
740
|
-
0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883,
|
741
|
-
0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
|
742
|
-
0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, 0x1521b628, 0x29076170,
|
743
|
-
0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
|
744
|
-
0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7,
|
745
|
-
0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
|
746
|
-
0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, 0x9b540b19, 0x875fa099,
|
747
|
-
0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
|
748
|
-
0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x57f584a5, 0x1b227263,
|
749
|
-
0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
|
750
|
-
0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, 0x5d4a14d9, 0xe864b7e3,
|
751
|
-
0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
|
752
|
-
0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 0xd81e799e, 0x86854dc7,
|
753
|
-
0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
|
754
|
-
0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, 0x095bbf00, 0xad19489d,
|
755
|
-
0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
|
756
|
-
0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759, 0xcbee7460,
|
757
|
-
0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
|
758
|
-
0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, 0x9e447a2e, 0xc3453484,
|
759
|
-
0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
|
760
|
-
0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a,
|
761
|
-
0xe6e39f2b, 0xdb83adf7], [
|
762
|
-
0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
|
763
|
-
0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a,
|
764
|
-
0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
|
765
|
-
0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785,
|
766
|
-
0x7fac6dd0, 0x31cb8504, 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
|
767
|
-
0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900,
|
768
|
-
0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
|
769
|
-
0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9,
|
770
|
-
0xee39d7ab, 0x3b124e8b, 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
|
771
|
-
0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397,
|
772
|
-
0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
|
773
|
-
0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9,
|
774
|
-
0x5ef47e1c, 0x9029317c, 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
|
775
|
-
0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f,
|
776
|
-
0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
|
777
|
-
0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e,
|
778
|
-
0xaf664fd1, 0xcad18115, 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
|
779
|
-
0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd,
|
780
|
-
0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
|
781
|
-
0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8,
|
782
|
-
0x991be14c, 0xdb6e6b0d, 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
|
783
|
-
0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c,
|
784
|
-
0xa091cf0b, 0xd9155ea3, 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
|
785
|
-
0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b,
|
786
|
-
0x12754ccc, 0x782ef11c, 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
|
787
|
-
0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386,
|
788
|
-
0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
|
789
|
-
0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0,
|
790
|
-
0x7745ae04, 0xd736fccc, 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
|
791
|
-
0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2,
|
792
|
-
0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
|
793
|
-
0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770,
|
794
|
-
0x8cd55591, 0xc902de4c, 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
|
795
|
-
0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c,
|
796
|
-
0x4a99a025, 0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
|
797
|
-
0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa,
|
798
|
-
0xa002b5c4, 0x0de6d027, 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
|
799
|
-
0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63,
|
800
|
-
0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
|
801
|
-
0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9,
|
802
|
-
0x1ac15bb4, 0xd39eb8fc, 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
|
803
|
-
0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4,
|
804
|
-
0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0], [
|
805
|
-
0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742,
|
806
|
-
0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
|
807
|
-
0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79,
|
808
|
-
0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
|
809
|
-
0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a,
|
810
|
-
0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
|
811
|
-
0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1,
|
812
|
-
0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
|
813
|
-
0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797,
|
814
|
-
0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
|
815
|
-
0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6,
|
816
|
-
0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
|
817
|
-
0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba,
|
818
|
-
0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
|
819
|
-
0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5,
|
820
|
-
0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
|
821
|
-
0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce,
|
822
|
-
0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
|
823
|
-
0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd,
|
824
|
-
0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
|
825
|
-
0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb,
|
826
|
-
0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
|
827
|
-
0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc,
|
828
|
-
0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
|
829
|
-
0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc,
|
830
|
-
0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
|
831
|
-
0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a,
|
832
|
-
0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
|
833
|
-
0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a,
|
834
|
-
0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
|
835
|
-
0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b,
|
836
|
-
0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
|
837
|
-
0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e,
|
838
|
-
0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
|
839
|
-
0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623,
|
840
|
-
0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
|
841
|
-
0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a,
|
842
|
-
0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
|
843
|
-
0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3,
|
844
|
-
0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
|
845
|
-
0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c,
|
846
|
-
0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
|
847
|
-
0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6]
|
848
|
-
]
|
849
|
-
|
850
|
-
|
851
|
-
end
|
852
|
-
end #--}}}
|
853
|
-
|
854
|
-
# blowfish.rb Richard Kernahan <kernighan_rich@rubyforge.org>
|
855
|
-
#
|
856
|
-
# Blowfish algorithm by Bruce Schneider
|
857
|
-
# Ported by Richard Kernahan from the reference C code
|
858
|
-
module Crypt #--{{{
|
859
|
-
class Blowfish
|
860
|
-
|
861
|
-
#require 'crypt/cbc'
|
862
|
-
include Crypt::CBC
|
863
|
-
|
864
|
-
#require 'crypt/blowfish-tables'
|
865
|
-
include Crypt::BlowfishTables
|
866
|
-
|
867
|
-
ULONG = 0x100000000
|
868
|
-
|
869
|
-
def block_size
|
870
|
-
return(8)
|
871
|
-
end
|
872
|
-
|
873
|
-
|
874
|
-
def initialize(key)
|
875
|
-
@key = key
|
876
|
-
raise "Bad key length: the key must be 1-56 bytes." unless (key.length.between?(1,56))
|
877
|
-
@pArray = []
|
878
|
-
@sBoxes = []
|
879
|
-
setup_blowfish()
|
880
|
-
end
|
881
|
-
|
882
|
-
|
883
|
-
def f(x)
|
884
|
-
a, b, c, d = [x].pack('N').unpack('CCCC')
|
885
|
-
y = (@sBoxes[0][a] + @sBoxes[1][b]) % ULONG
|
886
|
-
y = (y ^ @sBoxes[2][c]) % ULONG
|
887
|
-
y = (y + @sBoxes[3][d]) % ULONG
|
888
|
-
return(y)
|
889
|
-
end
|
890
|
-
|
891
|
-
|
892
|
-
def setup_blowfish()
|
893
|
-
@sBoxes = Array.new(4) { |i| INITIALSBOXES[i].clone }
|
894
|
-
@pArray = INITIALPARRAY.clone
|
895
|
-
keypos = 0
|
896
|
-
0.upto(17) { |i|
|
897
|
-
data = 0
|
898
|
-
4.times {
|
899
|
-
data = ((data << 8) | @key[keypos]) % ULONG
|
900
|
-
keypos = (keypos.next) % @key.length
|
901
|
-
}
|
902
|
-
@pArray[i] = (@pArray[i] ^ data) % ULONG
|
903
|
-
}
|
904
|
-
l = 0
|
905
|
-
r = 0
|
906
|
-
0.step(17, 2) { |i|
|
907
|
-
l, r = encrypt_pair(l, r)
|
908
|
-
@pArray[i] = l
|
909
|
-
@pArray[i+1] = r
|
910
|
-
}
|
911
|
-
0.upto(3) { |i|
|
912
|
-
0.step(255, 2) { |j|
|
913
|
-
l, r = encrypt_pair(l, r)
|
914
|
-
@sBoxes[i][j] = l
|
915
|
-
@sBoxes[i][j+1] = r
|
916
|
-
}
|
917
|
-
}
|
918
|
-
end
|
919
|
-
|
920
|
-
def encrypt_pair(xl, xr)
|
921
|
-
0.upto(15) { |i|
|
922
|
-
xl = (xl ^ @pArray[i]) % ULONG
|
923
|
-
xr = (xr ^ f(xl)) % ULONG
|
924
|
-
xl, xr = [xl, xr].reverse
|
925
|
-
}
|
926
|
-
xl, xr = [xl, xr].reverse
|
927
|
-
xr = (xr ^ @pArray[16]) % ULONG
|
928
|
-
xl = (xl ^ @pArray[17]) % ULONG
|
929
|
-
return([xl, xr])
|
930
|
-
end
|
931
|
-
|
932
|
-
|
933
|
-
def decrypt_pair(xl, xr)
|
934
|
-
17.downto(2) { |i|
|
935
|
-
xl = (xl ^ @pArray[i]) % ULONG
|
936
|
-
xr = (xr ^ f(xl)) % ULONG
|
937
|
-
xl, xr = [xl, xr].reverse
|
938
|
-
}
|
939
|
-
xl, xr = [xl, xr].reverse
|
940
|
-
xr = (xr ^ @pArray[1]) % ULONG
|
941
|
-
xl = (xl ^ @pArray[0]) % ULONG
|
942
|
-
return([xl, xr])
|
943
|
-
end
|
944
|
-
|
945
|
-
|
946
|
-
def encrypt_block(block)
|
947
|
-
xl, xr = block.unpack('NN')
|
948
|
-
xl, xr = encrypt_pair(xl, xr)
|
949
|
-
encrypted = [xl, xr].pack('NN')
|
950
|
-
return(encrypted)
|
951
|
-
end
|
952
|
-
|
953
|
-
|
954
|
-
def decrypt_block(block)
|
955
|
-
xl, xr = block.unpack('NN')
|
956
|
-
xl, xr = decrypt_pair(xl, xr)
|
957
|
-
decrypted = [xl, xr].pack('NN')
|
958
|
-
return(decrypted)
|
959
|
-
end
|
960
|
-
|
961
|
-
end
|
962
|
-
end #--}}}
|
963
|
-
|
964
|
-
# gost.rb
|
965
|
-
# Adapted by Richard Kernahan <kernighan_rich@rubyforge.org>
|
966
|
-
# from C++ code written by Wei Dai
|
967
|
-
# of the Crypto++ project http://www.eskimo.com/~weidai/cryptlib.html
|
968
|
-
module Crypt #--{{{
|
969
|
-
class Gost
|
970
|
-
|
971
|
-
#require 'crypt/cbc'
|
972
|
-
include CBC
|
973
|
-
|
974
|
-
ULONG = 0x100000000
|
975
|
-
|
976
|
-
def block_size
|
977
|
-
return(8)
|
978
|
-
end
|
979
|
-
|
980
|
-
|
981
|
-
def initialize(userKey)
|
982
|
-
|
983
|
-
# These are the S-boxes given in Applied Cryptography 2nd Ed., p. 333
|
984
|
-
@sBox = [
|
985
|
-
[4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3],
|
986
|
-
[14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9],
|
987
|
-
[5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11],
|
988
|
-
[7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3],
|
989
|
-
[6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2],
|
990
|
-
[4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14],
|
991
|
-
[13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12],
|
992
|
-
[1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12]
|
993
|
-
]
|
994
|
-
|
995
|
-
# These are the S-boxes given in the GOST source code listing in Applied
|
996
|
-
# Cryptography 2nd Ed., p. 644. They appear to be from the DES S-boxes
|
997
|
-
# [13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7 ],
|
998
|
-
# [ 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1 ],
|
999
|
-
# [12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11 ],
|
1000
|
-
# [ 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9 ],
|
1001
|
-
# [ 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15 ],
|
1002
|
-
# [10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8 ],
|
1003
|
-
# [15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10 ],
|
1004
|
-
# [14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7 ]
|
1005
|
-
|
1006
|
-
# precalculate the S table
|
1007
|
-
@sTable = precalculate_S_table()
|
1008
|
-
|
1009
|
-
# derive the 32-byte key from the user-supplied key
|
1010
|
-
userKeyLength = userKey.length
|
1011
|
-
@key = userKey[0..31].unpack('C'*32)
|
1012
|
-
if (userKeyLength < 32)
|
1013
|
-
userKeyLength.upto(31) { @key << 0 }
|
1014
|
-
end
|
1015
|
-
end
|
1016
|
-
|
1017
|
-
|
1018
|
-
def precalculate_S_table()
|
1019
|
-
sTable = [[], [], [], []]
|
1020
|
-
0.upto(3) { |i|
|
1021
|
-
0.upto(255) { |j|
|
1022
|
-
t = @sBox[2*i][j % 16] | (@sBox[2*i+1][j/16] << 4)
|
1023
|
-
u = (8*i + 11) % 32
|
1024
|
-
v = (t << u) | (t >> (32-u))
|
1025
|
-
sTable[i][j] = (v % ULONG)
|
1026
|
-
}
|
1027
|
-
}
|
1028
|
-
return(sTable)
|
1029
|
-
end
|
1030
|
-
|
1031
|
-
|
1032
|
-
def f(longWord)
|
1033
|
-
longWord = longWord % ULONG
|
1034
|
-
a, b, c, d = [longWord].pack('L').unpack('CCCC')
|
1035
|
-
return(@sTable[3][d] ^ @sTable[2][c] ^ @sTable[1][b] ^ @sTable[0][a])
|
1036
|
-
end
|
1037
|
-
|
1038
|
-
|
1039
|
-
def encrypt_pair(xl, xr)
|
1040
|
-
3.times {
|
1041
|
-
xr ^= f(xl+@key[0])
|
1042
|
-
xl ^= f(xr+@key[1])
|
1043
|
-
xr ^= f(xl+@key[2])
|
1044
|
-
xl ^= f(xr+@key[3])
|
1045
|
-
xr ^= f(xl+@key[4])
|
1046
|
-
xl ^= f(xr+@key[5])
|
1047
|
-
xr ^= f(xl+@key[6])
|
1048
|
-
xl ^= f(xr+@key[7])
|
1049
|
-
}
|
1050
|
-
xr ^= f(xl+@key[7])
|
1051
|
-
xl ^= f(xr+@key[6])
|
1052
|
-
xr ^= f(xl+@key[5])
|
1053
|
-
xl ^= f(xr+@key[4])
|
1054
|
-
xr ^= f(xl+@key[3])
|
1055
|
-
xl ^= f(xr+@key[2])
|
1056
|
-
xr ^= f(xl+@key[1])
|
1057
|
-
xl ^= f(xr+@key[0])
|
1058
|
-
return([xr, xl])
|
1059
|
-
end
|
1060
|
-
|
1061
|
-
|
1062
|
-
def decrypt_pair(xl, xr)
|
1063
|
-
xr ^= f(xl+@key[0])
|
1064
|
-
xl ^= f(xr+@key[1])
|
1065
|
-
xr ^= f(xl+@key[2])
|
1066
|
-
xl ^= f(xr+@key[3])
|
1067
|
-
xr ^= f(xl+@key[4])
|
1068
|
-
xl ^= f(xr+@key[5])
|
1069
|
-
xr ^= f(xl+@key[6])
|
1070
|
-
xl ^= f(xr+@key[7])
|
1071
|
-
3.times {
|
1072
|
-
xr ^= f(xl+@key[7])
|
1073
|
-
xl ^= f(xr+@key[6])
|
1074
|
-
xr ^= f(xl+@key[5])
|
1075
|
-
xl ^= f(xr+@key[4])
|
1076
|
-
xr ^= f(xl+@key[3])
|
1077
|
-
xl ^= f(xr+@key[2])
|
1078
|
-
xr ^= f(xl+@key[1])
|
1079
|
-
xl ^= f(xr+@key[0])
|
1080
|
-
}
|
1081
|
-
return([xr, xl])
|
1082
|
-
end
|
1083
|
-
|
1084
|
-
|
1085
|
-
def encrypt_block(block)
|
1086
|
-
xl, xr = block.unpack('NN')
|
1087
|
-
xl, xr = encrypt_pair(xl, xr)
|
1088
|
-
encrypted = [xl, xr].pack('NN')
|
1089
|
-
return(encrypted)
|
1090
|
-
end
|
1091
|
-
|
1092
|
-
|
1093
|
-
def decrypt_block(block)
|
1094
|
-
xl, xr = block.unpack('NN')
|
1095
|
-
xl, xr = decrypt_pair(xl, xr)
|
1096
|
-
decrypted = [xl, xr].pack('NN')
|
1097
|
-
return(decrypted)
|
1098
|
-
end
|
1099
443
|
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1104
|
-
# idea.rb Richard Kernahan <kernighan_rich@rubyforge.org>
|
1105
|
-
# IDEA (International Data Encryption Algorithm) by
|
1106
|
-
# Xuejia Lai and James Massey (1992). Refer to license info at end.
|
1107
|
-
# Ported by Richard Kernahan 2005
|
1108
|
-
module Crypt #--{{{
|
1109
|
-
class IDEA
|
1110
|
-
|
1111
|
-
#require 'crypt/cbc'
|
1112
|
-
include Crypt::CBC
|
1113
|
-
|
1114
|
-
require 'digest/md5'
|
1115
|
-
|
1116
|
-
ULONG = 0x100000000
|
1117
|
-
USHORT = 0x10000
|
1118
|
-
|
1119
|
-
ENCRYPT = 0
|
1120
|
-
DECRYPT = 1
|
1121
|
-
|
1122
|
-
|
1123
|
-
def block_size
|
1124
|
-
return(8)
|
1125
|
-
end
|
1126
|
-
|
1127
|
-
|
1128
|
-
def initialize(key128, mode)
|
1129
|
-
# IDEA is subject to attack unless the key is sufficiently random, so we
|
1130
|
-
# take an MD5 digest of a variable-length passphrase to ensure a solid key
|
1131
|
-
if (key128.class == String)
|
1132
|
-
digest = Digest::MD5.new(key128).digest
|
1133
|
-
key128 = digest.unpack('n'*8)
|
1134
|
-
end
|
1135
|
-
raise "Key must be 128 bits (8 words)" unless (key128.class == Array) && (key128.length == 8)
|
1136
|
-
raise "Mode must be IDEA::ENCRYPT or IDEA::DECRYPT" unless ((mode == ENCRYPT) | (mode == DECRYPT))
|
1137
|
-
if (mode == ENCRYPT)
|
1138
|
-
@subkeys = generate_encryption_subkeys(key128)
|
1139
|
-
else (mode == DECRYPT)
|
1140
|
-
@subkeys = generate_decryption_subkeys(key128)
|
1141
|
-
end
|
1142
|
-
end
|
1143
|
-
|
1144
|
-
|
1145
|
-
def mul(a, b)
|
1146
|
-
modulus = 0x10001
|
1147
|
-
return((1 - b) % USHORT) if (a == 0)
|
1148
|
-
return((1 - a) % USHORT) if (b == 0)
|
1149
|
-
return((a * b) % modulus)
|
1150
|
-
end
|
1151
|
-
|
1152
|
-
|
1153
|
-
def mulInv(x)
|
1154
|
-
modulus = 0x10001
|
1155
|
-
x = x.to_i % USHORT
|
1156
|
-
return(x) if (x <= 1)
|
1157
|
-
t1 = USHORT / x
|
1158
|
-
y = modulus % x
|
1159
|
-
if (y == 1)
|
1160
|
-
inv = (1 - t1) & 0xFFFF
|
1161
|
-
return(inv)
|
1162
|
-
end
|
1163
|
-
t0 = 1
|
1164
|
-
while (y != 1)
|
1165
|
-
q = x / y
|
1166
|
-
x = x % y
|
1167
|
-
t0 = t0 + (q * t1)
|
1168
|
-
return(t0) if (x == 1)
|
1169
|
-
q = y / x
|
1170
|
-
y = y % x
|
1171
|
-
t1 = t1 + (q * t0)
|
1172
|
-
end
|
1173
|
-
inv = (1 - t1) & 0xFFFF
|
1174
|
-
return(inv)
|
1175
|
-
end
|
1176
|
-
|
1177
|
-
|
1178
|
-
def generate_encryption_subkeys(key)
|
1179
|
-
encrypt_keys = []
|
1180
|
-
encrypt_keys[0..7] = key.dup
|
1181
|
-
8.upto(51) { |i|
|
1182
|
-
a = ((i + 1) % 8 > 0) ? (i-7) : (i-15)
|
1183
|
-
b = ((i + 2) % 8 < 2) ? (i-14) : (i-6)
|
1184
|
-
encrypt_keys[i] = ((encrypt_keys[a] << 9) | (encrypt_keys[b] >> 7)) % USHORT
|
1185
|
-
}
|
1186
|
-
return(encrypt_keys)
|
1187
|
-
end
|
1188
|
-
|
1189
|
-
|
1190
|
-
def generate_decryption_subkeys(key)
|
1191
|
-
encrypt_keys = generate_encryption_subkeys(key)
|
1192
|
-
decrypt_keys = []
|
1193
|
-
decrypt_keys[48] = mulInv(encrypt_keys.shift)
|
1194
|
-
decrypt_keys[49] = (-encrypt_keys.shift) % USHORT
|
1195
|
-
decrypt_keys[50] = (-encrypt_keys.shift) % USHORT
|
1196
|
-
decrypt_keys[51] = mulInv(encrypt_keys.shift)
|
1197
|
-
42.step(0, -6) { |i|
|
1198
|
-
decrypt_keys[i+4] = encrypt_keys.shift % USHORT
|
1199
|
-
decrypt_keys[i+5] = encrypt_keys.shift % USHORT
|
1200
|
-
decrypt_keys[i] = mulInv(encrypt_keys.shift)
|
1201
|
-
if (i ==0)
|
1202
|
-
decrypt_keys[1] = (-encrypt_keys.shift) % USHORT
|
1203
|
-
decrypt_keys[2] = (-encrypt_keys.shift) % USHORT
|
1204
|
-
else
|
1205
|
-
decrypt_keys[i+2] = (-encrypt_keys.shift) % USHORT
|
1206
|
-
decrypt_keys[i+1] = (-encrypt_keys.shift) % USHORT
|
444
|
+
def rails_root?(&block)
|
445
|
+
boolean = test(?d, 'app') && test(?d, 'app/controllers')
|
446
|
+
return boolean unless block
|
447
|
+
boolean ? block.call() : abort('run this in a RAILS_ROOT')
|
1207
448
|
end
|
1208
|
-
decrypt_keys[i+3] = mulInv(encrypt_keys.shift)
|
1209
|
-
}
|
1210
|
-
return(decrypt_keys)
|
1211
|
-
end
|
1212
|
-
|
1213
|
-
|
1214
|
-
def crypt_pair(l, r)
|
1215
|
-
word = [l, r].pack('NN').unpack('nnnn')
|
1216
|
-
k = @subkeys[0..51]
|
1217
|
-
8.downto(1) { |i|
|
1218
|
-
word[0] = mul(word[0], k.shift)
|
1219
|
-
word[1] = (word[1] + k.shift) % USHORT
|
1220
|
-
word[2] = (word[2] + k.shift) % USHORT
|
1221
|
-
word[3] = mul(word[3], k.shift)
|
1222
|
-
t2 = word[0] ^ word[2]
|
1223
|
-
t2 = mul(t2, k.shift)
|
1224
|
-
t1 = (t2 + (word[1] ^ word[3])) % USHORT
|
1225
|
-
t1 = mul(t1, k.shift)
|
1226
|
-
t2 = (t1 + t2) % USHORT
|
1227
|
-
word[0] ^= t1
|
1228
|
-
word[3] ^= t2
|
1229
|
-
t2 ^= word[1]
|
1230
|
-
word[1] = word[2] ^ t1
|
1231
|
-
word[2] = t2
|
1232
|
-
}
|
1233
|
-
result = []
|
1234
|
-
result << mul(word[0], k.shift)
|
1235
|
-
result << (word[2] + k.shift) % USHORT
|
1236
|
-
result << (word[1] + k.shift) % USHORT
|
1237
|
-
result << mul(word[3], k.shift)
|
1238
|
-
twoLongs = result.pack('nnnn').unpack('NN')
|
1239
|
-
return(twoLongs)
|
1240
|
-
end
|
1241
|
-
|
1242
|
-
def encrypt_block(block)
|
1243
|
-
xl, xr = block.unpack('NN')
|
1244
|
-
xl, xr = crypt_pair(xl, xr)
|
1245
|
-
encrypted = [xl, xr].pack('NN')
|
1246
|
-
return(encrypted)
|
1247
|
-
end
|
1248
|
-
|
1249
|
-
|
1250
|
-
def decrypt_block(block)
|
1251
|
-
xl, xr = block.unpack('NN')
|
1252
|
-
xl, xr = crypt_pair(xl, xr)
|
1253
|
-
decrypted = [xl, xr].pack('NN')
|
1254
|
-
return(decrypted)
|
1255
|
-
end
|
1256
449
|
|
450
|
+
def generate_controller
|
451
|
+
src = DATA.read.strip
|
1257
452
|
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1261
|
-
#
|
1262
|
-
|
1263
|
-
|
1264
|
-
|
1265
|
-
#
|
1266
|
-
|
1267
|
-
# and use of same" (hereinafter referred to as "the algorithm"). Any use of
|
1268
|
-
# the algorithm for commercial purposes is thus subject to a license from Ascom
|
1269
|
-
# Systec Ltd. of CH-5506 Maegenwil (Switzerland), being the patentee and sole
|
1270
|
-
# owner of all rights, including the trademark IDEA.
|
1271
|
-
#
|
1272
|
-
# Commercial purposes shall mean any revenue generating purpose including but
|
1273
|
-
# not limited to:
|
1274
|
-
#
|
1275
|
-
# i) Using the algorithm for company internal purposes (subject to a site
|
1276
|
-
# license).
|
1277
|
-
#
|
1278
|
-
# ii) Incorporating the algorithm into any software and distributing such
|
1279
|
-
# software and/or providing services relating thereto to others (subject to
|
1280
|
-
# a product license).
|
1281
|
-
#
|
1282
|
-
# iii) Using a product containing the algorithm not covered by an IDEA license
|
1283
|
-
# (subject to an end user license).
|
1284
|
-
#
|
1285
|
-
# All such end user license agreements are available exclusively from Ascom
|
1286
|
-
# Systec Ltd and may be requested via the WWW at http://www.ascom.ch/systec or
|
1287
|
-
# by email to idea@ascom.ch.
|
1288
|
-
#
|
1289
|
-
# Use other than for commercial purposes is strictly limited to non-revenue
|
1290
|
-
# generating data transfer between private individuals. The use by government
|
1291
|
-
# agencies, non-profit organizations, etc is considered as use for commercial
|
1292
|
-
# purposes but may be subject to special conditions. Any misuse will be
|
1293
|
-
# prosecuted.
|
1294
|
-
|
1295
|
-
# crypt/rattle.rb Richard Kernahan <kernighan_rich@rubyforge.org>
|
1296
|
-
|
1297
|
-
# add_noise - take a message and intersperse noise to make a new noisy message of given byte-length
|
1298
|
-
# remove_noise - take a noisy message and extract the message
|
1299
|
-
module Crypt #--{{{
|
1300
|
-
module Noise
|
1301
|
-
|
1302
|
-
def add_noise(newLength)
|
1303
|
-
message = self
|
1304
|
-
usableNoisyMessageLength = newLength / 9 * 8
|
1305
|
-
bitmapSize = newLength / 9
|
1306
|
-
remainingBytes = newLength - usableNoisyMessageLength - bitmapSize
|
1307
|
-
if (message.length > usableNoisyMessageLength)
|
1308
|
-
minimumNewLength = (message.length / 8.0).ceil * 9
|
1309
|
-
puts "For a clear text of #{message.length} bytes, the minimum obscured length"
|
1310
|
-
puts "is #{minimumNewLength} bytes which allows for no noise in the message."
|
1311
|
-
puts "You should choose an obscured length of at least double the clear text"
|
1312
|
-
puts "length, such as #{message.length / 8 * 32} bytes"
|
1313
|
-
raise "Insufficient length for noisy message"
|
1314
|
-
end
|
1315
|
-
bitmap = []
|
1316
|
-
usableNoisyMessageLength.times { bitmap << false }
|
1317
|
-
srand(Time.now.to_i)
|
1318
|
-
positionsSelected = 0
|
1319
|
-
while (positionsSelected < message.length)
|
1320
|
-
positionTaken = rand(usableNoisyMessageLength)
|
1321
|
-
if bitmap[positionTaken]
|
1322
|
-
next
|
1323
|
-
else
|
1324
|
-
bitmap[positionTaken] = true
|
1325
|
-
positionsSelected = positionsSelected.next
|
1326
|
-
end
|
1327
|
-
end
|
1328
|
-
|
1329
|
-
noisyMessage = ""
|
1330
|
-
0.upto(bitmapSize-1) { |byte|
|
1331
|
-
c = 0
|
1332
|
-
0.upto(7) { |bit|
|
1333
|
-
c = c + (1<<bit) if bitmap[byte * 8 + bit]
|
1334
|
-
}
|
1335
|
-
noisyMessage << c.chr
|
1336
|
-
}
|
1337
|
-
posInMessage = 0
|
1338
|
-
0.upto(usableNoisyMessageLength-1) { |pos|
|
1339
|
-
if bitmap[pos]
|
1340
|
-
meaningfulByte = message[posInMessage]
|
1341
|
-
noisyMessage << meaningfulByte
|
1342
|
-
posInMessage = posInMessage.next
|
1343
|
-
else
|
1344
|
-
noiseByte = rand(256).chr
|
1345
|
-
noisyMessage << noiseByte
|
1346
|
-
end
|
1347
|
-
}
|
1348
|
-
remainingBytes.times {
|
1349
|
-
noiseByte = rand(256).chr
|
1350
|
-
noisyMessage << noiseByte
|
1351
|
-
}
|
1352
|
-
return(noisyMessage)
|
1353
|
-
end
|
1354
|
-
|
1355
|
-
|
1356
|
-
def remove_noise
|
1357
|
-
noisyMessage = self
|
1358
|
-
bitmapSize = noisyMessage.length / 9
|
1359
|
-
actualMessageLength = bitmapSize * 8
|
1360
|
-
|
1361
|
-
actualMessageStart = bitmapSize
|
1362
|
-
actualMessageFinish = bitmapSize + actualMessageLength - 1
|
1363
|
-
actualMessage = noisyMessage[actualMessageStart..actualMessageFinish]
|
1364
|
-
|
1365
|
-
bitmap = []
|
1366
|
-
0.upto(bitmapSize - 1) { |byte|
|
1367
|
-
c = noisyMessage[byte]
|
1368
|
-
0.upto(7) { |bit|
|
1369
|
-
bitmap[byte * 8 + bit] = (c[bit] == 1)
|
1370
|
-
}
|
1371
|
-
}
|
1372
|
-
clearMessage = ""
|
1373
|
-
0.upto(actualMessageLength) { |pos|
|
1374
|
-
meaningful = bitmap[pos]
|
1375
|
-
if meaningful
|
1376
|
-
clearMessage << actualMessage[pos]
|
453
|
+
rails_root? do
|
454
|
+
path = File.join 'app', 'controllers', 'raptcha_controller.rb'
|
455
|
+
if test(?e, path)
|
456
|
+
puts "exists #{ path }"
|
457
|
+
exit 1
|
458
|
+
end
|
459
|
+
open(path, 'w'){|fd| fd.puts(src)}
|
460
|
+
puts "#{ path }"
|
461
|
+
end
|
1377
462
|
end
|
1378
|
-
}
|
1379
|
-
return(clearMessage)
|
1380
|
-
end
|
1381
|
-
|
1382
|
-
end
|
1383
|
-
end
|
1384
463
|
|
1385
|
-
|
1386
|
-
|
1387
|
-
end #--}}}
|
1388
|
-
|
1389
|
-
|
1390
|
-
# Thanks to Binky DaClown who wrote this pure-ruby implementation
|
1391
|
-
# http://rubyforge.org/projects/prstringio/
|
1392
|
-
# Apparently CBC does not work well with the C-based stringio
|
1393
|
-
module Crypt #--{{{
|
1394
|
-
class PureRubyStringIO
|
1395
|
-
|
1396
|
-
include Enumerable
|
1397
|
-
|
1398
|
-
SEEK_CUR = IO::SEEK_CUR
|
1399
|
-
SEEK_END = IO::SEEK_END
|
1400
|
-
SEEK_SET = IO::SEEK_SET
|
1401
|
-
|
1402
|
-
@@relayMethods = [:<<, :all?, :any?, :binmode, :close, :close_read, :close_write, :closed?, :closed_read?,
|
1403
|
-
:closed_write?, :collect, :detect, :each, :each_byte, :each_line, :each_with_index,
|
1404
|
-
:entries, :eof, :eof?, :fcntl, :fileno, :find, :find_all, :flush, :fsync, :getc, :gets,
|
1405
|
-
:grep, :include?, :inject, :isatty, :length, :lineno, :lineno=, :map, :max, :member?,
|
1406
|
-
:min, :partition, :path, :pid, :pos, :pos=, :print, :printf, :putc, :puts, :read,
|
1407
|
-
:readchar, :readline, :readlines, :reject, :rewind, :seek, :select, :size, :sort,
|
1408
|
-
:sort_by, :string, :string=, :sync, :sync=, :sysread, :syswrite, :tell, :truncate, :tty?,
|
1409
|
-
:ungetc, :write, :zip]
|
1410
|
-
|
1411
|
-
def self.open(string="", mode="r+")
|
1412
|
-
if block_given? then
|
1413
|
-
sio = new(string, mode)
|
1414
|
-
rc = yield(sio)
|
1415
|
-
sio.close
|
1416
|
-
rc
|
1417
|
-
else
|
1418
|
-
new(string, mode)
|
1419
|
-
end
|
1420
|
-
end
|
1421
|
-
|
1422
|
-
def <<(obj)
|
1423
|
-
requireWritable
|
1424
|
-
write obj
|
1425
|
-
self
|
1426
|
-
end
|
1427
|
-
|
1428
|
-
def binmode
|
1429
|
-
self
|
1430
|
-
end
|
1431
|
-
|
1432
|
-
def close
|
1433
|
-
requireOpen
|
1434
|
-
@sio_closed_read = true
|
1435
|
-
@sio_closed_write = true
|
1436
|
-
self
|
1437
|
-
end
|
1438
|
-
|
1439
|
-
def close_read
|
1440
|
-
raise IOError, "closing non-duplex IO for reading", caller if closed_read?
|
1441
|
-
@sio_closed_read = true
|
1442
|
-
self
|
1443
|
-
end
|
1444
|
-
|
1445
|
-
def close_write
|
1446
|
-
raise IOError, "closing non-duplex IO for writing", caller if closed_write?
|
1447
|
-
@sio_closed_read = true
|
1448
|
-
self
|
1449
|
-
end
|
1450
|
-
|
1451
|
-
def closed?
|
1452
|
-
closed_read? && closed_write?
|
1453
|
-
end
|
1454
|
-
|
1455
|
-
def closed_read?
|
1456
|
-
@sio_closed_read
|
1457
|
-
end
|
1458
|
-
|
1459
|
-
def closed_write?
|
1460
|
-
@sio_closed_write
|
1461
|
-
end
|
1462
|
-
|
1463
|
-
def each(sep_string=$/, &block)
|
1464
|
-
requireReadable
|
1465
|
-
@sio_string.each(sep_string, &block)
|
1466
|
-
@sio_pos = @sio_string.length
|
1467
|
-
end
|
1468
|
-
|
1469
|
-
def each_byte(&block)
|
1470
|
-
requireReadable
|
1471
|
-
@sio_string.each_byte(&block)
|
1472
|
-
@sio_pos = @sio_string.length
|
1473
|
-
end
|
1474
|
-
|
1475
|
-
def eof
|
1476
|
-
requireReadable { @sio_pos >= @sio_string.length }
|
1477
|
-
end
|
1478
|
-
|
1479
|
-
def fcntl(integer_cmd, arg)
|
1480
|
-
raise NotImplementedError, "The fcntl() function is unimplemented on this machine", caller
|
1481
|
-
end
|
1482
|
-
|
1483
|
-
def fileno
|
1484
|
-
nil
|
1485
|
-
end
|
1486
|
-
|
1487
|
-
def flush
|
1488
|
-
self
|
1489
|
-
end
|
1490
|
-
|
1491
|
-
def fsync
|
1492
|
-
0
|
1493
|
-
end
|
1494
|
-
|
1495
|
-
def getc
|
1496
|
-
requireReadable
|
1497
|
-
char = @sio_string[@sio_pos]
|
1498
|
-
@sio_pos += 1 unless char.nil?
|
1499
|
-
char
|
1500
|
-
end
|
1501
|
-
|
1502
|
-
def gets(sep_string=$/)
|
1503
|
-
requireReadable
|
1504
|
-
@sio_lineno += 1
|
1505
|
-
pstart = @sio_pos
|
1506
|
-
@sio_pos = @sio_string.index(sep_string, @sio_pos) || [@sio_string.length, @sio_pos].max
|
1507
|
-
@sio_string[pstart..@sio_pos]
|
1508
|
-
end
|
1509
|
-
|
1510
|
-
def initialize(string="", mode="r+")
|
1511
|
-
@sio_string = string.to_s
|
1512
|
-
@sio_lineno = 0
|
1513
|
-
@mode = mode
|
1514
|
-
@relay = nil
|
1515
|
-
case mode.delete("b")
|
1516
|
-
when "r"
|
1517
|
-
@sio_closed_read = false
|
1518
|
-
@sio_closed_write = true
|
1519
|
-
@sio_pos = 0
|
1520
|
-
when "r+"
|
1521
|
-
@sio_closed_read = false
|
1522
|
-
@sio_closed_write = false
|
1523
|
-
@sio_pos = 0
|
1524
|
-
when "w"
|
1525
|
-
@sio_closed_read = true
|
1526
|
-
@sio_closed_write = false
|
1527
|
-
@sio_pos = 0
|
1528
|
-
@sio_string.replace("")
|
1529
|
-
when "w+"
|
1530
|
-
@sio_closed_read = false
|
1531
|
-
@sio_closed_write = false
|
1532
|
-
@sio_pos = 0
|
1533
|
-
@sio_string.replace("")
|
1534
|
-
when "a"
|
1535
|
-
@sio_closed_read = true
|
1536
|
-
@sio_closed_write = false
|
1537
|
-
@sio_pos = @sio_string.length
|
1538
|
-
when "a+"
|
1539
|
-
@sio_closed_read = false
|
1540
|
-
@sio_closed_write = false
|
1541
|
-
@sio_pos = @sio_string.length
|
1542
|
-
else
|
1543
|
-
raise ArgumentError, "illegal access mode #{mode}", caller
|
1544
|
-
end
|
1545
|
-
end
|
1546
|
-
|
1547
|
-
def isatty
|
1548
|
-
flase
|
1549
|
-
end
|
1550
|
-
|
1551
|
-
def length
|
1552
|
-
@sio_string.length
|
1553
|
-
end
|
1554
|
-
|
1555
|
-
def lineno
|
1556
|
-
@sio_lineno
|
1557
|
-
end
|
1558
|
-
|
1559
|
-
def lineno=(integer)
|
1560
|
-
@sio_lineno = integer
|
1561
|
-
end
|
1562
|
-
|
1563
|
-
def path
|
1564
|
-
nil
|
1565
|
-
end
|
1566
|
-
|
1567
|
-
def pid
|
1568
|
-
nil
|
1569
|
-
end
|
1570
|
-
|
1571
|
-
def pos
|
1572
|
-
@sio_pos
|
1573
|
-
end
|
1574
|
-
|
1575
|
-
def pos=(integer)
|
1576
|
-
raise Errno::EINVAL, "Invalid argument", caller if integer < 0
|
1577
|
-
@sio_pos = integer
|
1578
|
-
end
|
1579
|
-
|
1580
|
-
def print(*args)
|
1581
|
-
requireWritable
|
1582
|
-
args.unshift($_) if args.empty
|
1583
|
-
args.each { |obj| write(obj) }
|
1584
|
-
write($\) unless $\.nil?
|
1585
|
-
nil
|
1586
|
-
end
|
1587
|
-
|
1588
|
-
def printf(format_string, *args)
|
1589
|
-
requireWritable
|
1590
|
-
write format(format_string, *args)
|
1591
|
-
nil
|
1592
|
-
end
|
1593
|
-
|
1594
|
-
def putc(obj)
|
1595
|
-
requireWritable
|
1596
|
-
write(obj.is_a?(Numeric) ? sprintf("%c", obj) : obj.to_s[0..0])
|
1597
|
-
obj
|
1598
|
-
end
|
1599
|
-
|
1600
|
-
def puts(*args)
|
1601
|
-
requireWritable
|
1602
|
-
args.unshift("") if args.empty?
|
1603
|
-
args.each { |obj|
|
1604
|
-
write obj
|
1605
|
-
write $/
|
1606
|
-
}
|
1607
|
-
nil
|
1608
|
-
end
|
1609
|
-
|
1610
|
-
def read(length=nil, buffer=nil)
|
1611
|
-
requireReadable
|
1612
|
-
len = length || [@sio_string.length - @sio_pos, 0].max
|
1613
|
-
raise ArgumentError, "negative length #{len} given", caller if len < 0
|
1614
|
-
buffer ||= ""
|
1615
|
-
pstart = @sio_pos
|
1616
|
-
@sio_pos += len
|
1617
|
-
buffer.replace(@sio_string[pstart..@sio_pos])
|
1618
|
-
buffer.empty? && !length.nil? ? nil : buffer
|
1619
|
-
end
|
1620
|
-
|
1621
|
-
def readchar
|
1622
|
-
requireReadable
|
1623
|
-
raise EOFError, "End of file reached", caller if eof?
|
1624
|
-
getc
|
1625
|
-
end
|
1626
|
-
|
1627
|
-
def readline
|
1628
|
-
requireReadable
|
1629
|
-
raise EOFError, "End of file reached", caller if eof?
|
1630
|
-
gets
|
1631
|
-
end
|
1632
|
-
|
1633
|
-
def readlines(sep_string=$/)
|
1634
|
-
requireReadable
|
1635
|
-
raise EOFError, "End of file reached", caller if eof?
|
1636
|
-
rc = []
|
1637
|
-
until eof
|
1638
|
-
rc << gets(sep_string)
|
1639
|
-
end
|
1640
|
-
rc
|
1641
|
-
end
|
1642
|
-
|
1643
|
-
def reopen(string, mode=nil)
|
1644
|
-
if string.is_a?(self.class) then
|
1645
|
-
raise ArgumentError, "wrong number of arguments (2 for 1)", caller if !mode.nil?
|
1646
|
-
@relay = string
|
1647
|
-
instance_eval(%Q{
|
1648
|
-
class << self
|
1649
|
-
@@relayMethods.each { |name|
|
1650
|
-
define_method(name, ObjectSpace._id2ref(#{@relay.object_id}).method(("original_" + name.to_s).to_sym).to_proc)
|
1651
|
-
}
|
1652
|
-
end
|
1653
|
-
})
|
1654
|
-
else
|
1655
|
-
raise ArgumentError, "wrong number of arguments (1 for 2)", caller if mode.nil?
|
1656
|
-
class << self
|
1657
|
-
@@relayMethods.each { |name|
|
1658
|
-
alias_method(name, "original_#{name}".to_sym)
|
1659
|
-
public name
|
1660
|
-
}
|
1661
|
-
@relay = nil
|
1662
|
-
end unless @relay.nil?
|
1663
|
-
@sio_string = string.to_s
|
1664
|
-
@mode = mode
|
1665
|
-
end
|
1666
|
-
end
|
1667
|
-
|
1668
|
-
def rewind
|
1669
|
-
@sio_pos = 0
|
1670
|
-
@sio_lineno = 0
|
1671
|
-
end
|
1672
|
-
|
1673
|
-
def seek(amount, whence=SEEK_SET)
|
1674
|
-
if whence == SEEK_CUR then
|
1675
|
-
offset += @sio_pos
|
1676
|
-
elsif whence == SEEK_END then
|
1677
|
-
offset += size
|
1678
|
-
end
|
1679
|
-
@sio_pos = offset
|
1680
|
-
end
|
1681
|
-
|
1682
|
-
def string
|
1683
|
-
@sio_string
|
1684
|
-
end
|
1685
|
-
|
1686
|
-
def string=(newstring)
|
1687
|
-
@sio_string = newstring
|
1688
|
-
end
|
1689
|
-
|
1690
|
-
def sync
|
1691
|
-
true
|
1692
|
-
end
|
1693
|
-
|
1694
|
-
def sync=(boolean)
|
1695
|
-
boolean
|
1696
|
-
end
|
1697
|
-
|
1698
|
-
def sysread(length=nil, buffer=nil)
|
1699
|
-
requireReadable
|
1700
|
-
raise EOFError, "End of file reached", caller if eof?
|
1701
|
-
read(length, buffer)
|
1702
|
-
end
|
1703
|
-
|
1704
|
-
def syswrite(string)
|
1705
|
-
requireWritable
|
1706
|
-
addition = "\000" * (@sio_string.length - @sio_pos) + string.to_s
|
1707
|
-
@sio_string[@sio_pos..(addition.length - 1)] = addition
|
1708
|
-
@sio_pos += addition.size
|
1709
|
-
addition.size
|
1710
|
-
end
|
1711
|
-
|
1712
|
-
#In ruby 1.8.4 truncate differs from the docs in two ways.
|
1713
|
-
#First, if an integer greater that the length is given then the string is expanded to the new integer
|
1714
|
-
#length. As this expansion seems to contain junk characters instead of nulls I suspect this may be a
|
1715
|
-
#flaw in the C code which could cause a core dump if abused/used.
|
1716
|
-
#Second, the documentation states that truncate returns 0. It returns the integer instead.
|
1717
|
-
#This implementation follows the documentation in the first instance as I suspect this will be fixed
|
1718
|
-
#in the C code. In the second instance, it follows the actions of the C code instead of the docs.
|
1719
|
-
#This was decided as it causes no immedeate harm and this ruby implentation is to be as compatable
|
1720
|
-
#as possible with the C version. Should the C version change to match the docs the ruby version
|
1721
|
-
#will be simple to update as well.
|
1722
|
-
def truncate(integer)
|
1723
|
-
requireWritable
|
1724
|
-
raise Errno::EINVAL, "Invalid argument - negative length", caller if integer < 0
|
1725
|
-
@sio_string[[integer, @sio_string.length].max..-1] = ""
|
1726
|
-
integer
|
1727
|
-
end
|
1728
|
-
|
1729
|
-
def ungetc(integer)
|
1730
|
-
requireWritable
|
1731
|
-
if @sio_pos > 0 then
|
1732
|
-
@sio_pos -= 1
|
1733
|
-
putc(integer)
|
1734
|
-
@sio_pos -= 1
|
1735
|
-
end
|
1736
|
-
end
|
1737
|
-
|
1738
|
-
alias :each_line :each
|
1739
|
-
alias :eof? :eof
|
1740
|
-
alias :size :length
|
1741
|
-
alias :tty? :isatty
|
1742
|
-
alias :tell :pos
|
1743
|
-
alias :write :syswrite
|
1744
|
-
|
1745
|
-
protected
|
1746
|
-
@@relayMethods.each { |name|
|
1747
|
-
alias_method("original_#{name}".to_sym, name)
|
1748
|
-
protected "original_#{name}".to_sym
|
1749
|
-
}
|
1750
|
-
|
1751
|
-
private
|
1752
|
-
|
1753
|
-
def requireReadable
|
1754
|
-
raise IOError, "not opened for reading", caller[1..-1] if @sio_closed_read
|
1755
|
-
end
|
1756
|
-
|
1757
|
-
def requireWritable
|
1758
|
-
raise IOError, "not opened for writing", caller[1..-1] if @sio_closed_write
|
1759
|
-
end
|
1760
|
-
|
1761
|
-
def requireOpen
|
1762
|
-
raise IOError, "closed stream", caller[1..-1] if @sio_closed_read && @sio_closed_write
|
1763
|
-
end
|
464
|
+
def generate_lib
|
465
|
+
src = IO.read(__FILE__).strip
|
1764
466
|
|
1765
|
-
|
1766
|
-
|
1767
|
-
|
1768
|
-
#
|
1769
|
-
|
1770
|
-
|
1771
|
-
|
1772
|
-
|
1773
|
-
|
1774
|
-
100, 4, 224, 14, 52, 141, 129, 239, 76, 113, 8, 200, 248, 105, 28, 193,
|
1775
|
-
125, 194, 29, 181, 249, 185, 39, 106, 77, 228, 166, 114, 154, 201, 9, 120,
|
1776
|
-
101, 47, 138, 5, 33, 15, 225, 36, 18, 240, 130, 69, 53, 147, 218, 142,
|
1777
|
-
150, 143, 219, 189, 54, 208, 206, 148, 19, 92, 210, 241, 64, 70, 131, 56,
|
1778
|
-
102, 221, 253, 48, 191, 6, 139, 98, 179, 37, 226, 152, 34, 136, 145, 16,
|
1779
|
-
126, 110, 72, 195, 163, 182, 30, 66, 58, 107, 40, 84, 250, 133, 61, 186,
|
1780
|
-
43, 121, 10, 21, 155, 159, 94, 202, 78, 212, 172, 229, 243, 115, 167, 87,
|
1781
|
-
175, 88, 168, 80, 244, 234, 214, 116, 79, 174, 233, 213, 231, 230, 173, 232,
|
1782
|
-
44, 215, 117, 122, 235, 22, 11, 245, 89, 203, 95, 176, 156, 169, 81, 160,
|
1783
|
-
127, 12, 246, 111, 23, 196, 73, 236, 216, 67, 31, 45, 164, 118, 123, 183,
|
1784
|
-
204, 187, 62, 90, 251, 96, 177, 134, 59, 82, 161, 108, 170, 85, 41, 157,
|
1785
|
-
151, 178, 135, 144, 97, 190, 220, 252, 188, 149, 207, 205, 55, 63, 91, 209,
|
1786
|
-
83, 57, 132, 60, 65, 162, 109, 71, 20, 42, 158, 93, 86, 242, 211, 171,
|
1787
|
-
68, 17, 146, 217, 35, 32, 46, 137, 180, 124, 184, 38, 119, 153, 227, 165,
|
1788
|
-
103, 74, 237, 222, 197, 49, 254, 24, 13, 99, 140, 128, 192, 247, 112, 7
|
1789
|
-
]
|
1790
|
-
|
1791
|
-
AlogTable = [
|
1792
|
-
1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53,
|
1793
|
-
95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10, 30, 34, 102, 170,
|
1794
|
-
229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, 112, 144, 171, 230, 49,
|
1795
|
-
83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205,
|
1796
|
-
76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136,
|
1797
|
-
131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154,
|
1798
|
-
181, 196, 87, 249, 16, 48, 80, 240, 11, 29, 39, 105, 187, 214, 97, 163,
|
1799
|
-
254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, 32, 96, 160,
|
1800
|
-
251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65,
|
1801
|
-
195, 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117,
|
1802
|
-
159, 186, 213, 100, 172, 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128,
|
1803
|
-
155, 182, 193, 88, 232, 35, 101, 175, 234, 37, 111, 177, 200, 67, 197, 84,
|
1804
|
-
252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, 202,
|
1805
|
-
69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14,
|
1806
|
-
18, 54, 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23,
|
1807
|
-
57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180, 199, 82, 246, 1
|
1808
|
-
]
|
1809
|
-
|
1810
|
-
S = [
|
1811
|
-
99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118,
|
1812
|
-
202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192,
|
1813
|
-
183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21,
|
1814
|
-
4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117,
|
1815
|
-
9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132,
|
1816
|
-
83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207,
|
1817
|
-
208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168,
|
1818
|
-
81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210,
|
1819
|
-
205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115,
|
1820
|
-
96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219,
|
1821
|
-
224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121,
|
1822
|
-
231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8,
|
1823
|
-
186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138,
|
1824
|
-
112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158,
|
1825
|
-
225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223,
|
1826
|
-
140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22
|
1827
|
-
]
|
1828
|
-
|
1829
|
-
Si = [
|
1830
|
-
82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, 251,
|
1831
|
-
124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, 196, 222, 233, 203,
|
1832
|
-
84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66, 250, 195, 78,
|
1833
|
-
8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, 109, 139, 209, 37,
|
1834
|
-
114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92, 204, 93, 101, 182, 146,
|
1835
|
-
108, 112, 72, 80, 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132,
|
1836
|
-
144, 216, 171, 0, 140, 188, 211, 10, 247, 228, 88, 5, 184, 179, 69, 6,
|
1837
|
-
208, 44, 30, 143, 202, 63, 15, 2, 193, 175, 189, 3, 1, 19, 138, 107,
|
1838
|
-
58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, 115,
|
1839
|
-
150, 172, 116, 34, 231, 173, 53, 133, 226, 249, 55, 232, 28, 117, 223, 110,
|
1840
|
-
71, 241, 26, 113, 29, 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27,
|
1841
|
-
252, 86, 62, 75, 198, 210, 121, 32, 154, 219, 192, 254, 120, 205, 90, 244,
|
1842
|
-
31, 221, 168, 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95,
|
1843
|
-
96, 81, 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239,
|
1844
|
-
160, 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97,
|
1845
|
-
23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, 85, 33, 12, 125,
|
1846
|
-
]
|
1847
|
-
|
1848
|
-
IG = [
|
1849
|
-
[0x0e, 0x09, 0x0d, 0x0b],
|
1850
|
-
[0x0b, 0x0e, 0x09, 0x0d],
|
1851
|
-
[0x0d, 0x0b, 0x0e, 0x09],
|
1852
|
-
[0x09, 0x0d, 0x0b, 0x0e]
|
1853
|
-
]
|
1854
|
-
|
1855
|
-
Rcon = [
|
1856
|
-
0x01, 0x02, 0x04, 0x08, 0x10, 0x20,
|
1857
|
-
0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8,
|
1858
|
-
0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc,
|
1859
|
-
0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4,
|
1860
|
-
0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91
|
1861
|
-
]
|
1862
|
-
|
1863
|
-
Shifts = [
|
1864
|
-
[
|
1865
|
-
[0, 0],
|
1866
|
-
[1, 3],
|
1867
|
-
[2, 2],
|
1868
|
-
[3, 1]
|
1869
|
-
], [
|
1870
|
-
[0, 0],
|
1871
|
-
[1, 5],
|
1872
|
-
[2, 4],
|
1873
|
-
[3, 3]
|
1874
|
-
], [
|
1875
|
-
[0, 0],
|
1876
|
-
[1, 7],
|
1877
|
-
[3, 5],
|
1878
|
-
[4, 4]
|
1879
|
-
]
|
1880
|
-
]
|
1881
|
-
|
1882
|
-
end
|
1883
|
-
end #--}}}
|
1884
|
-
|
1885
|
-
# rijndael.rb Richard Kernahan <kernighan_rich@rubyforge.org>
|
1886
|
-
# Adapted from the reference C implementation:
|
1887
|
-
# rijndael-alg-ref.c v2.2 March 2002
|
1888
|
-
# Reference ANSI C code
|
1889
|
-
# authors: Paulo Barreto and Vincent Rijmen
|
1890
|
-
# This code is placed in the public domain.
|
1891
|
-
module Crypt #--{{{
|
1892
|
-
class Rijndael
|
1893
|
-
|
1894
|
-
#require 'crypt/cbc'
|
1895
|
-
include Crypt::CBC
|
1896
|
-
|
1897
|
-
#require 'crypt/rijndael-tables'
|
1898
|
-
include Crypt::RijndaelTables
|
1899
|
-
|
1900
|
-
|
1901
|
-
def initialize(userKey, keyBits = 256, blockBits = 128)
|
1902
|
-
case keyBits
|
1903
|
-
when 128
|
1904
|
-
@keyWords = 4
|
1905
|
-
when 192
|
1906
|
-
@keyWords = 6
|
1907
|
-
when 256
|
1908
|
-
@keyWords = 8
|
1909
|
-
else raise "The key must be 128, 192, or 256 bits long."
|
1910
|
-
end
|
1911
|
-
|
1912
|
-
case (keyBits >= blockBits) ? keyBits : blockBits
|
1913
|
-
when 128
|
1914
|
-
@rounds = 10
|
1915
|
-
when 192
|
1916
|
-
@rounds = 12
|
1917
|
-
when 256
|
1918
|
-
@rounds = 14
|
1919
|
-
else raise "The key and block sizes must be 128, 192, or 256 bits long."
|
1920
|
-
end
|
1921
|
-
|
1922
|
-
case blockBits
|
1923
|
-
when 128
|
1924
|
-
@blockSize = 16
|
1925
|
-
@blockWords = 4
|
1926
|
-
@shiftIndex = 0
|
1927
|
-
when 192
|
1928
|
-
@blockSize = 24
|
1929
|
-
@blockWords = 6
|
1930
|
-
@shiftIndex = 1
|
1931
|
-
when 256
|
1932
|
-
@blockSize = 32
|
1933
|
-
@blockWords = 8
|
1934
|
-
@shiftIndex = 2
|
1935
|
-
else raise "The block size must be 128, 192, or 256 bits long."
|
1936
|
-
end
|
1937
|
-
|
1938
|
-
uk = userKey.unpack('C'*userKey.length)
|
1939
|
-
maxUsefulSizeOfUserKey = (keyBits/8)
|
1940
|
-
uk = uk[0..maxUsefulSizeOfUserKey-1] # truncate
|
1941
|
-
padding = 0
|
1942
|
-
if (userKey.length < keyBits/8)
|
1943
|
-
shortfallInUserKey = (keyBits/8 - userKey.length)
|
1944
|
-
shortfallInUserKey.times { uk << padding }
|
1945
|
-
end
|
1946
|
-
@key = [[], [], [], []]
|
1947
|
-
0.upto(uk.length-1) { |pos|
|
1948
|
-
@key[pos % 4][pos / 4] = uk[pos]
|
1949
|
-
}
|
1950
|
-
@roundKeys = generate_key_schedule(@key, keyBits, blockBits)
|
1951
|
-
end
|
1952
|
-
|
1953
|
-
|
1954
|
-
def block_size
|
1955
|
-
return(@blockSize) # needed for CBC
|
1956
|
-
end
|
1957
|
-
|
1958
|
-
|
1959
|
-
def mul(a, b)
|
1960
|
-
if ((a ==0) | (b == 0))
|
1961
|
-
result = 0
|
1962
|
-
else
|
1963
|
-
result = AlogTable[(LogTable[a] + LogTable[b]) % 255]
|
1964
|
-
end
|
1965
|
-
return(result)
|
1966
|
-
end
|
1967
|
-
|
1968
|
-
|
1969
|
-
def add_round_key(blockArray, roundKey)
|
1970
|
-
0.upto(3) { |i|
|
1971
|
-
0.upto(@blockWords) { |j|
|
1972
|
-
blockArray[i][j] ^= roundKey[i][j]
|
1973
|
-
}
|
1974
|
-
}
|
1975
|
-
return(blockArray)
|
1976
|
-
end
|
1977
|
-
|
1978
|
-
|
1979
|
-
def shift_rows(blockArray, direction)
|
1980
|
-
tmp = []
|
1981
|
-
1.upto(3) { |i| # row zero remains unchanged
|
1982
|
-
0.upto(@blockWords-1) { |j|
|
1983
|
-
tmp[j] = blockArray[i][(j + Shifts[@shiftIndex][i][direction]) % @blockWords]
|
1984
|
-
}
|
1985
|
-
0.upto(@blockWords-1) { |j|
|
1986
|
-
blockArray[i][j] = tmp[j]
|
1987
|
-
}
|
1988
|
-
}
|
1989
|
-
return(blockArray)
|
1990
|
-
end
|
1991
|
-
|
1992
|
-
|
1993
|
-
def substitution(blockArray, sBox)
|
1994
|
-
# replace every byte of the input with the byte at that position in the S-box
|
1995
|
-
0.upto(3) { |i|
|
1996
|
-
0.upto(@blockWords-1) { |j|
|
1997
|
-
blockArray[i][j] = sBox[blockArray[i][j]]
|
1998
|
-
}
|
1999
|
-
}
|
2000
|
-
return(blockArray)
|
2001
|
-
end
|
2002
|
-
|
2003
|
-
|
2004
|
-
def mix_columns(blockArray)
|
2005
|
-
mixed = [[], [], [], []]
|
2006
|
-
0.upto(@blockWords-1) { |j|
|
2007
|
-
0.upto(3) { |i|
|
2008
|
-
mixed[i][j] = mul(2,blockArray[i][j]) ^
|
2009
|
-
mul(3,blockArray[(i + 1) % 4][j]) ^
|
2010
|
-
blockArray[(i + 2) % 4][j] ^
|
2011
|
-
blockArray[(i + 3) % 4][j]
|
2012
|
-
}
|
2013
|
-
}
|
2014
|
-
return(mixed)
|
2015
|
-
end
|
2016
|
-
|
2017
|
-
|
2018
|
-
def inverse_mix_columns(blockArray)
|
2019
|
-
unmixed = [[], [], [], []]
|
2020
|
-
0.upto(@blockWords-1) { |j|
|
2021
|
-
0.upto(3) { |i|
|
2022
|
-
unmixed[i][j] = mul(0xe, blockArray[i][j]) ^
|
2023
|
-
mul(0xb, blockArray[(i + 1) % 4][j]) ^
|
2024
|
-
mul(0xd, blockArray[(i + 2) % 4][j]) ^
|
2025
|
-
mul(0x9, blockArray[(i + 3) % 4][j])
|
2026
|
-
}
|
2027
|
-
}
|
2028
|
-
return(unmixed)
|
2029
|
-
end
|
2030
|
-
|
2031
|
-
|
2032
|
-
def generate_key_schedule(k, keyBits, blockBits)
|
2033
|
-
tk = k[0..3][0..@keyWords-1] # using slice to get a copy instead of a reference
|
2034
|
-
keySched = []
|
2035
|
-
(@rounds + 1).times { keySched << [[], [], [], []] }
|
2036
|
-
t = 0
|
2037
|
-
j = 0
|
2038
|
-
while ((j < @keyWords) && (t < (@rounds+1)*@blockWords))
|
2039
|
-
0.upto(3) { |i|
|
2040
|
-
keySched[t / @blockWords][i][t % @blockWords] = tk[i][j]
|
2041
|
-
}
|
2042
|
-
j += 1
|
2043
|
-
t += 1
|
2044
|
-
end
|
2045
|
-
# while not enough round key material collected, calculate new values
|
2046
|
-
rconIndex = 0
|
2047
|
-
while (t < (@rounds+1)*@blockWords)
|
2048
|
-
0.upto(3) { |i|
|
2049
|
-
tk[i][0] ^= S[tk[(i + 1) % 4][@keyWords - 1]]
|
2050
|
-
}
|
2051
|
-
tk[0][0] ^= Rcon[rconIndex]
|
2052
|
-
rconIndex = rconIndex.next
|
2053
|
-
if (@keyWords != 8)
|
2054
|
-
1.upto(@keyWords - 1) { |j|
|
2055
|
-
0.upto(3) { |i|
|
2056
|
-
tk[i][j] ^= tk[i][j-1];
|
2057
|
-
}
|
2058
|
-
}
|
2059
|
-
else
|
2060
|
-
1.upto(@keyWords/2 - 1) { |j|
|
2061
|
-
0.upto(3) { |i|
|
2062
|
-
tk[i][j] ^= tk[i][j-1]
|
2063
|
-
}
|
2064
|
-
}
|
2065
|
-
0.upto(3) { |i|
|
2066
|
-
tk[i][@keyWords/2] ^= S[tk[i][@keyWords/2 - 1]]
|
2067
|
-
}
|
2068
|
-
(@keyWords/2 + 1).upto(@keyWords - 1) { |j|
|
2069
|
-
0.upto(3) { |i|
|
2070
|
-
tk[i][j] ^= tk[i][j-1]
|
2071
|
-
}
|
2072
|
-
}
|
2073
|
-
end
|
2074
|
-
j = 0
|
2075
|
-
while ((j < @keyWords) && (t < (@rounds+1) * @blockWords))
|
2076
|
-
0.upto(3) { |i|
|
2077
|
-
keySched[t / @blockWords][i][t % @blockWords] = tk[i][j]
|
2078
|
-
}
|
2079
|
-
j += 1
|
2080
|
-
t += 1
|
467
|
+
rails_root? do
|
468
|
+
path = File.join('lib', 'raptcha.rb')
|
469
|
+
if test(?e, path)
|
470
|
+
puts "exists #{ path }"
|
471
|
+
exit 1
|
472
|
+
end
|
473
|
+
open(path, 'w'){|fd| fd.puts(src)}
|
474
|
+
puts "#{ path }"
|
475
|
+
end
|
2081
476
|
end
|
2082
477
|
end
|
2083
|
-
return(keySched)
|
2084
|
-
end
|
2085
|
-
|
2086
|
-
|
2087
|
-
def encrypt_byte_array(blockArray)
|
2088
|
-
blockArray = add_round_key(blockArray, @roundKeys[0])
|
2089
|
-
1.upto(@rounds - 1) { |round|
|
2090
|
-
blockArray = substitution(blockArray, S)
|
2091
|
-
blockArray = shift_rows(blockArray, 0)
|
2092
|
-
blockArray = mix_columns(blockArray)
|
2093
|
-
blockArray = add_round_key(blockArray, @roundKeys[round])
|
2094
|
-
}
|
2095
|
-
# special round without mix_columns
|
2096
|
-
blockArray = substitution(blockArray,S)
|
2097
|
-
blockArray = shift_rows(blockArray,0)
|
2098
|
-
blockArray = add_round_key(blockArray, @roundKeys[@rounds])
|
2099
|
-
return(blockArray)
|
2100
|
-
end
|
2101
|
-
|
2102
|
-
|
2103
|
-
def encrypt_block(block)
|
2104
|
-
raise "block must be #{@blockSize} bytes long" if (block.length() != @blockSize)
|
2105
|
-
blockArray = [[], [], [], []]
|
2106
|
-
0.upto(@blockSize - 1) { |pos|
|
2107
|
-
blockArray[pos % 4][pos / 4] = block[pos]
|
2108
|
-
}
|
2109
|
-
encryptedBlock = encrypt_byte_array(blockArray)
|
2110
|
-
encrypted = ""
|
2111
|
-
0.upto(@blockSize - 1) { |pos|
|
2112
|
-
encrypted << encryptedBlock[pos % 4][pos / 4]
|
2113
|
-
}
|
2114
|
-
return(encrypted)
|
2115
|
-
end
|
2116
|
-
|
2117
|
-
|
2118
|
-
def decrypt_byte_array(blockArray)
|
2119
|
-
# first special round without inverse_mix_columns
|
2120
|
-
# add_round_key is an involution - applying it a second time returns the original result
|
2121
|
-
blockArray = add_round_key(blockArray, @roundKeys[@rounds])
|
2122
|
-
blockArray = substitution(blockArray,Si) # using inverse S-box
|
2123
|
-
blockArray = shift_rows(blockArray,1)
|
2124
|
-
(@rounds-1).downto(1) { |round|
|
2125
|
-
blockArray = add_round_key(blockArray, @roundKeys[round])
|
2126
|
-
blockArray = inverse_mix_columns(blockArray)
|
2127
|
-
blockArray = substitution(blockArray, Si)
|
2128
|
-
blockArray = shift_rows(blockArray, 1)
|
2129
|
-
}
|
2130
|
-
blockArray = add_round_key(blockArray, @roundKeys[0])
|
2131
|
-
return(blockArray)
|
2132
|
-
end
|
2133
|
-
|
2134
|
-
|
2135
|
-
def decrypt_block(block)
|
2136
|
-
raise "block must be #{@blockSize} bytes long" if (block.length() != @blockSize)
|
2137
|
-
blockArray = [[], [], [], []]
|
2138
|
-
0.upto(@blockSize - 1) { |pos|
|
2139
|
-
blockArray[pos % 4][pos / 4] = block[pos]
|
2140
|
-
}
|
2141
|
-
decryptedBlock = decrypt_byte_array(blockArray)
|
2142
|
-
decrypted = ""
|
2143
|
-
0.upto(@blockSize - 1) { |pos|
|
2144
|
-
decrypted << decryptedBlock[pos % 4][pos / 4]
|
2145
|
-
}
|
2146
|
-
return(decrypted)
|
2147
|
-
end
|
2148
|
-
|
2149
|
-
|
2150
|
-
end
|
2151
|
-
end #--}}}
|
2152
|
-
|
2153
|
-
# stringxor.rb Richard Kernahan <kernighan_rich@rubyforge.org>
|
2154
|
-
module Crypt #--{{{
|
2155
|
-
module StringXor
|
2156
|
-
|
2157
|
-
|
2158
|
-
def ^(aString)
|
2159
|
-
a = self.unpack('C'*(self.length))
|
2160
|
-
b = aString.unpack('C'*(aString.length))
|
2161
|
-
if (b.length < a.length)
|
2162
|
-
(a.length - b.length).times { b << 0 }
|
2163
|
-
end
|
2164
|
-
xor = ""
|
2165
|
-
0.upto(a.length-1) { |pos|
|
2166
|
-
x = a[pos] ^ b[pos]
|
2167
|
-
xor << x.chr()
|
2168
|
-
}
|
2169
|
-
return(xor)
|
2170
478
|
end
|
2171
|
-
|
2172
|
-
|
2173
|
-
end
|
2174
|
-
end
|
2175
479
|
|
2176
|
-
|
2177
|
-
|
2178
|
-
end #--}}}
|
2179
|
-
#--}}}
|
2180
|
-
}
|
480
|
+
Raptcha::CLI.run
|
481
|
+
end
|
2181
482
|
|
2182
483
|
__END__
|
484
|
+
|
2183
485
|
class RaptchaController < ApplicationController
|
2184
|
-
|
2185
|
-
|
486
|
+
# this is the image responder - it is the *only* action you need here
|
487
|
+
#
|
488
|
+
# you may need a to route /raptcha to this action in config/routes.rb
|
489
|
+
#
|
490
|
+
# match 'raptcha(/:action)', :controller => 'raptcha'
|
491
|
+
#
|
492
|
+
def index
|
493
|
+
Raptcha.render(controller=self, params)
|
2186
494
|
end
|
2187
495
|
|
2188
|
-
|
496
|
+
# sample on how to use - you may delete this action
|
497
|
+
#
|
498
|
+
def form
|
2189
499
|
render :inline => <<-html
|
2190
500
|
<html>
|
2191
501
|
<body>
|
2192
502
|
<hr>
|
2193
|
-
<em>valid</em>:#{ Raptcha.valid?
|
503
|
+
<em>valid</em>:#{ Raptcha.valid?(params) ? :true : :false }
|
2194
504
|
<hr>
|
2195
|
-
|
505
|
+
<%= form_tag do %>
|
2196
506
|
#{ Raptcha.input }
|
2197
507
|
<hr>
|
2198
508
|
<input type=submit name=submit value=submit />
|
2199
509
|
<hr>
|
2200
|
-
<a href="#{ request.
|
2201
|
-
|
510
|
+
<a href="#{ request.fullpath }">new</a>
|
511
|
+
<% end %>
|
2202
512
|
</body>
|
2203
513
|
</html>
|
2204
514
|
html
|
2205
515
|
end
|
2206
516
|
|
2207
|
-
|
517
|
+
# sample inline image (IE incompatible) - you may delete this action
|
518
|
+
#
|
519
|
+
def inline
|
2208
520
|
render :inline => <<-html
|
2209
521
|
<html>
|
2210
522
|
<body>
|
2211
523
|
<hr>
|
2212
|
-
<em>valid</em>:#{ Raptcha.valid?
|
524
|
+
<em>valid</em>:#{ Raptcha.valid?(params) ? :true : :false }
|
2213
525
|
<hr>
|
2214
|
-
|
526
|
+
<%= form_tag do %>
|
2215
527
|
#{ Raptcha.input :inline => true }
|
2216
528
|
<hr>
|
2217
529
|
<input type=submit name=submit value=submit />
|
2218
530
|
<hr>
|
2219
531
|
<a href="#{ request.request_uri }">new</a>
|
2220
|
-
|
532
|
+
<% end %>
|
2221
533
|
</body>
|
2222
534
|
</html>
|
2223
535
|
html
|
2224
536
|
end
|
2225
537
|
end
|
538
|
+
|
539
|
+
load 'lib/raptcha.rb' if Rails.env.development?
|