mongoid-encrypted-fields 1.0.0 → 1.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/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