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 CHANGED
@@ -1,4 +1,8 @@
1
- # CryptKeeper
1
+ [![Build Status](https://secure.travis-ci.org/jmazzi/crypt_keeper.png?branch=master)](http://travis-ci.org/jmazzi/crypt_keeper)
2
+
3
+ ![CryptKeeper](http://i.imgur.com/qf0aD.jpg)
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: CryptKeeperProviders::Aes,
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.3'
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'
@@ -9,14 +9,14 @@ module CryptKeeper
9
9
  private
10
10
 
11
11
  # Private: Encrypt each crypt_keeper_fields
12
- def before_save_encrypt
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 after_save_decrypt
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: CryptKeeperProviders::Aes,
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
- crypt_keeper_encryptor.new(crypt_keeper_options.dup)
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 crypt_keeper_encryptor.respond_to?(:new)
73
- raise "You must specify an encryption class `crypt_keeper encryptor: EncryptionClass`"
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 :after_save_decrypt
80
- after_find :after_save_decrypt
81
- before_save :before_save_encrypt
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
@@ -1,3 +1,3 @@
1
1
  module CryptKeeper
2
- VERSION = "0.0.4"
2
+ VERSION = "0.1.0"
3
3
  end
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: 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: encryptor }.to raise_error(ArgumentError, msg)
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: 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 :after_save_decrypt
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 :before_save_encrypt
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
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: &6479720 !ruby/object:Gem::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: *6479720
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: &6478940 !ruby/object:Gem::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: *6478940
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: &6494620 !ruby/object:Gem::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.3
53
+ version: 0.0.4
44
54
  type: :runtime
45
55
  prerelease: false
46
- version_requirements: *6494620
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: &6493320 !ruby/object:Gem::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: *6493320
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: &6490560 !ruby/object:Gem::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: *6490560
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: &6488360 !ruby/object:Gem::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: *6488360
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: &6502220 !ruby/object:Gem::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: *6502220
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: &6500300 !ruby/object:Gem::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: *6500300
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: -259501510008969600
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: -259501510008969600
188
+ hash: 2759538915342928512
148
189
  requirements: []
149
190
  rubyforge_project:
150
- rubygems_version: 1.8.11
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