encryptor 1.1.3 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +121 -0
- data/Rakefile +15 -4
- data/lib/encryptor.rb +13 -2
- data/lib/encryptor/version.rb +3 -3
- data/test/compatibility_test.rb +93 -0
- data/test/encryptor_test.rb +16 -12
- data/test/legacy_encryptor_test.rb +107 -0
- data/test/openssl_helper.rb +6 -0
- data/test/test_helper.rb +14 -0
- metadata +88 -43
- data/README.rdoc +0 -103
data/README.md
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
## Encryptor [](https://travis-ci.org/attr-encrypted/encryptor)
|
2
|
+
|
3
|
+
A simple wrapper for the standard Ruby OpenSSL library
|
4
|
+
|
5
|
+
Intended to be used by a future version of `http://github.com/shuber/attr_encrypted` to easily encrypt/decrypt attributes in any Ruby class or model.
|
6
|
+
|
7
|
+
### Installation
|
8
|
+
|
9
|
+
```bash
|
10
|
+
gem install encryptor
|
11
|
+
```
|
12
|
+
|
13
|
+
### Usage
|
14
|
+
|
15
|
+
#### Basic
|
16
|
+
|
17
|
+
Encryptor uses the AES-256-CBC algorithm by default to encrypt strings securely. You are strongly advised to use both an initialization vector (via the `:iv` option) and a salt (via the `:salt` option) to perform this encryption as securely as possible. Specifying only an `:iv` option without `:salt` is not recommended but is supported as part of a "compatibility mode" to support clients built using older versions of this gem.
|
18
|
+
|
19
|
+
The best example is:
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
salt = Time.now.to_i.to_s
|
23
|
+
secret_key = 'secret'
|
24
|
+
iv = OpenSSL::Cipher::Cipher.new('aes-256-cbc').random_iv
|
25
|
+
encrypted_value = Encryptor.encrypt('some string to encrypt', :key => secret_key, :iv => iv, :salt => salt)
|
26
|
+
decrypted_value = Encryptor.decrypt(encrypted_value, :key => secret_key, :iv => iv, :salt => salt)
|
27
|
+
```
|
28
|
+
|
29
|
+
The value to encrypt or decrypt may also be passed as the :value option if you'd prefer.
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
encrypted_value = Encryptor.encrypt(:value => 'some string to encrypt', :key => secret_key, :iv => iv, :salt => salt)
|
33
|
+
decrypted_value = Encryptor.decrypt(:value => encrypted_value, :key => secret_key, :iv => iv, :salt => salt)
|
34
|
+
```
|
35
|
+
|
36
|
+
**You may also skip the salt and the IV if you like. Do so at your own risk!**
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
encrypted_value = Encryptor.encrypt(:value => 'some string to encrypt', :key => 'secret')
|
40
|
+
decrypted_value = Encryptor.decrypt(:value => encrypted_value, :key => 'secret')
|
41
|
+
```
|
42
|
+
|
43
|
+
You may also pass an `:algorithm` option, though this is not required.
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
Encryptor.default_options.merge!(:algorithm => 'aes-128-cbc', :key => 'some default secret key', :iv => iv, :salt => salt)
|
47
|
+
```
|
48
|
+
|
49
|
+
#### Strings
|
50
|
+
|
51
|
+
Encryptor adds `encrypt` and `decrypt` methods to `String` objects for your convenience. These two methods accept the same arguments as the associated ones in the `Encryptor` module. They're nice when you set the default options in the `Encryptor.default_options attribute.` For example:
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
Encryptor.default_options.merge!(:key => 'some default secret key', :iv => iv, :salt => salt)
|
55
|
+
credit_card = 'xxxx xxxx xxxx 1234'
|
56
|
+
encrypted_credit_card = credit_card.encrypt
|
57
|
+
```
|
58
|
+
|
59
|
+
There's also `encrypt!` and `decrypt!` methods that replace the contents of a string with the encrypted or decrypted version of itself.
|
60
|
+
|
61
|
+
### Algorithms
|
62
|
+
|
63
|
+
Run `openssl list-cipher-commands` in your terminal to view a list of all cipher algorithms that are supported on your platform. Typically, this will include the following:
|
64
|
+
|
65
|
+
aes-128-cbc
|
66
|
+
aes-128-ecb
|
67
|
+
aes-192-cbc
|
68
|
+
aes-192-ecb
|
69
|
+
aes-256-cbc
|
70
|
+
aes-256-ecb
|
71
|
+
bf
|
72
|
+
bf-cbc
|
73
|
+
bf-cfb
|
74
|
+
bf-ecb
|
75
|
+
bf-ofb
|
76
|
+
cast
|
77
|
+
cast-cbc
|
78
|
+
cast5-cbc
|
79
|
+
cast5-cfb
|
80
|
+
cast5-ecb
|
81
|
+
cast5-ofb
|
82
|
+
des
|
83
|
+
des-cbc
|
84
|
+
des-cfb
|
85
|
+
des-ecb
|
86
|
+
des-ede
|
87
|
+
des-ede-cbc
|
88
|
+
des-ede-cfb
|
89
|
+
des-ede-ofb
|
90
|
+
des-ede3
|
91
|
+
des-ede3-cbc
|
92
|
+
des-ede3-cfb
|
93
|
+
des-ede3-ofb
|
94
|
+
des-ofb
|
95
|
+
des3
|
96
|
+
desx
|
97
|
+
idea
|
98
|
+
idea-cbc
|
99
|
+
idea-cfb
|
100
|
+
idea-ecb
|
101
|
+
idea-ofb
|
102
|
+
rc2
|
103
|
+
rc2-40-cbc
|
104
|
+
rc2-64-cbc
|
105
|
+
rc2-cbc
|
106
|
+
rc2-cfb
|
107
|
+
rc2-ecb
|
108
|
+
rc2-ofb
|
109
|
+
rc4
|
110
|
+
rc4-40
|
111
|
+
|
112
|
+
Note that some ciphers may not be supported by Ruby.
|
113
|
+
|
114
|
+
### Notes on patches/pull requests
|
115
|
+
|
116
|
+
* Fork the project.
|
117
|
+
* Make your feature addition or bug fix.
|
118
|
+
* Add tests for it: this is important so I don't break it in a future version unintentionally.
|
119
|
+
* Commit, do not mess with Rakefile, version, or history: if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull).
|
120
|
+
* Send me a pull request: bonus points for topic branches.
|
121
|
+
|
data/Rakefile
CHANGED
@@ -2,9 +2,6 @@ require 'rake'
|
|
2
2
|
require 'rake/testtask'
|
3
3
|
require 'rake/rdoctask'
|
4
4
|
|
5
|
-
desc 'Default: run unit tests'
|
6
|
-
task :default => :test
|
7
|
-
|
8
5
|
desc 'Test the encryptor gem'
|
9
6
|
Rake::TestTask.new(:test) do |t|
|
10
7
|
t.libs << 'lib'
|
@@ -19,4 +16,18 @@ Rake::RDocTask.new(:rdoc) do |rdoc|
|
|
19
16
|
rdoc.options << '--line-numbers' << '--inline-source'
|
20
17
|
rdoc.rdoc_files.include('README*')
|
21
18
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
22
|
-
end
|
19
|
+
end
|
20
|
+
|
21
|
+
if RUBY_VERSION < '1.9.3'
|
22
|
+
require 'rcov/rcovtask'
|
23
|
+
|
24
|
+
task :rcov do
|
25
|
+
system "rcov -o coverage/rcov --exclude '^(?!lib)' " + FileList[ 'test/**/*_test.rb' ].join(' ')
|
26
|
+
end
|
27
|
+
|
28
|
+
desc 'Default: run unit tests under rcov.'
|
29
|
+
task :default => :rcov
|
30
|
+
else
|
31
|
+
desc 'Default: run unit tests.'
|
32
|
+
task :default => :test
|
33
|
+
end
|
data/lib/encryptor.rb
CHANGED
@@ -52,8 +52,19 @@ module Encryptor
|
|
52
52
|
cipher = OpenSSL::Cipher::Cipher.new(options[:algorithm])
|
53
53
|
cipher.send(cipher_method)
|
54
54
|
if options[:iv]
|
55
|
-
cipher.key = options[:key]
|
56
55
|
cipher.iv = options[:iv]
|
56
|
+
if options[:salt].nil?
|
57
|
+
# Use a non-salted cipher.
|
58
|
+
# This behaviour is retained for backwards compatibility. This mode
|
59
|
+
# is not secure and new deployments should use the :salt options
|
60
|
+
# wherever possible.
|
61
|
+
cipher.key = options[:key]
|
62
|
+
else
|
63
|
+
# Use an explicit salt (which can be persisted into a database on a
|
64
|
+
# per-column basis, for example). This is the preferred (and more
|
65
|
+
# secure) mode of operation.
|
66
|
+
cipher.key = OpenSSL::PKCS5.pbkdf2_hmac_sha1(options[:key], options[:salt], 2000, cipher.key_len)
|
67
|
+
end
|
57
68
|
else
|
58
69
|
cipher.pkcs5_keyivgen(options[:key])
|
59
70
|
end
|
@@ -61,4 +72,4 @@ module Encryptor
|
|
61
72
|
result = cipher.update(options[:value])
|
62
73
|
result << cipher.final
|
63
74
|
end
|
64
|
-
end
|
75
|
+
end
|
data/lib/encryptor/version.rb
CHANGED
@@ -2,8 +2,8 @@ module Encryptor
|
|
2
2
|
# Contains information about this gem's version
|
3
3
|
module Version
|
4
4
|
MAJOR = 1
|
5
|
-
MINOR =
|
6
|
-
PATCH =
|
5
|
+
MINOR = 3
|
6
|
+
PATCH = 0
|
7
7
|
|
8
8
|
# Returns a version string by joining <tt>MAJOR</tt>, <tt>MINOR</tt>, and <tt>PATCH</tt> with <tt>'.'</tt>
|
9
9
|
#
|
@@ -14,4 +14,4 @@ module Encryptor
|
|
14
14
|
[MAJOR, MINOR, PATCH].join('.')
|
15
15
|
end
|
16
16
|
end
|
17
|
-
end
|
17
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require File.expand_path('../test_helper', __FILE__)
|
2
|
+
|
3
|
+
# Test ensures that values stored by previous versions of the gem will
|
4
|
+
# roundtrip and decrypt correctly in this and future versions. This is important
|
5
|
+
# for data stored in databases and allows consumers of the gem to upgrade with
|
6
|
+
# confidence in the future.
|
7
|
+
#
|
8
|
+
class CompatibilityTest < Test::Unit::TestCase
|
9
|
+
ALGORITHM = 'aes-256-cbc'
|
10
|
+
|
11
|
+
def self.base64_encode(value)
|
12
|
+
[value].pack('m').strip
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.base64_decode(value)
|
16
|
+
value.unpack('m').first
|
17
|
+
end
|
18
|
+
|
19
|
+
if OpenSSL::Cipher.ciphers.include?(ALGORITHM)
|
20
|
+
def test_encrypt_with_iv
|
21
|
+
key = Digest::SHA256.hexdigest('my-fixed-key')
|
22
|
+
iv = Digest::SHA256.hexdigest('my-fixed-iv')
|
23
|
+
result = Encryptor.encrypt(
|
24
|
+
:algorithm => ALGORITHM,
|
25
|
+
:value => 'my-fixed-input',
|
26
|
+
:key => key,
|
27
|
+
:iv => iv
|
28
|
+
)
|
29
|
+
assert_equal 'nGuyGniksFXnMYj/eCxXKQ==', self.class.base64_encode(result)
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_encrypt_without_iv
|
33
|
+
key = Digest::SHA256.hexdigest('my-fixed-key')
|
34
|
+
result = Encryptor.encrypt(
|
35
|
+
:algorithm => ALGORITHM,
|
36
|
+
:value => 'my-fixed-input',
|
37
|
+
:key => key
|
38
|
+
)
|
39
|
+
assert_equal 'XbwHRMFWqR5M80kgwRcEEg==', self.class.base64_encode(result)
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_decrypt_with_iv
|
43
|
+
key = Digest::SHA256.hexdigest('my-fixed-key')
|
44
|
+
iv = Digest::SHA256.hexdigest('my-fixed-iv')
|
45
|
+
result = Encryptor.decrypt(
|
46
|
+
:algorithm => ALGORITHM,
|
47
|
+
:value => self.class.base64_decode('nGuyGniksFXnMYj/eCxXKQ=='),
|
48
|
+
:key => key,
|
49
|
+
:iv => iv
|
50
|
+
)
|
51
|
+
assert_equal 'my-fixed-input', result
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_decrypt_without_iv
|
55
|
+
key = Digest::SHA256.hexdigest('my-fixed-key')
|
56
|
+
result = Encryptor.decrypt(
|
57
|
+
:algorithm => ALGORITHM,
|
58
|
+
:value => self.class.base64_decode('XbwHRMFWqR5M80kgwRcEEg=='),
|
59
|
+
:key => key
|
60
|
+
)
|
61
|
+
assert_equal 'my-fixed-input', result
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_encrypt_with_iv_and_salt
|
65
|
+
key = Digest::SHA256.hexdigest('my-fixed-key')
|
66
|
+
iv = Digest::SHA256.hexdigest('my-fixed-iv')
|
67
|
+
salt = 'my-fixed-salt'
|
68
|
+
result = Encryptor.encrypt(
|
69
|
+
:algorithm => ALGORITHM,
|
70
|
+
:value => 'my-fixed-input',
|
71
|
+
:key => key,
|
72
|
+
:iv => iv,
|
73
|
+
:salt => salt
|
74
|
+
)
|
75
|
+
assert_equal 'DENuQSh9b0eW8GN3YLzLGw==', self.class.base64_encode(result)
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_decrypt_with_iv_and_salt
|
79
|
+
key = Digest::SHA256.hexdigest('my-fixed-key')
|
80
|
+
iv = Digest::SHA256.hexdigest('my-fixed-iv')
|
81
|
+
salt = 'my-fixed-salt'
|
82
|
+
result = Encryptor.decrypt(
|
83
|
+
:algorithm => ALGORITHM,
|
84
|
+
:value => self.class.base64_decode('DENuQSh9b0eW8GN3YLzLGw=='),
|
85
|
+
:key => key,
|
86
|
+
:iv => iv,
|
87
|
+
:salt => salt
|
88
|
+
)
|
89
|
+
assert_equal 'my-fixed-input', result
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
data/test/encryptor_test.rb
CHANGED
@@ -1,20 +1,23 @@
|
|
1
1
|
require File.expand_path('../test_helper', __FILE__)
|
2
|
+
require File.expand_path('../openssl_helper', __FILE__)
|
2
3
|
|
4
|
+
# Tests for new preferred salted encryption mode
|
5
|
+
#
|
3
6
|
class EncryptorTest < Test::Unit::TestCase
|
4
7
|
|
5
|
-
algorithms = %x(openssl list-cipher-commands).split
|
6
8
|
key = Digest::SHA256.hexdigest(([Time.now.to_s] * rand(3)).join)
|
7
9
|
iv = Digest::SHA256.hexdigest(([Time.now.to_s] * rand(3)).join)
|
10
|
+
salt = Time.now.to_i.to_s
|
8
11
|
original_value = Digest::SHA256.hexdigest(([Time.now.to_s] * rand(3)).join)
|
9
12
|
|
10
|
-
|
11
|
-
encrypted_value_with_iv = Encryptor.encrypt(:value => original_value, :key => key, :iv => iv, :algorithm => algorithm)
|
13
|
+
OpenSSLHelper::ALGORITHMS.each do |algorithm|
|
14
|
+
encrypted_value_with_iv = Encryptor.encrypt(:value => original_value, :key => key, :iv => iv, :salt => salt, :algorithm => algorithm)
|
12
15
|
encrypted_value_without_iv = Encryptor.encrypt(:value => original_value, :key => key, :algorithm => algorithm)
|
13
16
|
|
14
17
|
define_method "test_should_crypt_with_the_#{algorithm}_algorithm_with_iv" do
|
15
18
|
assert_not_equal original_value, encrypted_value_with_iv
|
16
19
|
assert_not_equal encrypted_value_without_iv, encrypted_value_with_iv
|
17
|
-
assert_equal original_value, Encryptor.decrypt(:value => encrypted_value_with_iv, :key => key, :iv => iv, :algorithm => algorithm)
|
20
|
+
assert_equal original_value, Encryptor.decrypt(:value => encrypted_value_with_iv, :key => key, :iv => iv, :salt => salt, :algorithm => algorithm)
|
18
21
|
end
|
19
22
|
|
20
23
|
define_method "test_should_crypt_with_the_#{algorithm}_algorithm_without_iv" do
|
@@ -23,7 +26,7 @@ class EncryptorTest < Test::Unit::TestCase
|
|
23
26
|
end
|
24
27
|
|
25
28
|
define_method "test_should_encrypt_with_the_#{algorithm}_algorithm_with_iv_with_the_first_arg_as_the_value" do
|
26
|
-
assert_equal encrypted_value_with_iv, Encryptor.encrypt(original_value, :key => key, :iv => iv, :algorithm => algorithm)
|
29
|
+
assert_equal encrypted_value_with_iv, Encryptor.encrypt(original_value, :key => key, :iv => iv, :salt => salt, :algorithm => algorithm)
|
27
30
|
end
|
28
31
|
|
29
32
|
define_method "test_should_encrypt_with_the_#{algorithm}_algorithm_without_iv_with_the_first_arg_as_the_value" do
|
@@ -31,7 +34,7 @@ class EncryptorTest < Test::Unit::TestCase
|
|
31
34
|
end
|
32
35
|
|
33
36
|
define_method "test_should_decrypt_with_the_#{algorithm}_algorithm_with_iv_with_the_first_arg_as_the_value" do
|
34
|
-
assert_equal original_value, Encryptor.decrypt(encrypted_value_with_iv, :key => key, :iv => iv, :algorithm => algorithm)
|
37
|
+
assert_equal original_value, Encryptor.decrypt(encrypted_value_with_iv, :key => key, :iv => iv, :salt => salt, :algorithm => algorithm)
|
35
38
|
end
|
36
39
|
|
37
40
|
define_method "test_should_decrypt_with_the_#{algorithm}_algorithm_without_iv_with_the_first_arg_as_the_value" do
|
@@ -39,7 +42,7 @@ class EncryptorTest < Test::Unit::TestCase
|
|
39
42
|
end
|
40
43
|
|
41
44
|
define_method "test_should_call_encrypt_on_a_string_with_the_#{algorithm}_algorithm_with_iv" do
|
42
|
-
assert_equal encrypted_value_with_iv, original_value.encrypt(:key => key, :iv => iv, :algorithm => algorithm)
|
45
|
+
assert_equal encrypted_value_with_iv, original_value.encrypt(:key => key, :iv => iv, :salt => salt, :algorithm => algorithm)
|
43
46
|
end
|
44
47
|
|
45
48
|
define_method "test_should_call_encrypt_on_a_string_with_the_#{algorithm}_algorithm_without_iv" do
|
@@ -47,7 +50,7 @@ class EncryptorTest < Test::Unit::TestCase
|
|
47
50
|
end
|
48
51
|
|
49
52
|
define_method "test_should_call_decrypt_on_a_string_with_the_#{algorithm}_algorithm_with_iv" do
|
50
|
-
assert_equal original_value, encrypted_value_with_iv.decrypt(:key => key, :iv => iv, :algorithm => algorithm)
|
53
|
+
assert_equal original_value, encrypted_value_with_iv.decrypt(:key => key, :iv => iv, :salt => salt, :algorithm => algorithm)
|
51
54
|
end
|
52
55
|
|
53
56
|
define_method "test_should_call_decrypt_on_a_string_with_the_#{algorithm}_algorithm_without_iv" do
|
@@ -56,8 +59,8 @@ class EncryptorTest < Test::Unit::TestCase
|
|
56
59
|
|
57
60
|
define_method "test_string_encrypt!_on_a_string_with_the_#{algorithm}_algorithm_with_iv" do
|
58
61
|
original_value_dup = original_value.dup
|
59
|
-
original_value_dup.encrypt!(:key => key, :iv => iv, :algorithm => algorithm)
|
60
|
-
assert_equal original_value.encrypt(:key => key, :iv => iv, :algorithm => algorithm), original_value_dup
|
62
|
+
original_value_dup.encrypt!(:key => key, :iv => iv, :salt => salt, :algorithm => algorithm)
|
63
|
+
assert_equal original_value.encrypt(:key => key, :iv => iv, :salt => salt, :algorithm => algorithm), original_value_dup
|
61
64
|
end
|
62
65
|
|
63
66
|
define_method "test_string_encrypt!_on_a_string_with_the_#{algorithm}_algorithm_without_iv" do
|
@@ -68,7 +71,7 @@ class EncryptorTest < Test::Unit::TestCase
|
|
68
71
|
|
69
72
|
define_method "test_string_decrypt!_on_a_string_with_the_#{algorithm}_algorithm_with_iv" do
|
70
73
|
encrypted_value_with_iv_dup = encrypted_value_with_iv.dup
|
71
|
-
encrypted_value_with_iv_dup.decrypt!(:key => key, :iv => iv, :algorithm => algorithm)
|
74
|
+
encrypted_value_with_iv_dup.decrypt!(:key => key, :iv => iv, :salt => salt, :algorithm => algorithm)
|
72
75
|
assert_equal original_value, encrypted_value_with_iv_dup
|
73
76
|
end
|
74
77
|
|
@@ -101,4 +104,5 @@ class EncryptorTest < Test::Unit::TestCase
|
|
101
104
|
assert called
|
102
105
|
end
|
103
106
|
|
104
|
-
end
|
107
|
+
end
|
108
|
+
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require File.expand_path('../test_helper', __FILE__)
|
2
|
+
require File.expand_path('../openssl_helper', __FILE__)
|
3
|
+
|
4
|
+
# Tests for legacy (non-salted) encryption mode
|
5
|
+
#
|
6
|
+
class LegacyEncryptorTest < Test::Unit::TestCase
|
7
|
+
|
8
|
+
key = Digest::SHA256.hexdigest(([Time.now.to_s] * rand(3)).join)
|
9
|
+
iv = Digest::SHA256.hexdigest(([Time.now.to_s] * rand(3)).join)
|
10
|
+
original_value = Digest::SHA256.hexdigest(([Time.now.to_s] * rand(3)).join)
|
11
|
+
|
12
|
+
OpenSSLHelper::ALGORITHMS.each do |algorithm|
|
13
|
+
encrypted_value_with_iv = Encryptor.encrypt(:value => original_value, :key => key, :iv => iv, :algorithm => algorithm)
|
14
|
+
encrypted_value_without_iv = Encryptor.encrypt(:value => original_value, :key => key, :algorithm => algorithm)
|
15
|
+
|
16
|
+
define_method "test_should_crypt_with_the_#{algorithm}_algorithm_with_iv" do
|
17
|
+
assert_not_equal original_value, encrypted_value_with_iv
|
18
|
+
assert_not_equal encrypted_value_without_iv, encrypted_value_with_iv
|
19
|
+
assert_equal original_value, Encryptor.decrypt(:value => encrypted_value_with_iv, :key => key, :iv => iv, :algorithm => algorithm)
|
20
|
+
end
|
21
|
+
|
22
|
+
define_method "test_should_crypt_with_the_#{algorithm}_algorithm_without_iv" do
|
23
|
+
assert_not_equal original_value, encrypted_value_without_iv
|
24
|
+
assert_equal original_value, Encryptor.decrypt(:value => encrypted_value_without_iv, :key => key, :algorithm => algorithm)
|
25
|
+
end
|
26
|
+
|
27
|
+
define_method "test_should_encrypt_with_the_#{algorithm}_algorithm_with_iv_with_the_first_arg_as_the_value" do
|
28
|
+
assert_equal encrypted_value_with_iv, Encryptor.encrypt(original_value, :key => key, :iv => iv, :algorithm => algorithm)
|
29
|
+
end
|
30
|
+
|
31
|
+
define_method "test_should_encrypt_with_the_#{algorithm}_algorithm_without_iv_with_the_first_arg_as_the_value" do
|
32
|
+
assert_equal encrypted_value_without_iv, Encryptor.encrypt(original_value, :key => key, :algorithm => algorithm)
|
33
|
+
end
|
34
|
+
|
35
|
+
define_method "test_should_decrypt_with_the_#{algorithm}_algorithm_with_iv_with_the_first_arg_as_the_value" do
|
36
|
+
assert_equal original_value, Encryptor.decrypt(encrypted_value_with_iv, :key => key, :iv => iv, :algorithm => algorithm)
|
37
|
+
end
|
38
|
+
|
39
|
+
define_method "test_should_decrypt_with_the_#{algorithm}_algorithm_without_iv_with_the_first_arg_as_the_value" do
|
40
|
+
assert_equal original_value, Encryptor.decrypt(encrypted_value_without_iv, :key => key, :algorithm => algorithm)
|
41
|
+
end
|
42
|
+
|
43
|
+
define_method "test_should_call_encrypt_on_a_string_with_the_#{algorithm}_algorithm_with_iv" do
|
44
|
+
assert_equal encrypted_value_with_iv, original_value.encrypt(:key => key, :iv => iv, :algorithm => algorithm)
|
45
|
+
end
|
46
|
+
|
47
|
+
define_method "test_should_call_encrypt_on_a_string_with_the_#{algorithm}_algorithm_without_iv" do
|
48
|
+
assert_equal encrypted_value_without_iv, original_value.encrypt(:key => key, :algorithm => algorithm)
|
49
|
+
end
|
50
|
+
|
51
|
+
define_method "test_should_call_decrypt_on_a_string_with_the_#{algorithm}_algorithm_with_iv" do
|
52
|
+
assert_equal original_value, encrypted_value_with_iv.decrypt(:key => key, :iv => iv, :algorithm => algorithm)
|
53
|
+
end
|
54
|
+
|
55
|
+
define_method "test_should_call_decrypt_on_a_string_with_the_#{algorithm}_algorithm_without_iv" do
|
56
|
+
assert_equal original_value, encrypted_value_without_iv.decrypt(:key => key, :algorithm => algorithm)
|
57
|
+
end
|
58
|
+
|
59
|
+
define_method "test_string_encrypt!_on_a_string_with_the_#{algorithm}_algorithm_with_iv" do
|
60
|
+
original_value_dup = original_value.dup
|
61
|
+
original_value_dup.encrypt!(:key => key, :iv => iv, :algorithm => algorithm)
|
62
|
+
assert_equal original_value.encrypt(:key => key, :iv => iv, :algorithm => algorithm), original_value_dup
|
63
|
+
end
|
64
|
+
|
65
|
+
define_method "test_string_encrypt!_on_a_string_with_the_#{algorithm}_algorithm_without_iv" do
|
66
|
+
original_value_dup = original_value.dup
|
67
|
+
original_value_dup.encrypt!(:key => key, :algorithm => algorithm)
|
68
|
+
assert_equal original_value.encrypt(:key => key, :algorithm => algorithm), original_value_dup
|
69
|
+
end
|
70
|
+
|
71
|
+
define_method "test_string_decrypt!_on_a_string_with_the_#{algorithm}_algorithm_with_iv" do
|
72
|
+
encrypted_value_with_iv_dup = encrypted_value_with_iv.dup
|
73
|
+
encrypted_value_with_iv_dup.decrypt!(:key => key, :iv => iv, :algorithm => algorithm)
|
74
|
+
assert_equal original_value, encrypted_value_with_iv_dup
|
75
|
+
end
|
76
|
+
|
77
|
+
define_method "test_string_decrypt!_on_a_string_with_the_#{algorithm}_algorithm_without_iv" do
|
78
|
+
encrypted_value_without_iv_dup = encrypted_value_without_iv.dup
|
79
|
+
encrypted_value_without_iv_dup.decrypt!(:key => key, :algorithm => algorithm)
|
80
|
+
assert_equal original_value, encrypted_value_without_iv_dup
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
define_method 'test_should_use_the_default_algorithm_if_one_is_not_specified' do
|
85
|
+
assert_equal Encryptor.encrypt(:value => original_value, :key => key, :algorithm => Encryptor.default_options[:algorithm]), Encryptor.encrypt(:value => original_value, :key => key)
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_should_have_a_default_algorithm
|
89
|
+
assert !Encryptor.default_options[:algorithm].nil?
|
90
|
+
assert !Encryptor.default_options[:algorithm].empty?
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_should_raise_argument_error_if_key_is_not_specified
|
94
|
+
assert_raises(ArgumentError) { Encryptor.encrypt('some value') }
|
95
|
+
assert_raises(ArgumentError) { Encryptor.decrypt('some encrypted string') }
|
96
|
+
assert_raises(ArgumentError) { Encryptor.encrypt('some value', :key => '') }
|
97
|
+
assert_raises(ArgumentError) { Encryptor.decrypt('some encrypted string', :key => '') }
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_should_yield_block_with_cipher_and_options
|
101
|
+
called = false
|
102
|
+
Encryptor.encrypt('some value', :key => 'some key') { |cipher, options| called = true }
|
103
|
+
assert called
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
|
data/test/test_helper.rb
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
if RUBY_VERSION >= '1.9.3'
|
2
|
+
require 'simplecov'
|
3
|
+
require 'simplecov-rcov'
|
4
|
+
|
5
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
6
|
+
SimpleCov::Formatter::HTMLFormatter,
|
7
|
+
SimpleCov::Formatter::RcovFormatter,
|
8
|
+
]
|
9
|
+
|
10
|
+
SimpleCov.start do
|
11
|
+
add_filter 'test'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
1
15
|
require 'test/unit'
|
2
16
|
require 'digest/sha2'
|
3
17
|
|
metadata
CHANGED
@@ -1,75 +1,120 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: encryptor
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.3.0
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 1
|
8
|
-
- 1
|
9
|
-
- 3
|
10
|
-
version: 1.1.3
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Sean Huber
|
9
|
+
- S. Brent Faulkner
|
10
|
+
- William Monk
|
14
11
|
autorequire:
|
15
12
|
bindir: bin
|
16
13
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
14
|
+
date: 2013-11-14 00:00:00.000000000 Z
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: rake
|
18
|
+
requirement: !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - '='
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.9.2.2
|
24
|
+
type: :development
|
25
|
+
prerelease: false
|
26
|
+
version_requirements: !ruby/object:Gem::Requirement
|
27
|
+
none: false
|
28
|
+
requirements:
|
29
|
+
- - '='
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
version: 0.9.2.2
|
32
|
+
- !ruby/object:Gem::Dependency
|
33
|
+
name: simplecov
|
34
|
+
requirement: !ruby/object:Gem::Requirement
|
35
|
+
none: false
|
36
|
+
requirements:
|
37
|
+
- - ! '>='
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
type: :development
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
44
|
+
requirements:
|
45
|
+
- - ! '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: simplecov-rcov
|
50
|
+
requirement: !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ! '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
type: :development
|
57
|
+
prerelease: false
|
58
|
+
version_requirements: !ruby/object:Gem::Requirement
|
59
|
+
none: false
|
60
|
+
requirements:
|
61
|
+
- - ! '>='
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0'
|
64
|
+
description: A simple wrapper for the standard ruby OpenSSL library to encrypt and
|
65
|
+
decrypt strings
|
66
|
+
email:
|
67
|
+
- shuber@huberry.com
|
68
|
+
- sbfaulkner@gmail.com
|
69
|
+
- billy.monk@gmail.com
|
24
70
|
executables: []
|
25
|
-
|
26
71
|
extensions: []
|
27
|
-
|
28
72
|
extra_rdoc_files: []
|
29
|
-
|
30
|
-
files:
|
73
|
+
files:
|
31
74
|
- lib/encryptor/string.rb
|
32
75
|
- lib/encryptor/version.rb
|
33
76
|
- lib/encryptor.rb
|
34
77
|
- MIT-LICENSE
|
35
78
|
- Rakefile
|
36
|
-
- README.
|
79
|
+
- README.md
|
80
|
+
- test/compatibility_test.rb
|
37
81
|
- test/encryptor_test.rb
|
82
|
+
- test/legacy_encryptor_test.rb
|
83
|
+
- test/openssl_helper.rb
|
38
84
|
- test/test_helper.rb
|
39
|
-
|
40
|
-
homepage: http://github.com/shuber/encryptor
|
85
|
+
homepage: http://github.com/attr-encrypted/encryptor
|
41
86
|
licenses: []
|
42
|
-
|
43
87
|
post_install_message:
|
44
88
|
rdoc_options: []
|
45
|
-
|
46
|
-
require_paths:
|
89
|
+
require_paths:
|
47
90
|
- lib
|
48
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
49
92
|
none: false
|
50
|
-
requirements:
|
51
|
-
- -
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
|
54
|
-
segments:
|
93
|
+
requirements:
|
94
|
+
- - ! '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
segments:
|
55
98
|
- 0
|
56
|
-
|
57
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
|
+
hash: -1331952118017536783
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
101
|
none: false
|
59
|
-
requirements:
|
60
|
-
- -
|
61
|
-
- !ruby/object:Gem::Version
|
62
|
-
|
63
|
-
segments:
|
102
|
+
requirements:
|
103
|
+
- - ! '>='
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
segments:
|
64
107
|
- 0
|
65
|
-
|
108
|
+
hash: -1331952118017536783
|
66
109
|
requirements: []
|
67
|
-
|
68
110
|
rubyforge_project:
|
69
|
-
rubygems_version: 1.
|
111
|
+
rubygems_version: 1.8.23
|
70
112
|
signing_key:
|
71
113
|
specification_version: 3
|
72
114
|
summary: A simple wrapper for the standard ruby OpenSSL library
|
73
|
-
test_files:
|
115
|
+
test_files:
|
116
|
+
- test/compatibility_test.rb
|
74
117
|
- test/encryptor_test.rb
|
118
|
+
- test/legacy_encryptor_test.rb
|
119
|
+
- test/openssl_helper.rb
|
75
120
|
- test/test_helper.rb
|
data/README.rdoc
DELETED
@@ -1,103 +0,0 @@
|
|
1
|
-
= Encryptor
|
2
|
-
|
3
|
-
A simple wrapper for the standard ruby OpenSSL library
|
4
|
-
|
5
|
-
Used by http://github.com/shuber/attr_encrypted to easily encrypt/decrypt attributes in any class
|
6
|
-
|
7
|
-
|
8
|
-
== Installation
|
9
|
-
|
10
|
-
gem install encryptor
|
11
|
-
|
12
|
-
|
13
|
-
== Usage
|
14
|
-
|
15
|
-
|
16
|
-
=== Basic
|
17
|
-
|
18
|
-
secret_key = Digest::SHA256.hexdigest('a secret key')
|
19
|
-
encrypted_value = Encryptor.encrypt('some string to encrypt', :key => secret_key) # '������{)��q�ށ�ܣ��q���Au/�ޜP'
|
20
|
-
decrypted_value = Encryptor.decrypt(encrypted_value, :key => secret_key) # 'some string to encrypt'
|
21
|
-
|
22
|
-
The value to encrypt or decrypt may also be passed as the <tt>:value</tt> option if you'd like.
|
23
|
-
|
24
|
-
encrypted_value = Encryptor.encrypt(:value => 'some string to encrypt', :key => secret_key) # '������{)��q�ށ�ܣ��q���Au/�ޜP'
|
25
|
-
decrypted_value = Encryptor.decrypt(:value => encrypted_value, :key => secret_key) # 'some string to encrypt'
|
26
|
-
|
27
|
-
You may also pass the <tt>:iv</tt> and <tt>:algorithm</tt> options but they are not required. If an algorithm is not specified, the Encryptor uses
|
28
|
-
the algorithm found at <tt>Encryptor.default_options[:algorithm]</tt> which is <tt>aes-256-cbc</tt> by default. You can change the default options
|
29
|
-
by overwriting or merging this attribute:
|
30
|
-
|
31
|
-
Encryptor.default_options.merge!(:algorithm => 'bf', :key => 'some default secret key')
|
32
|
-
|
33
|
-
|
34
|
-
=== Strings
|
35
|
-
|
36
|
-
<tt>Encryptor</tt> adds <tt>encrypt</tt> and <tt>decrypt</tt> methods to <tt>String</tt> objects for your convenience. These two methods accept the same arguments as the associated ones in the <tt>Encryptor</tt> module. They're nice when you set the default options in the <tt>Encryptor.default_options</tt> attribute. For example:
|
37
|
-
|
38
|
-
Encryptor.default_options.merge!(:key => 'some default secret key')
|
39
|
-
credit_card = 'xxxx xxxx xxxx 1234'
|
40
|
-
encrypted_credit_card = credit_card.encrypt
|
41
|
-
|
42
|
-
There's also <tt>encrypt!</tt> and <tt>decrypt!</tt> methods that replace the contents of a string with the encrypted or decrypted version of itself.
|
43
|
-
|
44
|
-
|
45
|
-
=== Algorithms
|
46
|
-
|
47
|
-
Run <tt>openssl list-cipher-commands</tt> in your terminal to view a list of all cipher algorithms that are supported on your platform.
|
48
|
-
|
49
|
-
aes-128-cbc
|
50
|
-
aes-128-ecb
|
51
|
-
aes-192-cbc
|
52
|
-
aes-192-ecb
|
53
|
-
aes-256-cbc
|
54
|
-
aes-256-ecb
|
55
|
-
bf
|
56
|
-
bf-cbc
|
57
|
-
bf-cfb
|
58
|
-
bf-ecb
|
59
|
-
bf-ofb
|
60
|
-
cast
|
61
|
-
cast-cbc
|
62
|
-
cast5-cbc
|
63
|
-
cast5-cfb
|
64
|
-
cast5-ecb
|
65
|
-
cast5-ofb
|
66
|
-
des
|
67
|
-
des-cbc
|
68
|
-
des-cfb
|
69
|
-
des-ecb
|
70
|
-
des-ede
|
71
|
-
des-ede-cbc
|
72
|
-
des-ede-cfb
|
73
|
-
des-ede-ofb
|
74
|
-
des-ede3
|
75
|
-
des-ede3-cbc
|
76
|
-
des-ede3-cfb
|
77
|
-
des-ede3-ofb
|
78
|
-
des-ofb
|
79
|
-
des3
|
80
|
-
desx
|
81
|
-
idea
|
82
|
-
idea-cbc
|
83
|
-
idea-cfb
|
84
|
-
idea-ecb
|
85
|
-
idea-ofb
|
86
|
-
rc2
|
87
|
-
rc2-40-cbc
|
88
|
-
rc2-64-cbc
|
89
|
-
rc2-cbc
|
90
|
-
rc2-cfb
|
91
|
-
rc2-ecb
|
92
|
-
rc2-ofb
|
93
|
-
rc4
|
94
|
-
rc4-40
|
95
|
-
|
96
|
-
|
97
|
-
== Note on Patches/Pull Requests
|
98
|
-
|
99
|
-
* Fork the project.
|
100
|
-
* Make your feature addition or bug fix.
|
101
|
-
* Add tests for it. This is important so I don't break it in a future version unintentionally.
|
102
|
-
* Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
103
|
-
* Send me a pull request. Bonus points for topic branches.
|