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.
Files changed (63) hide show
  1. data/README +0 -88
  2. data/Rakefile +364 -0
  3. data/image.sh +24 -0
  4. data/images/raptcha.png +0 -0
  5. data/lib/raptcha.rb +377 -2063
  6. metadata +56 -128
  7. data/bin/raptcha +0 -2225
  8. data/gemspec.rb +0 -28
  9. data/install.rb +0 -210
  10. data/out +0 -0
  11. data/rails/README +0 -182
  12. data/rails/Rakefile +0 -10
  13. data/rails/app/controllers/application.rb +0 -7
  14. data/rails/app/controllers/raptcha_controller.rb +0 -43
  15. data/rails/app/helpers/application_helper.rb +0 -3
  16. data/rails/config/boot.rb +0 -45
  17. data/rails/config/database.yml +0 -36
  18. data/rails/config/environment.rb +0 -62
  19. data/rails/config/environments/development.rb +0 -21
  20. data/rails/config/environments/production.rb +0 -18
  21. data/rails/config/environments/test.rb +0 -19
  22. data/rails/config/lighttpd.conf +0 -54
  23. data/rails/config/routes.rb +0 -23
  24. data/rails/doc/README_FOR_APP +0 -2
  25. data/rails/lib/raptcha.rb +0 -2225
  26. data/rails/log/development.log +0 -16
  27. data/rails/log/fastcgi.crash.log +0 -4
  28. data/rails/log/lighttpd.access.log +0 -2
  29. data/rails/log/lighttpd.error.log +0 -3
  30. data/rails/log/production.log +0 -0
  31. data/rails/log/server.log +0 -0
  32. data/rails/log/test.log +0 -0
  33. data/rails/public/404.html +0 -30
  34. data/rails/public/500.html +0 -30
  35. data/rails/public/dispatch.cgi +0 -10
  36. data/rails/public/dispatch.fcgi +0 -24
  37. data/rails/public/dispatch.rb +0 -10
  38. data/rails/public/favicon.ico +0 -0
  39. data/rails/public/images/rails.png +0 -0
  40. data/rails/public/index.html +0 -277
  41. data/rails/public/javascripts/application.js +0 -2
  42. data/rails/public/javascripts/controls.js +0 -833
  43. data/rails/public/javascripts/dragdrop.js +0 -942
  44. data/rails/public/javascripts/effects.js +0 -1088
  45. data/rails/public/javascripts/prototype.js +0 -2515
  46. data/rails/public/robots.txt +0 -1
  47. data/rails/script/about +0 -3
  48. data/rails/script/breakpointer +0 -3
  49. data/rails/script/console +0 -3
  50. data/rails/script/destroy +0 -3
  51. data/rails/script/generate +0 -3
  52. data/rails/script/performance/benchmarker +0 -3
  53. data/rails/script/performance/profiler +0 -3
  54. data/rails/script/plugin +0 -3
  55. data/rails/script/process/inspector +0 -3
  56. data/rails/script/process/reaper +0 -3
  57. data/rails/script/process/spawner +0 -3
  58. data/rails/script/runner +0 -3
  59. data/rails/script/server +0 -3
  60. data/rails/test/test_helper.rb +0 -28
  61. data/rails/tmp/sessions/ruby_sess.04085f44b9141c9d +0 -0
  62. data/raptcha-0.0.1.gem +0 -0
  63. data/samples.rb +0 -19
@@ -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' \
Binary file
@@ -1,126 +1,205 @@
1
1
  #! /usr/bin/env ruby
2
2
 
3
3
  module Raptcha
4
- #--{{{
5
- VERSION = '0.0.1' unless defined? Raptcha::VERSION
6
- def self.version() VERSION end
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
- begin
12
- require 'rubygems'
13
- rescue LoadError
14
- nil
15
- end
83
+ module Image
84
+ class << Image
85
+ def create(options = {})
86
+ options = Raptcha.normalize(options)
16
87
 
17
- begin
18
- require 'RMagick'
19
- rescue LoadError
20
- begin
21
- require 'Rmagick'
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
- =begin
28
- #--{{{
29
- # all of this in inlined in the BEGIN block below...
30
-
31
- libdir = __FILE__.gsub %r'\.rb$', '/'
32
- begin
33
- $:.unshift libdir
34
- require 'pervasives'
35
- require 'attributes'
36
- require 'crypt/blowfish'
37
- ensure
38
- $:.shift
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 Image
44
- #--{{{
45
- singleton_class =
46
- class << self
47
- self
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
- singleton_class.module_eval do
51
- attribute('key'){ "--img--#{ Raptcha.mac_address }--#{ Raptcha.hostname }--"[0,56] }
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
- kw[:width] = kw[:width].to_i
84
- kw[:height] = kw[:height].to_i
85
- kw[:implode] = kw[:implode].to_f
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
- img = Magick::Image.new(kw[:width], kw[:height]) do |i|
88
- i.background_color = kw[:background]
89
- i.format = kw[:format]
90
- end
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
- draw = Magick::Draw.new
172
+ def cycle(plaintext, options = {})
173
+ decrypt(encrypt(plaintext, options), options)
174
+ end
93
175
 
