crypt_keeper 0.0.4 → 0.1.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 +37 -5
- data/crypt_keeper.gemspec +1 -1
- data/lib/crypt_keeper/model.rb +14 -10
- data/lib/crypt_keeper/version.rb +1 -1
- data/spec/model_spec.rb +6 -28
- data/spec/support/encryptors.rb +26 -0
- metadata +63 -21
data/README.md
CHANGED
@@ -1,4 +1,8 @@
|
|
1
|
-
|
1
|
+
[](http://travis-ci.org/jmazzi/crypt_keeper)
|
2
|
+
|
3
|
+

|
4
|
+
|
5
|
+
# CryptKeeper
|
2
6
|
|
3
7
|
Provides transparent encryption for ActiveRecord. It is encryption agnostic.
|
4
8
|
You can guard your data with any encryption algorithm you want. All you need
|
@@ -22,21 +26,49 @@ simple that *just works*.
|
|
22
26
|
## Usage
|
23
27
|
|
24
28
|
```ruby
|
25
|
-
|
26
29
|
class MyModel < ActiveRecord::Base
|
27
|
-
crypt_keeper :field, :other_field, encryptor:
|
28
|
-
passphrase: 'super_good_password'
|
30
|
+
crypt_keeper :field, :other_field, :encryptor => :aes, :passphrase => 'super_good_password'
|
29
31
|
end
|
30
32
|
|
31
33
|
model = MyModel.new(field: 'sometext')
|
32
34
|
model.save! #=> Your data is now encrypted
|
33
35
|
model.field #=> 'sometext'
|
34
|
-
|
35
36
|
```
|
36
37
|
|
37
38
|
It works with all persistences methods: `update_attribute`, `update_attributes`,
|
38
39
|
and save.
|
39
40
|
|
41
|
+
## Creating your own encryptor
|
42
|
+
|
43
|
+
Creating your own encryptor is easy. All you have to do is create a class
|
44
|
+
under the `CryptKeeperProviders` namespace, like this:
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
module CryptKeeperProviders
|
48
|
+
class MyEncryptor
|
49
|
+
def initialize(options ={})
|
50
|
+
end
|
51
|
+
|
52
|
+
def encrypt(value)
|
53
|
+
end
|
54
|
+
|
55
|
+
def decrypt(value)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
```
|
61
|
+
|
62
|
+
Just require your code and setup your model to use it. Just pass the class name
|
63
|
+
as an underscored symbol
|
64
|
+
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
class MyModel < ActiveRecord::Base
|
68
|
+
crypt_keeper :field, :other_field, :encryptor => :my_encryptor, :passphrase => 'super_good_password'
|
69
|
+
end
|
70
|
+
```
|
71
|
+
|
40
72
|
## Installation
|
41
73
|
|
42
74
|
Add this line to your application's Gemfile:
|
data/crypt_keeper.gemspec
CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |gem|
|
|
17
17
|
|
18
18
|
gem.add_runtime_dependency 'activerecord', '>= 3.0'
|
19
19
|
gem.add_runtime_dependency 'activesupport', '>= 3.0'
|
20
|
-
gem.add_runtime_dependency 'crypt_keeper_providers', '~> 0.0.
|
20
|
+
gem.add_runtime_dependency 'crypt_keeper_providers', '~> 0.0.4'
|
21
21
|
|
22
22
|
gem.add_development_dependency 'rspec', '~> 2.10.0'
|
23
23
|
gem.add_development_dependency 'guard', '~> 1.2.0'
|
data/lib/crypt_keeper/model.rb
CHANGED
@@ -9,14 +9,14 @@ module CryptKeeper
|
|
9
9
|
private
|
10
10
|
|
11
11
|
# Private: Encrypt each crypt_keeper_fields
|
12
|
-
def
|
12
|
+
def encrypt_callback
|
13
13
|
crypt_keeper_fields.each do |field|
|
14
14
|
self[field] = self.class.encrypt read_attribute(field)
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
18
|
# Private: Decrypt each crypt_keeper_fields
|
19
|
-
def
|
19
|
+
def decrypt_callback
|
20
20
|
crypt_keeper_fields.each do |field|
|
21
21
|
self[field] = self.class.decrypt read_attribute(field)
|
22
22
|
end
|
@@ -33,8 +33,7 @@ module CryptKeeper
|
|
33
33
|
# Example
|
34
34
|
#
|
35
35
|
# class MyModel < ActiveRecord::Base
|
36
|
-
# crypt_keeper :field, :other_field, encryptor:
|
37
|
-
# passphrase: 'super_good_password'
|
36
|
+
# crypt_keeper :field, :other_field, :encryptor => :aes, :passphrase => 'super_good_password'
|
38
37
|
# end
|
39
38
|
#
|
40
39
|
def crypt_keeper(*args)
|
@@ -64,21 +63,26 @@ module CryptKeeper
|
|
64
63
|
|
65
64
|
# Private: An instance of the encryptor class
|
66
65
|
def encryptor
|
67
|
-
|
66
|
+
@encryptor ||= encryptor_klass.new(crypt_keeper_options.dup)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Private: The encryptor class
|
70
|
+
def encryptor_klass
|
71
|
+
@encryptor_klass ||= "CryptKeeperProviders::#{crypt_keeper_encryptor.to_s.camelize}".constantize
|
68
72
|
end
|
69
73
|
|
70
74
|
# Private: Ensure that the encryptor responds to new
|
71
75
|
def ensure_valid_encryptor!
|
72
|
-
unless
|
73
|
-
raise "You must specify
|
76
|
+
unless defined? encryptor_klass
|
77
|
+
raise "You must specify a valid encryptor `crypt_keeper :encryptor => :aes`"
|
74
78
|
end
|
75
79
|
end
|
76
80
|
|
77
81
|
# Private: Define callbacks for encryption
|
78
82
|
def define_crypt_keeper_callbacks
|
79
|
-
after_save :
|
80
|
-
after_find :
|
81
|
-
before_save :
|
83
|
+
after_save :decrypt_callback
|
84
|
+
after_find :decrypt_callback
|
85
|
+
before_save :encrypt_callback
|
82
86
|
|
83
87
|
crypt_keeper_fields.each do |field|
|
84
88
|
ensure_field_is_encryptable! field
|
data/lib/crypt_keeper/version.rb
CHANGED
data/spec/model_spec.rb
CHANGED
@@ -3,55 +3,33 @@ require 'spec_helper'
|
|
3
3
|
module CryptKeeper
|
4
4
|
describe Model do
|
5
5
|
subject { SensitiveData }
|
6
|
-
let(:encryptor) do
|
7
|
-
mock('Encryptor').tap do |m|
|
8
|
-
m.stub :new
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
6
|
describe "#crypt_keeper" do
|
13
7
|
context "Fields" do
|
14
8
|
it "should set the fields" do
|
15
|
-
subject.crypt_keeper :storage, :secret, encryptor:
|
9
|
+
subject.crypt_keeper :storage, :secret, encryptor: :fake_encryptor
|
16
10
|
subject.crypt_keeper_fields.should == [:storage, :secret]
|
17
11
|
end
|
18
12
|
|
19
13
|
it "should raise an exception with wrong field type" do
|
20
14
|
msg = ":name must be of type 'text' to be used for encryption"
|
21
|
-
expect { subject.crypt_keeper :name, encryptor:
|
15
|
+
expect { subject.crypt_keeper :name, encryptor: :fake_encryptor }.to raise_error(ArgumentError, msg)
|
22
16
|
end
|
23
17
|
end
|
24
18
|
|
25
19
|
context "Options" do
|
26
20
|
it "should set the options" do
|
27
|
-
subject.crypt_keeper :storage, :secret, key1: 1, key2: 2, encryptor:
|
21
|
+
subject.crypt_keeper :storage, :secret, key1: 1, key2: 2, encryptor: :fake_encryptor
|
28
22
|
subject.crypt_keeper_options.should == { key1: 1, key2: 2 }
|
29
23
|
end
|
30
24
|
end
|
31
25
|
end
|
32
26
|
|
33
27
|
context "Encryption" do
|
34
|
-
let(:encryptor) do
|
35
|
-
Class.new do
|
36
|
-
def initialize(options = {})
|
37
|
-
@passphrase = options[:passphrase]
|
38
|
-
end
|
39
|
-
|
40
|
-
def encrypt(data)
|
41
|
-
@passphrase + data.reverse
|
42
|
-
end
|
43
|
-
|
44
|
-
def decrypt(data)
|
45
|
-
data.sub(/^#{@passphrase}/, '').reverse
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
28
|
let(:plain_text) { 'plain_text' }
|
51
29
|
let(:cipher_text) { 'tooltxet_nialp' }
|
52
30
|
|
53
31
|
before do
|
54
|
-
SensitiveData.crypt_keeper :storage, passphrase: 'tool', encryptor: encryptor
|
32
|
+
SensitiveData.crypt_keeper :storage, passphrase: 'tool', encryptor: :encryptor
|
55
33
|
end
|
56
34
|
|
57
35
|
subject { SensitiveData.new }
|
@@ -59,7 +37,7 @@ module CryptKeeper
|
|
59
37
|
describe "#encrypt" do
|
60
38
|
it "should encrypt the data" do
|
61
39
|
subject.storage = plain_text
|
62
|
-
subject.stub :
|
40
|
+
subject.stub :decrypt_callback
|
63
41
|
subject.save!
|
64
42
|
subject.storage.should == cipher_text
|
65
43
|
end
|
@@ -68,7 +46,7 @@ module CryptKeeper
|
|
68
46
|
describe "#decrypt" do
|
69
47
|
it "should decrypt the data" do
|
70
48
|
subject.storage = cipher_text
|
71
|
-
subject.stub :
|
49
|
+
subject.stub :encrypt_callback
|
72
50
|
subject.save!
|
73
51
|
subject.storage.should == plain_text
|
74
52
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# A fake class that does no encryption
|
2
|
+
module CryptKeeperProviders
|
3
|
+
class FakeEncryptor
|
4
|
+
def initialize(*args)
|
5
|
+
end
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
# This class embeds the passphrase in the beginning of the string
|
10
|
+
# and then reverses the 'plaintext'
|
11
|
+
module CryptKeeperProviders
|
12
|
+
class Encryptor
|
13
|
+
def initialize(options = {})
|
14
|
+
@passphrase = options[:passphrase]
|
15
|
+
end
|
16
|
+
|
17
|
+
def encrypt(data)
|
18
|
+
@passphrase + data.reverse
|
19
|
+
end
|
20
|
+
|
21
|
+
def decrypt(data)
|
22
|
+
data.sub(/^#{@passphrase}/, '').reverse
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: crypt_keeper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ date: 2012-07-27 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,15 @@ dependencies:
|
|
21
21
|
version: '3.0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '3.0'
|
25
30
|
- !ruby/object:Gem::Dependency
|
26
31
|
name: activesupport
|
27
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
28
33
|
none: false
|
29
34
|
requirements:
|
30
35
|
- - ! '>='
|
@@ -32,21 +37,31 @@ dependencies:
|
|
32
37
|
version: '3.0'
|
33
38
|
type: :runtime
|
34
39
|
prerelease: false
|
35
|
-
version_requirements:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '3.0'
|
36
46
|
- !ruby/object:Gem::Dependency
|
37
47
|
name: crypt_keeper_providers
|
38
|
-
requirement:
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
39
49
|
none: false
|
40
50
|
requirements:
|
41
51
|
- - ~>
|
42
52
|
- !ruby/object:Gem::Version
|
43
|
-
version: 0.0.
|
53
|
+
version: 0.0.4
|
44
54
|
type: :runtime
|
45
55
|
prerelease: false
|
46
|
-
version_requirements:
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.0.4
|
47
62
|
- !ruby/object:Gem::Dependency
|
48
63
|
name: rspec
|
49
|
-
requirement:
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
50
65
|
none: false
|
51
66
|
requirements:
|
52
67
|
- - ~>
|
@@ -54,10 +69,15 @@ dependencies:
|
|
54
69
|
version: 2.10.0
|
55
70
|
type: :development
|
56
71
|
prerelease: false
|
57
|
-
version_requirements:
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 2.10.0
|
58
78
|
- !ruby/object:Gem::Dependency
|
59
79
|
name: guard
|
60
|
-
requirement:
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
61
81
|
none: false
|
62
82
|
requirements:
|
63
83
|
- - ~>
|
@@ -65,10 +85,15 @@ dependencies:
|
|
65
85
|
version: 1.2.0
|
66
86
|
type: :development
|
67
87
|
prerelease: false
|
68
|
-
version_requirements:
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 1.2.0
|
69
94
|
- !ruby/object:Gem::Dependency
|
70
95
|
name: guard-rspec
|
71
|
-
requirement:
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
72
97
|
none: false
|
73
98
|
requirements:
|
74
99
|
- - ~>
|
@@ -76,10 +101,15 @@ dependencies:
|
|
76
101
|
version: 1.1.0
|
77
102
|
type: :development
|
78
103
|
prerelease: false
|
79
|
-
version_requirements:
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 1.1.0
|
80
110
|
- !ruby/object:Gem::Dependency
|
81
111
|
name: rake
|
82
|
-
requirement:
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
83
113
|
none: false
|
84
114
|
requirements:
|
85
115
|
- - ~>
|
@@ -87,10 +117,15 @@ dependencies:
|
|
87
117
|
version: 0.9.2.2
|
88
118
|
type: :development
|
89
119
|
prerelease: false
|
90
|
-
version_requirements:
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ~>
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: 0.9.2.2
|
91
126
|
- !ruby/object:Gem::Dependency
|
92
127
|
name: sqlite3
|
93
|
-
requirement:
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
94
129
|
none: false
|
95
130
|
requirements:
|
96
131
|
- - ! '>='
|
@@ -98,7 +133,12 @@ dependencies:
|
|
98
133
|
version: '0'
|
99
134
|
type: :development
|
100
135
|
prerelease: false
|
101
|
-
version_requirements:
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ! '>='
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
102
142
|
description: Transparent encryption for ActiveRecord that isn't over-engineered
|
103
143
|
email:
|
104
144
|
- jmazzi@gmail.com
|
@@ -121,6 +161,7 @@ files:
|
|
121
161
|
- spec/model_spec.rb
|
122
162
|
- spec/spec_helper.rb
|
123
163
|
- spec/support/active_record.rb
|
164
|
+
- spec/support/encryptors.rb
|
124
165
|
homepage: ''
|
125
166
|
licenses: []
|
126
167
|
post_install_message:
|
@@ -135,7 +176,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
135
176
|
version: '0'
|
136
177
|
segments:
|
137
178
|
- 0
|
138
|
-
hash:
|
179
|
+
hash: 2759538915342928512
|
139
180
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
140
181
|
none: false
|
141
182
|
requirements:
|
@@ -144,10 +185,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
144
185
|
version: '0'
|
145
186
|
segments:
|
146
187
|
- 0
|
147
|
-
hash:
|
188
|
+
hash: 2759538915342928512
|
148
189
|
requirements: []
|
149
190
|
rubyforge_project:
|
150
|
-
rubygems_version: 1.8.
|
191
|
+
rubygems_version: 1.8.23
|
151
192
|
signing_key:
|
152
193
|
specification_version: 3
|
153
194
|
summary: Transparent encryption for ActiveRecord that isn't over-engineered
|
@@ -155,3 +196,4 @@ test_files:
|
|
155
196
|
- spec/model_spec.rb
|
156
197
|
- spec/spec_helper.rb
|
157
198
|
- spec/support/active_record.rb
|
199
|
+
- spec/support/encryptors.rb
|