validates_captcha 0.9.4 → 0.9.5
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/CHANGELOG.rdoc +9 -0
- data/README.rdoc +2 -2
- data/lib/validates_captcha.rb +3 -3
- data/lib/validates_captcha/image_generator/simple.rb +10 -4
- data/lib/validates_captcha/provider/{image.rb → dynamic_image.rb} +14 -14
- data/lib/validates_captcha/string_generator/simple.rb +6 -3
- data/lib/validates_captcha/symmetric_encryptor/simple.rb +52 -0
- data/lib/validates_captcha/version.rb +1 -1
- data/test/cases/controller_validation_test.rb +1 -1
- data/test/cases/model_validation_test.rb +1 -1
- data/test/cases/provider/{image_test.rb → dynamic_image_test.rb} +11 -11
- data/test/cases/{reversible_encrypter → symmetric_encryptor}/simple_test.rb +7 -7
- metadata +9 -9
- data/lib/validates_captcha/reversible_encrypter/simple.rb +0 -55
data/CHANGELOG.rdoc
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
== 0.9.5 (October 9, 2009)
|
2
|
+
|
3
|
+
* API change: renamed Provider::Image to Provider::DynamicImage in order to guard against confusion
|
4
|
+
|
5
|
+
* API change: renamed ReversibleEncrypter to SymmetricEncryptor
|
6
|
+
|
7
|
+
* ReversibleEncrypter::Simple class now uses ActiveSupport's MessageEncryptor instead of custom implementation
|
8
|
+
|
9
|
+
|
1
10
|
== 0.9.4 (October 7, 2009)
|
2
11
|
|
3
12
|
* Include new StaticImage provider
|
data/README.rdoc
CHANGED
@@ -178,7 +178,7 @@ You can set the captcha provider to use dynamically created image challenges
|
|
178
178
|
with the code below. Dynamic means that the captcha image is created on invocation.
|
179
179
|
If you want to utilize this provider, it is best to put this in a Rails initializer.
|
180
180
|
|
181
|
-
ValidatesCaptcha.provider = ValidatesCaptcha::Provider::
|
181
|
+
ValidatesCaptcha.provider = ValidatesCaptcha::Provider::DynamicImage.new
|
182
182
|
|
183
183
|
By default, image captchas have a length of 6 characters and the text displayed
|
184
184
|
on the captcha image is created by randomly selecting characters from a
|
@@ -233,7 +233,7 @@ that creates images that are harder to crack.
|
|
233
233
|
Please see the documentation of the following classes for further information.
|
234
234
|
|
235
235
|
* ValidatesCaptcha::StringGenerator::Simple
|
236
|
-
* ValidatesCaptcha::
|
236
|
+
* ValidatesCaptcha::SymmetricEncryptor::Simple
|
237
237
|
* ValidatesCaptcha::ImageGenerator::Simple
|
238
238
|
|
239
239
|
Or you can implement a custom captcha challenge provider and assign it to
|
data/lib/validates_captcha.rb
CHANGED
@@ -37,7 +37,7 @@ module ValidatesCaptcha
|
|
37
37
|
|
38
38
|
module Provider
|
39
39
|
autoload :Question, 'validates_captcha/provider/question'
|
40
|
-
autoload :
|
40
|
+
autoload :DynamicImage, 'validates_captcha/provider/dynamic_image'
|
41
41
|
autoload :StaticImage, 'validates_captcha/provider/static_image'
|
42
42
|
end
|
43
43
|
|
@@ -45,8 +45,8 @@ module ValidatesCaptcha
|
|
45
45
|
autoload :Simple, 'validates_captcha/string_generator/simple'
|
46
46
|
end
|
47
47
|
|
48
|
-
module
|
49
|
-
autoload :Simple, 'validates_captcha/
|
48
|
+
module SymmetricEncryptor
|
49
|
+
autoload :Simple, 'validates_captcha/symmetric_encryptor/simple'
|
50
50
|
end
|
51
51
|
|
52
52
|
module ImageGenerator
|
@@ -19,8 +19,7 @@ module ValidatesCaptcha
|
|
19
19
|
# for your own implementations.
|
20
20
|
#
|
21
21
|
# You can implement your own (better) image generator by creating a
|
22
|
-
# class that conforms to the method definitions of the example below
|
23
|
-
# assign an instance of it to ValidatesCaptcha::Provider::Image#image_generator=.
|
22
|
+
# class that conforms to the method definitions of the example below.
|
24
23
|
#
|
25
24
|
# Example for a custom image generator:
|
26
25
|
#
|
@@ -40,8 +39,15 @@ module ValidatesCaptcha
|
|
40
39
|
# end
|
41
40
|
# end
|
42
41
|
#
|
43
|
-
#
|
44
|
-
#
|
42
|
+
# Then assign an instance of it to ValidatesCaptcha::Provider::DynamicImage#image_generator=.
|
43
|
+
#
|
44
|
+
# ValidatesCaptcha::Provider::DynamicImage.image_generator = AdvancedImageGenerator.new
|
45
|
+
# ValidatesCaptcha.provider = ValidatesCaptcha::Provider::DynamicImage.new
|
46
|
+
#
|
47
|
+
# Or to ValidatesCaptcha::Provider::StaticImage#image_generator=.
|
48
|
+
#
|
49
|
+
# ValidatesCaptcha::Provider::StaticImage.image_generator = AdvancedImageGenerator.new
|
50
|
+
# ValidatesCaptcha.provider = ValidatesCaptcha::Provider::StaticImage.new
|
45
51
|
#
|
46
52
|
class Simple
|
47
53
|
MIME_TYPE = 'image/gif'.freeze
|
@@ -63,7 +63,7 @@ module ValidatesCaptcha
|
|
63
63
|
# An image captcha provider.
|
64
64
|
#
|
65
65
|
# This class contains the getters and setters for the backend classes:
|
66
|
-
# image generator, string generator, and
|
66
|
+
# image generator, string generator, and symmetric encryptor. This
|
67
67
|
# allows you to replace them with your custom implementations. For more
|
68
68
|
# information on how to bring the image provider to use your own
|
69
69
|
# implementation instead of the default one, consult the documentation
|
@@ -75,11 +75,11 @@ module ValidatesCaptcha
|
|
75
75
|
# But you are not bound to ImageMagick. If you want to provide a custom image
|
76
76
|
# generator, take a look at the documentation for
|
77
77
|
# ValidatesCaptcha::ImageGenerator::Simple on how to create your own.
|
78
|
-
class
|
78
|
+
class DynamicImage
|
79
79
|
include ActionView::Helpers
|
80
80
|
|
81
81
|
@@string_generator = nil
|
82
|
-
@@
|
82
|
+
@@symmetric_encryptor = nil
|
83
83
|
@@image_generator = nil
|
84
84
|
|
85
85
|
class << self
|
@@ -95,16 +95,16 @@ module ValidatesCaptcha
|
|
95
95
|
@@string_generator = generator
|
96
96
|
end
|
97
97
|
|
98
|
-
# Returns the current captcha
|
99
|
-
# instance of the ValidatesCaptcha::
|
100
|
-
def
|
101
|
-
@@
|
98
|
+
# Returns the current captcha symmetric encryptor. Defaults to an
|
99
|
+
# instance of the ValidatesCaptcha::SymmetricEncryptor::Simple class.
|
100
|
+
def symmetric_encryptor
|
101
|
+
@@symmetric_encryptor ||= ValidatesCaptcha::SymmetricEncryptor::Simple.new
|
102
102
|
end
|
103
103
|
|
104
|
-
# Sets the current captcha
|
105
|
-
# custom
|
106
|
-
def
|
107
|
-
@@
|
104
|
+
# Sets the current captcha symmetric encryptor. Used to set a
|
105
|
+
# custom symmetric encryptor.
|
106
|
+
def symmetric_encryptor=(encryptor)
|
107
|
+
@@symmetric_encryptor = encryptor
|
108
108
|
end
|
109
109
|
|
110
110
|
# Returns the current captcha image generator. Defaults to an
|
@@ -166,7 +166,7 @@ module ValidatesCaptcha
|
|
166
166
|
# Returns true if the captcha was solved using the given +challenge+ and +solution+,
|
167
167
|
# otherwise false.
|
168
168
|
def solved?(challenge, solution)
|
169
|
-
challenge ==
|
169
|
+
decrypt(challenge) == solution
|
170
170
|
end
|
171
171
|
|
172
172
|
# Returns an image tag with the source set to the url of the captcha image.
|
@@ -211,11 +211,11 @@ module ValidatesCaptcha
|
|
211
211
|
end
|
212
212
|
|
213
213
|
def encrypt(code) #:nodoc:
|
214
|
-
self.class.
|
214
|
+
self.class.symmetric_encryptor.encrypt code
|
215
215
|
end
|
216
216
|
|
217
217
|
def decrypt(encrypted_code) #:nodoc:
|
218
|
-
self.class.
|
218
|
+
self.class.symmetric_encryptor.decrypt encrypted_code
|
219
219
|
end
|
220
220
|
|
221
221
|
def generate_code #:nodoc:
|
@@ -10,7 +10,8 @@ module ValidatesCaptcha
|
|
10
10
|
#
|
11
11
|
# You can implement your own string generator by creating a
|
12
12
|
# class that conforms to the method definitions of the example below and
|
13
|
-
# assign an instance of it to
|
13
|
+
# assign an instance of it to
|
14
|
+
# ValidatesCaptcha::Provider::DynamicImage#string_generator=.
|
14
15
|
#
|
15
16
|
# Example for a custom string generator:
|
16
17
|
#
|
@@ -22,8 +23,10 @@ module ValidatesCaptcha
|
|
22
23
|
# end
|
23
24
|
# end
|
24
25
|
#
|
25
|
-
# ValidatesCaptcha::Provider::
|
26
|
-
# ValidatesCaptcha.provider = ValidatesCaptcha::Provider::
|
26
|
+
# ValidatesCaptcha::Provider::DynamicImage.string_generator = DictionaryGenerator.new
|
27
|
+
# ValidatesCaptcha.provider = ValidatesCaptcha::Provider::DynamicImage.new
|
28
|
+
#
|
29
|
+
# You can also assign it to ValidatesCaptcha::Provider::StaticImage#string_generator=.
|
27
30
|
#
|
28
31
|
class Simple
|
29
32
|
@@alphabet = 'abdefghjkmnqrtABDEFGHJKLMNQRT234678923467892346789'
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
|
3
|
+
module ValidatesCaptcha
|
4
|
+
module SymmetricEncryptor
|
5
|
+
# This class is responsible for encrypting and decrypting captcha codes.
|
6
|
+
# It internally uses ActiveSupport's MessageEncryptor to do the string
|
7
|
+
# encryption/decryption.
|
8
|
+
#
|
9
|
+
# You can implement your own symmetric encryptor by creating a class
|
10
|
+
# that conforms to the method definitions of the example below and
|
11
|
+
# assign an instance of it to
|
12
|
+
# ValidatesCaptcha::Provider::DynamicImage#symmetric_encryptor=.
|
13
|
+
#
|
14
|
+
# Example for a custom symmetric encryptor:
|
15
|
+
#
|
16
|
+
# class ReverseString # very insecure and easily cracked
|
17
|
+
# def encrypt(code)
|
18
|
+
# code.reverse
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# def decrypt(encrypted_code)
|
22
|
+
# encrypted_code.reverse
|
23
|
+
# rescue SomeKindOfDecryptionError
|
24
|
+
# nil
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# ValidatesCaptcha::Provider::DynamicImage.symmetric_encryptor = ReverseString.new
|
29
|
+
# ValidatesCaptcha.provider = ValidatesCaptcha::Provider::DynamicImage.new
|
30
|
+
#
|
31
|
+
# Please note: The #decrypt method should return +nil+ if decryption fails.
|
32
|
+
class Simple
|
33
|
+
KEY = ::ActiveSupport::SecureRandom.hex(64).freeze
|
34
|
+
|
35
|
+
def initialize #:nodoc:
|
36
|
+
@symmetric_encryptor = ::ActiveSupport::MessageEncryptor.new(KEY)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Encrypts a cleartext string.
|
40
|
+
def encrypt(code)
|
41
|
+
@symmetric_encryptor.encrypt(code).gsub('+', '%2B').gsub('/', '%2F')
|
42
|
+
end
|
43
|
+
|
44
|
+
# Decrypts an encrypted string.
|
45
|
+
def decrypt(encrypted_code)
|
46
|
+
@symmetric_encryptor.decrypt encrypted_code.gsub('%2F', '/').gsub('%2B', '+')
|
47
|
+
rescue ::ActiveSupport::MessageEncryptor::InvalidMessage
|
48
|
+
nil
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -78,7 +78,7 @@ class ControllerValidationTest < ActionController::TestCase
|
|
78
78
|
|
79
79
|
def with_dynamic_image_provider(&block)
|
80
80
|
old_provider = ValidatesCaptcha.provider
|
81
|
-
provider = ValidatesCaptcha.provider = ValidatesCaptcha::Provider::
|
81
|
+
provider = ValidatesCaptcha.provider = ValidatesCaptcha::Provider::DynamicImage.new
|
82
82
|
yield provider
|
83
83
|
ValidatesCaptcha.provider = old_provider
|
84
84
|
end
|
@@ -3,7 +3,7 @@ require 'test_helper'
|
|
3
3
|
class ModelValidationTest < ValidatesCaptcha::TestCase
|
4
4
|
def with_dynamic_image_provider(&block)
|
5
5
|
old_provider = ValidatesCaptcha.provider
|
6
|
-
provider = ValidatesCaptcha.provider = ValidatesCaptcha::Provider::
|
6
|
+
provider = ValidatesCaptcha.provider = ValidatesCaptcha::Provider::DynamicImage.new
|
7
7
|
yield provider
|
8
8
|
ValidatesCaptcha.provider = old_provider
|
9
9
|
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
-
IMAGE = ValidatesCaptcha::Provider::
|
3
|
+
IMAGE = ValidatesCaptcha::Provider::DynamicImage
|
4
4
|
|
5
|
-
class
|
5
|
+
class DynamicImageTest < ValidatesCaptcha::TestCase
|
6
6
|
test "defines a class level #string_generator method" do
|
7
7
|
assert_respond_to IMAGE, :string_generator
|
8
8
|
end
|
@@ -20,21 +20,21 @@ class ImageTest < ValidatesCaptcha::TestCase
|
|
20
20
|
IMAGE.string_generator = old_string_generator
|
21
21
|
end
|
22
22
|
|
23
|
-
test "defines a class level #
|
24
|
-
assert_respond_to IMAGE, :
|
23
|
+
test "defines a class level #symmetric_encryptor method" do
|
24
|
+
assert_respond_to IMAGE, :symmetric_encryptor
|
25
25
|
end
|
26
26
|
|
27
|
-
test "defines a class level #
|
28
|
-
assert_respond_to IMAGE, :
|
27
|
+
test "defines a class level #symmetric_encryptor= method" do
|
28
|
+
assert_respond_to IMAGE, :symmetric_encryptor=
|
29
29
|
end
|
30
30
|
|
31
|
-
test "#
|
32
|
-
|
31
|
+
test "#symmetric_encryptor method's return value should equal the value set using the #symmetric_encryptor= method" do
|
32
|
+
old_symmetric_encryptor = IMAGE.symmetric_encryptor
|
33
33
|
|
34
|
-
IMAGE.
|
35
|
-
assert_equal 'abc', IMAGE.
|
34
|
+
IMAGE.symmetric_encryptor = 'abc'
|
35
|
+
assert_equal 'abc', IMAGE.symmetric_encryptor
|
36
36
|
|
37
|
-
IMAGE.
|
37
|
+
IMAGE.symmetric_encryptor = old_symmetric_encryptor
|
38
38
|
end
|
39
39
|
|
40
40
|
test "defines a class level #image_generator method" do
|
@@ -1,27 +1,27 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
-
|
3
|
+
SE = ValidatesCaptcha::SymmetricEncryptor::Simple
|
4
4
|
|
5
|
-
class
|
5
|
+
class SymmetricEncryptorTest < ValidatesCaptcha::TestCase
|
6
6
|
test "defines an instance level #encrypt method" do
|
7
|
-
assert_respond_to
|
7
|
+
assert_respond_to SE.new, :encrypt
|
8
8
|
end
|
9
9
|
|
10
10
|
test "instance level #encrypt method returns a string" do
|
11
|
-
assert_kind_of String,
|
11
|
+
assert_kind_of String, SE.new.encrypt('abc')
|
12
12
|
end
|
13
13
|
|
14
14
|
test "defines an instance level #decrypt method" do
|
15
|
-
assert_respond_to
|
15
|
+
assert_respond_to SE.new, :decrypt
|
16
16
|
end
|
17
17
|
|
18
18
|
test "instance level #decrypt method returns nil if decryption failes" do
|
19
|
-
assert_nil
|
19
|
+
assert_nil SE.new.decrypt('invalid')
|
20
20
|
end
|
21
21
|
|
22
22
|
test "decryption of encryption of string should equal the string" do
|
23
23
|
%w(d3crypti0n 3ncrypt3d 5trin9 sh0u1d equ41 th3 c4ptch4).each do |captcha|
|
24
|
-
assert_equal captcha,
|
24
|
+
assert_equal captcha, SE.new.decrypt(SE.new.encrypt(captcha))
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: validates_captcha
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Martin Andert
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-10-
|
12
|
+
date: 2009-10-09 00:00:00 +02:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -53,11 +53,11 @@ files:
|
|
53
53
|
- lib/validates_captcha/form_helper.rb
|
54
54
|
- lib/validates_captcha/image_generator/simple.rb
|
55
55
|
- lib/validates_captcha/model_validation.rb
|
56
|
-
- lib/validates_captcha/provider/
|
56
|
+
- lib/validates_captcha/provider/dynamic_image.rb
|
57
57
|
- lib/validates_captcha/provider/question.rb
|
58
58
|
- lib/validates_captcha/provider/static_image.rb
|
59
|
-
- lib/validates_captcha/reversible_encrypter/simple.rb
|
60
59
|
- lib/validates_captcha/string_generator/simple.rb
|
60
|
+
- lib/validates_captcha/symmetric_encryptor/simple.rb
|
61
61
|
- lib/validates_captcha/test_case.rb
|
62
62
|
- lib/validates_captcha/version.rb
|
63
63
|
- rails/init.rb
|
@@ -65,11 +65,11 @@ files:
|
|
65
65
|
- test/cases/controller_validation_test.rb
|
66
66
|
- test/cases/image_generator/simple_test.rb
|
67
67
|
- test/cases/model_validation_test.rb
|
68
|
-
- test/cases/provider/
|
68
|
+
- test/cases/provider/dynamic_image_test.rb
|
69
69
|
- test/cases/provider/question_test.rb
|
70
70
|
- test/cases/provider/static_image_test.rb
|
71
|
-
- test/cases/reversible_encrypter/simple_test.rb
|
72
71
|
- test/cases/string_generator/simple_test.rb
|
72
|
+
- test/cases/symmetric_encryptor/simple_test.rb
|
73
73
|
- test/cases/validates_captcha_test.rb
|
74
74
|
- test/test_helper.rb
|
75
75
|
has_rdoc: true
|
@@ -79,7 +79,7 @@ licenses: []
|
|
79
79
|
post_install_message:
|
80
80
|
rdoc_options:
|
81
81
|
- --title
|
82
|
-
- Validates Captcha 0.9.
|
82
|
+
- Validates Captcha 0.9.5
|
83
83
|
- --main
|
84
84
|
- README.rdoc
|
85
85
|
- --line-numbers
|
@@ -111,10 +111,10 @@ test_files:
|
|
111
111
|
- test/cases/controller_validation_test.rb
|
112
112
|
- test/cases/image_generator/simple_test.rb
|
113
113
|
- test/cases/model_validation_test.rb
|
114
|
-
- test/cases/provider/
|
114
|
+
- test/cases/provider/dynamic_image_test.rb
|
115
115
|
- test/cases/provider/question_test.rb
|
116
116
|
- test/cases/provider/static_image_test.rb
|
117
|
-
- test/cases/reversible_encrypter/simple_test.rb
|
118
117
|
- test/cases/string_generator/simple_test.rb
|
118
|
+
- test/cases/symmetric_encryptor/simple_test.rb
|
119
119
|
- test/cases/validates_captcha_test.rb
|
120
120
|
- test/test_helper.rb
|
@@ -1,55 +0,0 @@
|
|
1
|
-
require 'openssl'
|
2
|
-
require 'active_support/secure_random'
|
3
|
-
|
4
|
-
module ValidatesCaptcha
|
5
|
-
module ReversibleEncrypter
|
6
|
-
# This class is responsible for encrypting and decrypting captcha codes.
|
7
|
-
# It internally uses AES256 to do the string encryption/decryption.
|
8
|
-
#
|
9
|
-
# You can implement your own reversible encrypter by creating a class
|
10
|
-
# that conforms to the method definitions of the example below and
|
11
|
-
# assign an instance of it to ValidatesCaptcha::Provider::Image#reversible_encrypter=.
|
12
|
-
#
|
13
|
-
# Example for a custom encrypter/decrypter:
|
14
|
-
#
|
15
|
-
# class ReverseString # very insecure and easily cracked
|
16
|
-
# def encrypt(code)
|
17
|
-
# code.reverse
|
18
|
-
# end
|
19
|
-
#
|
20
|
-
# def decrypt(encrypted_code)
|
21
|
-
# encrypted_code.reverse
|
22
|
-
# rescue SomeKindOfDecryptionError
|
23
|
-
# nil
|
24
|
-
# end
|
25
|
-
# end
|
26
|
-
#
|
27
|
-
# ValidatesCaptcha::Provider::Image.reversible_encrypter = ReverseString.new
|
28
|
-
# ValidatesCaptcha.provider = ValidatesCaptcha::Provider::Image.new
|
29
|
-
#
|
30
|
-
# Please note: The #decrypt method should return +nil+ if decryption fails.
|
31
|
-
class Simple
|
32
|
-
KEY = ::ActiveSupport::SecureRandom.hex(32).freeze
|
33
|
-
|
34
|
-
def initialize #:nodoc:
|
35
|
-
@aes = OpenSSL::Cipher::Cipher.new('AES-256-ECB')
|
36
|
-
end
|
37
|
-
|
38
|
-
# Encrypts a cleartext string using #key as encryption key.
|
39
|
-
def encrypt(code)
|
40
|
-
@aes.encrypt
|
41
|
-
@aes.key = KEY
|
42
|
-
[@aes.update(code) + @aes.final].pack("m").tr('+/=', '-_ ').strip.gsub("\n", '')
|
43
|
-
end
|
44
|
-
|
45
|
-
# Decrypts an encrypted string using using #key as decryption key.
|
46
|
-
def decrypt(encrypted_code)
|
47
|
-
@aes.decrypt
|
48
|
-
@aes.key = KEY
|
49
|
-
@aes.update((encrypted_code + '=' * (4 - encrypted_code.size % 4)).tr('-_', '+/').unpack("m").first) + @aes.final
|
50
|
-
rescue # OpenSSL::CipherError, OpenSSL::Cipher::CipherError
|
51
|
-
nil
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|