94
- # text
95
- draw.stroke = kw[:foreground]
96
- draw.stroke_width = 0
97
- draw.font_family = kw[:font_family]
98
- draw.pointsize = kw[:pointsize]
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
- # line
105
- draw.stroke = kw[:foreground]
106
- draw.stroke_width = 1
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
- draw.draw img
186
+ def key=(key)
187
+ @key = key.to_s[0, 56]
188
+ end
112
189
 
113
- img = img.wave *distort[kw[:distort]]
114
- img = img.implode kw[:implode]
190
+ def alg
191
+ @alg ||= 'AES-256-CBC'
192
+ end
115
193
 
116
- img.to_blob
117
- end
194
+ def salt
195
+ @salt ||= nil
196
+ end
118
197
 
119
- def inline kw ={}
120
- Base64.encode64(create(kw))
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
- singleton_class =
132
- class << self
133
- self
210
+ class << Raptcha
211
+ def key
212
+ @key ||= Rails::Application.config.secret_token
134
213
  end
135
214
 
136
- singleton_class.module_eval do
137
- attribute('key'){ "--key--#{ mac_address }--#{ hostname }--"[0,56] }
138
- attribute('src'){ '/raptcha' }
139
- attribute('gravity'){ 'west' }
140
- attribute('hostname'){ Socket.gethostname }
141
- attribute('user'){ ENV['USER'] || ENV['LOGNAME'] || 'raptcha' }
142
- attribute('alphabet'){ ('A' .. 'Z').to_a }
143
- attribute('ttl'){ 30 * 60 }
144
-
145
- attribute('close_enough'){ Hash[
146
- '0OoQ' => '0',
147
- '1l' => '1',
148
- '2zZ' => '2',
149
- '5sS' => '5',
150
- 'kKxX' => 'x',
151
- ] }
152
-
153
- def valid? params
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! params
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! params
168
- #--{{{
169
- if params.has_key? 'raptcha'
170
- raptcha = params['raptcha']
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['t']
173
- word = raptcha['w']
174
- timebomb = raptcha['b']
257
+ textarea = raptcha[:t]
258
+ word = raptcha[:w]
259
+ timebomb = raptcha[:b]
175
260
 
176
- raise NoInput unless textarea and word and timebomb
261
+ raise NoInput unless(textarea and word and timebomb)
177
262
 
178
- word = decrypt word
179
- timebomb = decrypt timebomb
263
+ word = Encryptor.decrypt(word)
264
+ timebomb = Encryptor.decrypt(timebomb)
180
265
 
181
266
  begin
182
- timebomb = Integer timebomb
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 fuzzy(word) == fuzzy(textarea)
275
+ raise BadInput unless fuzzy_match(word, textarea)
191
276
 
192
277
  textarea
193
278
  else
194
- validate! 'raptcha' => params
279
+ validate!(:raptcha => params)
195
280
  end
196
- #--}}}
197
281
  end
198
282
 
199
- def fuzzy word
200
- #--{{{
283
+ def fuzzy(word)
201
284
  result = word.to_s.downcase
202
285
  close_enough.each do |charset, replace|
203
- result.gsub! %r"[#{ charset }]", replace
286
+ result.gsub!(%r"[#{ charset }]", replace)
204
287
  end
205
- result
206
- #--}}}
288
+ result.upcase.strip
207
289
  end
208
290
 
209
- attribute 'input_north'
210
- attribute 'input_south'
211
- attribute 'input_east'
212
- attribute 'input_west'
291
+ def fuzzy_match(a, b)
292
+ fuzzy(a) == fuzzy(b)
293
+ end
213
294
 
214
- def input kw = {}
215
- #--{{{
216
- kw.to_options!
295
+ def input(options = {})
296
+ options = Raptcha.normalize(options)
217
297
 
218
- kw[:src] ||= Raptcha.src
219
- kw[:word] ||= Raptcha.word
220
- kw[:timebomb] ||= Raptcha.timebomb
221
- kw[:gravity] ||= Raptcha.gravity
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 kw[:word], :key => Raptcha.key
224
- encrypted_timebomb = encrypt kw[:timebomb], :key => Raptcha.key
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(kw)
310
+ west = Raptcha.img(options)
230
311
  when /n(orth)?/
231
- north = Raptcha.img(kw) + '<br>'
312
+ north = Raptcha.img(options) + '<br>'
232
313
  when /e(ast)?/
233
- east = Raptcha.img(kw)
314
+ east = Raptcha.img(options)
234
315
  when /s(outh)?/
235
- south = '<br>' + Raptcha.img(kw)
316
+ south = '<br>' + Raptcha.img(options)
236
317
  end
237
318
 
