mongoid-encrypted-fields 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGLOG.md ADDED
@@ -0,0 +1,22 @@
1
+ # Revision history
2
+
3
+ ## 1.1 - Breaking changes - PLEASE READ
4
+
5
+ ### encrypted-strings gem
6
+ During performance testing, we've found the [encrypted-strings](https://github.com/pluginaweek/encrypted_strings) gem
7
+ to be very slow under load, and it's patching the == method on String so it has been removed as the default cipher option.
8
+
9
+ ### Gibberish
10
+ [Gibberish](https://github.com/mdp/gibberish) was found to be very fast, but uses a unique salt for each encryption.
11
+ This is normally great for security, but becomes problematic for searching for encrypted fields in Mongoid because each
12
+ search would generate a unique value that wouldn't match what's stored in the database.
13
+
14
+ We've included classes in the **examples** folder to show implementations of using either of these Gems, but remember that
15
+ we only require a class that implements **encrypt** and **decrypt** so you can use any gem of your choice.
16
+
17
+ ### Modifications
18
+
19
+ * Removed included cipher implementations
20
+ * Removed [encrypted-strings](https://github.com/pluginaweek/encrypted_strings) gem dependency
21
+
22
+ ## 1.0 - Initial release
data/README.md CHANGED
@@ -10,16 +10,19 @@ Queries encrypt data before searching the database, so equality matches work aut
10
10
  ## Prerequisites
11
11
  * Ruby 1.9.3
12
12
  * [Mongoid](http://mongoid.org) 3.0
13
- * [Encrypted-Strings](https://github.com/pluginaweek/encrypted_strings)
13
+ * "Bring your own" encryption, see below
14
14
 
15
15
  ## Install
16
16
  gem 'mongoid-encrypted-fields'
17
17
 
18
18
  ## Usage
19
19
  * Configure the cipher to be used for encrypting field values:
20
- ```Ruby
21
- Mongoid::EncryptedFields.cipher = Mongoid::Ciphers::SymmetricCipher.new(algorithm: 'aes-256-cbc', password: ENV['MY_PASSWORD']) # find a secure way to get your password
22
- ```
20
+
21
+ GibberishCipher can be found in examples - uses the [Gibberish](https://github.com/mdp/gibberish) gem:
22
+ ```Ruby
23
+ Mongoid::EncryptedFields.cipher = GibberishCipher.new(ENV['MY_PASSWORD'])
24
+ ```
25
+
23
26
  * Use encrypted types for fields in your models:
24
27
  ```Ruby
25
28
  class Person
@@ -37,6 +40,9 @@ Queries encrypt data before searching the database, so equality matches work aut
37
40
  * The encrypted value is accessible with the "encrypted" attribute
38
41
  ```Ruby
39
42
  person.ssn.encrypted # => <encrypted string>
43
+
44
+ # It can also be accessed using the hash syntax supported by Mongoid
45
+ person[:ssn] # => <encrypted string>
40
46
  ```
41
47
  * Finding a model by an encrypted field works automatically (equality only):
42
48
  ```Ruby
@@ -47,4 +53,4 @@ Queries encrypt data before searching the database, so equality matches work aut
47
53
  * Single cipher for all encrypted fields
48
54
 
49
55
  ## Copyright
50
- (c) 2012 Koan Health. See LICENSE.txt for further details.
56
+ (c) 2012 Koan Health. See LICENSE.txt for further details.
@@ -0,0 +1,20 @@
1
+ require 'encrypted_strings'
2
+
3
+ class EncryptedStringsAsymmetricCipher
4
+
5
+ attr_reader :algorithm, :password, :public_key_file, :private_key_file
6
+
7
+ def initialize(options = {})
8
+ @options = options
9
+ @options.each { |key, value| instance_variable_set "@#{key}", value }
10
+ end
11
+
12
+ def encrypt(data)
13
+ data.encrypt(:asymmetric, @options)
14
+ end
15
+
16
+ def decrypt(data)
17
+ data.decrypt(:asymmetric, @options)
18
+ end
19
+
20
+ end
@@ -0,0 +1,20 @@
1
+ require 'encrypted_strings'
2
+
3
+ class EncryptedStringsSymmetricCipher
4
+
5
+ attr_reader :algorithm, :password
6
+
7
+ def initialize(options = {})
8
+ @options = options
9
+ @options.each { |key, value| instance_variable_set "@#{key}", value }
10
+ end
11
+
12
+ def encrypt(data)
13
+ data.encrypt(:symmetric, @options)
14
+ end
15
+
16
+ def decrypt(data)
17
+ data.decrypt(:symmetric, @options)
18
+ end
19
+
20
+ end
@@ -0,0 +1,19 @@
1
+ require 'gibberish/aes'
2
+
3
+ # Gibberish uses a unique salt for every encryption, but we need the same text to return the same ciphertext
4
+ # so Searching for encrypted field will work
5
+ class GibberishCipher < Gibberish::AES
6
+
7
+ SALT = "OU812FTW" # TODO: If you use this example class, make a unique 8-byte salt for your project
8
+
9
+ def initialize(password, options = {})
10
+ super password, options[:size] || 256
11
+ @salt = options[:salt] || SALT
12
+ end
13
+
14
+ def generate_salt
15
+ return @salt if @salt
16
+ super
17
+ end
18
+
19
+ end
@@ -1,10 +1,5 @@
1
- require 'encrypted_strings'
2
-
3
1
  require 'mongoid-encrypted-fields/version'
4
2
  require 'mongoid-encrypted-fields/logging'
5
- require 'mongoid-encrypted-fields/ciphers/cipher'
6
- require 'mongoid-encrypted-fields/ciphers/asymmetric_cipher'
7
- require 'mongoid-encrypted-fields/ciphers/symmetric_cipher'
8
3
  require 'mongoid-encrypted-fields/fields/encrypted_field'
9
4
  require 'mongoid-encrypted-fields/fields/encrypted_string'
10
5
  require 'mongoid-encrypted-fields/fields/encrypted_date'
@@ -1,5 +1,5 @@
1
1
  module Mongoid
2
2
  module EncryptedFields
3
- VERSION = "1.0.0"
3
+ VERSION = "1.1.0"
4
4
  end
5
5
  end
@@ -19,7 +19,8 @@ Gem::Specification.new do |gem|
19
19
 
20
20
  gem.add_dependency "rake"
21
21
  gem.add_dependency "mongoid", "~> 3"
22
- gem.add_dependency "encrypted_strings", "~> 0.3"
23
22
 
24
23
  gem.add_development_dependency "rspec"
24
+ gem.add_development_dependency "gibberish", "~> 1.2"
25
+ gem.add_development_dependency "encrypted_strings", "~> 0.3"
25
26
  end
@@ -4,7 +4,7 @@ module Mongoid
4
4
  describe EncryptedDate do
5
5
 
6
6
  before(:all) do
7
- Mongoid::EncryptedFields.cipher = Mongoid::Ciphers::SymmetricCipher.new(algorithm: 'aes-256-cbc', password: 'my test password')
7
+ Mongoid::EncryptedFields.cipher = GibberishCipher.new('my test password')
8
8
  end
9
9
 
10
10
  subject { Mongoid::EncryptedDate }
@@ -4,7 +4,7 @@ module Mongoid
4
4
  describe EncryptedDateTime do
5
5
 
6
6
  before(:all) do
7
- Mongoid::EncryptedFields.cipher = Mongoid::Ciphers::SymmetricCipher.new(algorithm: 'aes-256-cbc', password: 'my test password')
7
+ Mongoid::EncryptedFields.cipher = GibberishCipher.new('my test password')
8
8
  end
9
9
 
10
10
  subject { Mongoid::EncryptedDateTime }
@@ -4,7 +4,7 @@ module Mongoid
4
4
  describe EncryptedField do
5
5
 
6
6
  before(:all) do
7
- Mongoid::EncryptedFields.cipher = Mongoid::Ciphers::SymmetricCipher.new(algorithm: 'aes-256-cbc', password: 'my test password')
7
+ Mongoid::EncryptedFields.cipher = GibberishCipher.new('my test password')
8
8
  end
9
9
 
10
10
  it "should encrypt and decrypt a string" do
@@ -4,7 +4,7 @@ module Mongoid
4
4
  describe EncryptedString do
5
5
 
6
6
  before(:all) do
7
- Mongoid::EncryptedFields.cipher = Mongoid::Ciphers::SymmetricCipher.new(algorithm: 'aes-256-cbc', password: 'my test password')
7
+ Mongoid::EncryptedFields.cipher = GibberishCipher.new('my test password')
8
8
  end
9
9
 
10
10
  let(:raw) { "abc123" }
@@ -4,7 +4,7 @@ module Mongoid
4
4
  describe EncryptedTime do
5
5
 
6
6
  before(:all) do
7
- Mongoid::EncryptedFields.cipher = Mongoid::Ciphers::SymmetricCipher.new(algorithm: 'aes-256-cbc', password: 'my test password')
7
+ Mongoid::EncryptedFields.cipher = GibberishCipher.new('my test password')
8
8
  end
9
9
 
10
10
  subject { Mongoid::EncryptedTime }
@@ -3,14 +3,14 @@ require 'spec_helper'
3
3
  describe 'Single model' do
4
4
 
5
5
  before(:all) do
6
- Mongoid::EncryptedFields.cipher = Mongoid::Ciphers::SymmetricCipher.new(algorithm: 'aes-256-cbc', password: 'my test password')
6
+ Mongoid::EncryptedFields.cipher = GibberishCipher.new('my test password')
7
7
  end
8
8
 
9
9
  let (:ssn) { '123456789' }
10
- let (:ssn_encrypted) { Mongoid::EncryptedString.mongoize('123456789') }
10
+ let (:ssn_encrypted) { Mongoid::EncryptedString.mongoize(ssn) }
11
11
  let (:birth_date) { 20.years.ago.to_date }
12
- let (:birth_date_encrypted) { Mongoid::EncryptedDate.mongoize(20.years.ago.to_date) }
13
- let (:person) { Person.new(name: 'John Doe', ssn: '123456789', birth_date: 20.years.ago.to_date) }
12
+ let (:birth_date_encrypted) { Mongoid::EncryptedDate.mongoize(birth_date) }
13
+ let (:person) { Person.new(name: 'John Doe', ssn: ssn, birth_date: birth_date) }
14
14
 
15
15
  it "model stores encrypted ssn" do
16
16
  person.attributes['ssn'].should eq(ssn_encrypted)
data/spec/spec_helper.rb CHANGED
@@ -1,11 +1,11 @@
1
1
  require 'rubygems'
2
2
  require 'bundler/setup'
3
3
  require 'mongoid'
4
- require 'encrypted_strings'
5
4
  require 'rspec'
6
5
 
7
6
  require 'mongoid-encrypted-fields'
8
7
 
8
+ Dir["#{File.dirname(__FILE__)}/../examples/**/*.rb"].each {|f| require f}
9
9
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
10
10
 
11
11
  ENV['MONGOID_ENV'] ||= 'test'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid-encrypted-fields
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-23 00:00:00.000000000 Z
12
+ date: 2013-02-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -44,37 +44,53 @@ dependencies:
44
44
  - !ruby/object:Gem::Version
45
45
  version: '3'
46
46
  - !ruby/object:Gem::Dependency
47
- name: encrypted_strings
47
+ name: rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: gibberish
48
64
  requirement: !ruby/object:Gem::Requirement
49
65
  none: false
50
66
  requirements:
51
67
  - - ~>
52
68
  - !ruby/object:Gem::Version
53
- version: '0.3'
54
- type: :runtime
69
+ version: '1.2'
70
+ type: :development
55
71
  prerelease: false
56
72
  version_requirements: !ruby/object:Gem::Requirement
57
73
  none: false
58
74
  requirements:
59
75
  - - ~>
60
76
  - !ruby/object:Gem::Version
61
- version: '0.3'
77
+ version: '1.2'
62
78
  - !ruby/object:Gem::Dependency
63
- name: rspec
79
+ name: encrypted_strings
64
80
  requirement: !ruby/object:Gem::Requirement
65
81
  none: false
66
82
  requirements:
67
- - - ! '>='
83
+ - - ~>
68
84
  - !ruby/object:Gem::Version
69
- version: '0'
85
+ version: '0.3'
70
86
  type: :development
71
87
  prerelease: false
72
88
  version_requirements: !ruby/object:Gem::Requirement
73
89
  none: false
74
90
  requirements:
75
- - - ! '>='
91
+ - - ~>
76
92
  - !ruby/object:Gem::Version
77
- version: '0'
93
+ version: '0.3'
78
94
  description: A library for storing encrypted data in Mongo
79
95
  email:
80
96
  - development@koanhealth.com
@@ -85,14 +101,15 @@ files:
85
101
  - .gitignore
86
102
  - .rspec
87
103
  - .rvmrc
104
+ - CHANGLOG.md
88
105
  - Gemfile
89
106
  - LICENSE.txt
90
107
  - README.md
91
108
  - Rakefile
109
+ - examples/encrypted_strings_asymmetric_cipher.rb
110
+ - examples/encrypted_strings_symmetric_cipher.rb
111
+ - examples/gibberish_cipher.rb
92
112
  - lib/mongoid-encrypted-fields.rb
93
- - lib/mongoid-encrypted-fields/ciphers/asymmetric_cipher.rb
94
- - lib/mongoid-encrypted-fields/ciphers/cipher.rb
95
- - lib/mongoid-encrypted-fields/ciphers/symmetric_cipher.rb
96
113
  - lib/mongoid-encrypted-fields/fields/encrypted_date.rb
97
114
  - lib/mongoid-encrypted-fields/fields/encrypted_date_time.rb
98
115
  - lib/mongoid-encrypted-fields/fields/encrypted_field.rb
@@ -124,7 +141,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
124
141
  version: '0'
125
142
  segments:
126
143
  - 0
127
- hash: 3554219364353199264
144
+ hash: -323082810856718661
128
145
  required_rubygems_version: !ruby/object:Gem::Requirement
129
146
  none: false
130
147
  requirements:
@@ -133,10 +150,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
133
150
  version: '0'
134
151
  segments:
135
152
  - 0
136
- hash: 3554219364353199264
153
+ hash: -323082810856718661
137
154
  requirements: []
138
155
  rubyforge_project:
139
- rubygems_version: 1.8.24
156
+ rubygems_version: 1.8.25
140
157
  signing_key:
141
158
  specification_version: 3
142
159
  summary: Custom types for storing encrypted data
@@ -1,22 +0,0 @@
1
- module Mongoid
2
- module Ciphers
3
- class AsymmetricCipher < Cipher
4
-
5
- attr_reader :algorithm, :password, :public_key_file, :private_key_file
6
-
7
- def initialize(options = {})
8
- @options = options
9
- @options.each { |key, value| instance_variable_set "@#{key}", value }
10
- end
11
-
12
- def encrypt(data)
13
- data.encrypt(:asymmetric, @options)
14
- end
15
-
16
- def decrypt(data)
17
- data.decrypt(:asymmetric, @options)
18
- end
19
-
20
- end
21
- end
22
- end
@@ -1,15 +0,0 @@
1
- module Mongoid
2
- module Ciphers
3
- class Cipher
4
-
5
- def encrypt(data)
6
- raise NotImplementedError.new('encrypt must be implemented')
7
- end
8
-
9
- def decrypt(data)
10
- raise NotImplementedError.new('decrypt must be implemented')
11
- end
12
-
13
- end
14
- end
15
- end
@@ -1,22 +0,0 @@
1
- module Mongoid
2
- module Ciphers
3
- class SymmetricCipher < Cipher
4
-
5
- attr_reader :algorithm, :password
6
-
7
- def initialize(options = { })
8
- @options = options
9
- @options.each { |key, value| instance_variable_set "@#{key}", value }
10
- end
11
-
12
- def encrypt(data)
13
- data.encrypt(:symmetric, @options)
14
- end
15
-
16
- def decrypt(data)
17
- data.decrypt(:symmetric, @options)
18
- end
19
-
20
- end
21
- end
22
- end