238
- <<-html
239
- <div class="raptcha">
240
- #{ input_north }#{ input_west }
241
- #{ north } #{ west }
242
- <input type="textarea" name="raptcha[t]" value="" class="raptcha_t"/>
243
- <input type="hidden" name="raptcha[w]" value="#{ encrypted_word }" class="raptcha_w"/>
244
- <input type="hidden" name="raptcha[b]" value="#{ encrypted_timebomb }" class="raptcha_b"/>
245
- #{ east } #{ south }
246
- #{ input_east } #{ input_south }
247
- </div>
248
- html
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 kw = {}
255
- #--{{{
256
- kw.to_options!
257
- return(inline(kw)) if kw[:inline]
258
- src = kw[:src] || Raptcha.src
259
- word = kw[:word] || Raptcha.word
260
- encrypted_word = encrypt word, :key => Image.key
261
- <<-html
262
- <img src="#{ src }?e=#{ CGI.escape encrypted_word }" alt="raptcha.png" class="raptcha_i"/>
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 kw = {}
268
- #--{{{
269
- <<-html
270
- <img src="data:image/png;base64,#{ Image.inline kw }" alt="raptcha.png" class="raptcha_i"/>
271
- html
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 size = 6
282
- #--{{{
283
- w = '' and size.times{ w << alphabet[rand(alphabet.size - 1)]} and w
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 image *a, &b
288
- #--{{{
289
- Raptcha::Image.create *a, &b
290
- #--}}}
369
+ def alphabet
370
+ @alphabet ||= ('A' .. 'Z').to_a
291
371
  end
292
372
 
293
- def mac_address
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 Raptcha.image(params), :type => 'image/png', :disposition => 'inline', :filename => 'raptcha.png'
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
- module Attributes #--{{{
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
- names_and_defaults = {}
472
- hashes.each{|h| names_and_defaults.update h}
473
- names.flatten.compact.each{|name| names_and_defaults.update name => nil}
395
+ # the command line code
396
+ #
397
+ module Raptcha
398
+ class CLI
399
+ def CLI.run
400
+ new.run
401
+ end
474
402
 
475
- names_and_defaults.each do |name, default|
476
- init = b || lambda { default }
477
- ivar, getter, setter, query, banger =
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
- define_method(setter) do |value|
481
- __pervasive__('instance_variable_set', ivar, value)
482
- end
407
+ @argv, kvs = @argv.partition{|arg| arg !~ /[=:]/}
483
408
 
484
- define_method(getter) do |*value|
485
- unless value.empty?
486
- __pervasive__('send', setter, value.shift)
487
- else
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
- define_method(banger) do
495
- __pervasive__('send', setter, __pervasive__('instance_eval', &init))
496
- __pervasive__('instance_variable_get', ivar)
497
- end
415
+ @mode = @argv.shift || 'help'
416
+ end
498
417
 
499
- alias_method query, getter
418
+ def run
419
+ respond_to?(@mode) ? send(@mode) : send(:help)
420
+ end
500
421
 
501
- (attributes << name.to_s).uniq!
502
- attributes
422
+ def help
423
+ STDERR.puts(README)
424
+ exit(42)
503
425
  end
504
- else
505
- begin
506
- __attribute_list__
507
- rescue NameError
508
- singleton_class =
509
- class << self
510
- self
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
- __attribute_list__
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
- class Object
527
- def attributes *a, &b
528
- sc =
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
- end
1102
- end #--}}}
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
- end
1259
- end #--}}}
1260
-
1261
- # LICENSE INFORMATION
1262
- #
1263
- # This software product contains the IDEA algorithm as described and claimed in
1264
- # US patent 5,214,703, EPO patent 0482154 (covering Austria, France, Germany,
1265
- # Italy, the Netherlands, Spain, Sweden, Switzerland, and the UK), and Japanese
1266
- # patent application 508119/1991, "Device for the conversion of a digital block
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
- class String
1386
- include Crypt::Noise
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
- end
1766
- end #--}}}
1767
-
1768
- # rijndael-tables.rb Richard Kernahan <kernighan_rich@rubyforge.org>
1769
- module Crypt #--{{{
1770
- module RijndaelTables
1771
-
1772
- LogTable = [
1773
- 0, 0, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51, 238, 223, 3,
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
- class String
2177
- include Crypt::StringXor
2178
- end #--}}}
2179
- #--}}}
2180
- }
480
+ Raptcha::CLI.run
481
+ end
2181
482
 
2182
483
  __END__
484
+
2183
485
  class RaptchaController < ApplicationController
2184
- def index # the image responder
2185
- Raptcha.render self, params
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
- def form # sample on how to use
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? params }
503
+ <em>valid</em>:#{ Raptcha.valid?(params) ? :true : :false }
2194
504
  <hr>
2195
- <form method=post>
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.request_uri }">new</a>
2201
- </form>
510
+ <a href="#{ request.fullpath }">new</a>
511
+ <% end %>
2202
512
  </body>
2203
513
  </html>
2204
514
  html
2205
515
  end
2206
516
 
2207
- def inline # does not work in older internet exploders
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? params }
524
+ <em>valid</em>:#{ Raptcha.valid?(params) ? :true : :false }
2213
525
  <hr>
2214
- <form method=post>
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
- </form>
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?