blind_index 0.3.2 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fe8410b6e972d6fe7aa37648396462b1e2a70358813e97db153d62ed5ac3fbad
4
- data.tar.gz: 37d9baa7fb293ee2aa6e0a9fb5d253f8d0c7a83807dade72a8ac532825dc0220
3
+ metadata.gz: 26d5a803099fa8b408065a43056697f24eaf10a89c6a778979e5bdd8d54bbb5e
4
+ data.tar.gz: '0288069afcdd54f3f3917ef25177550bd3c912333aca346d1ae77d0d237eb5ce'
5
5
  SHA512:
6
- metadata.gz: c647598d872e02b829377d5436442f0d929575722ee3330396c773d4dea556aabf74083e4868923fb597478df5648487fbfa26361eb6a341b1709dea3bb2e137
7
- data.tar.gz: 1a9c501115e25cecf73e59ccb7ee5b23c96ccb01c81e4a62e48c1858546cf67a9c83f4f482cbf212ca2f38de559bbb668c39bf90a131ede9732eb4e390f45d3b
6
+ metadata.gz: 1f062a2b9d1aa2d251dd38b6c815423afa146a34df0825d655bd9ac0ea666af9d0382d958995c7899e16a729b15e7e3d696d661485a246220e93bade67104641
7
+ data.tar.gz: 1478bb3716c6ad099e42ed95b286d7aa5a13c6be7f75d4ec6e7d5c82898c95d1fc7db2537d53c6daa5754ad398579bca5e924a60551423402e064f24b52ee2ff
@@ -1,3 +1,7 @@
1
+ ## 0.3.3
2
+
3
+ - Added support for string keys in finders
4
+
1
5
  ## 0.3.2
2
6
 
3
7
  - Added support for dynamic finders
data/README.md CHANGED
@@ -4,7 +4,7 @@ Securely search encrypted database fields
4
4
 
5
5
  Designed for use with [attr_encrypted](https://github.com/attr-encrypted/attr_encrypted)
6
6
 
7
- Here’s a [full example](https://shorts.dokkuapp.com/securing-user-emails-in-rails/) of how to use it with Devise
7
+ Here’s a [full example](https://ankane.org/securing-user-emails-in-rails) of how to use it with Devise
8
8
 
9
9
  [![Build Status](https://travis-ci.org/ankane/blind_index.svg?branch=master)](https://travis-ci.org/ankane/blind_index)
10
10
 
@@ -42,7 +42,7 @@ class User < ApplicationRecord
42
42
  end
43
43
  ```
44
44
 
45
- We use environment variables to store the keys as hex-encoded strings ([dotenv](https://github.com/bkeepers/dotenv) is great for this). *Do not commit them to source control.* Generate one key for encryption and one key for hashing. You can generate keys in the Rails console with:
45
+ We use environment variables to store the keys as hex-encoded strings ([dotenv](https://github.com/bkeepers/dotenv) is great for this). [Here’s an explanation](https://ankane.org/encryption-keys) of why `pack` is used. *Do not commit them to source control.* Generate one key for encryption and one key for hashing. You can generate keys in the Rails console with:
46
46
 
47
47
  ```ruby
48
48
  SecureRandom.hex(32)
@@ -118,12 +118,36 @@ class User < ApplicationRecord
118
118
  end
119
119
  ```
120
120
 
121
+ *Requires ActiveRecord 5.1+*
122
+
123
+ ## Multiple Columns
124
+
125
+ You can also use virtual attributes to index data from multiple columns:
126
+
127
+ ```ruby
128
+ class User < ApplicationRecord
129
+ attribute :initials
130
+
131
+ # must come before blind_index method
132
+ before_validation :set_initials, if: -> { changes.key?(:first_name) || changes.key?(:last_name) }
133
+ blind_index :initials, ...
134
+
135
+ def set_initials
136
+ self.initials = "#{first_name[0]}#{last_name[0]}"
137
+ end
138
+ end
139
+ ```
140
+
141
+ *Requires ActiveRecord 5.1+*
142
+
121
143
  ## Fixtures
122
144
 
123
- You can use blind indexes in fixtures with:
145
+ You can use encrypted attributes and blind indexes in fixtures with:
124
146
 
125
147
  ```yml
126
148
  test_user:
149
+ encrypted_email: <%= User.encrypt_email("test@example.org", iv: Base64.decode64("0000000000000000")) %>
150
+ encrypted_email_iv: "0000000000000000"
127
151
  encrypted_email_bidx: <%= User.compute_email_bidx("test@example.org").inspect %>
128
152
  ```
129
153
 
@@ -179,6 +203,46 @@ class User < ApplicationRecord
179
203
  end
180
204
  ```
181
205
 
206
+ ## Key Rotation
207
+
208
+ To rotate keys without downtime, add a new column:
209
+
210
+ ```ruby
211
+ add_column :users, :encrypted_email_v2_bidx, :string
212
+ add_index :users, :encrypted_email_v2_bidx
213
+ ```
214
+
215
+ And add to your model
216
+
217
+ ```ruby
218
+ class User < ApplicationRecord
219
+ blind_index :email, key: [ENV["EMAIL_BLIND_INDEX_KEY"]].pack("H*")
220
+ blind_index :email_v2, attribute: :email, key: [ENV["EMAIL_V2_BLIND_INDEX_KEY"]].pack("H*")
221
+ end
222
+ ```
223
+
224
+ Backfill the data
225
+
226
+ ```ruby
227
+ User.find_each do |user|
228
+ user.compute_email_v2_bidx
229
+ user.save!
230
+ end
231
+ ```
232
+
233
+ Then update your model
234
+
235
+ ```ruby
236
+ class User < ApplicationRecord
237
+ blind_index :email, bidx_attribute: :encrypted_email_v2_bidx, key: [ENV["EMAIL_V2_BLIND_INDEX_KEY"]].pack("H*")
238
+
239
+ # remove this line after dropping column
240
+ self.ignored_columns = ["encrypted_email_bidx"]
241
+ end
242
+ ```
243
+
244
+ Finally, drop the old column.
245
+
182
246
  ## Reference
183
247
 
184
248
  By default, blind indexes are encoded in Base64. Set a different encoding with:
@@ -6,7 +6,7 @@ module BlindIndex
6
6
  new_hash = super
7
7
  if has_blind_indexes?
8
8
  hash.each do |key, _|
9
- if (bi = klass.blind_indexes[key]) && !new_hash[key].is_a?(ActiveRecord::StatementCache::Substitute)
9
+ if key.respond_to?(:to_sym) && (bi = klass.blind_indexes[key.to_sym]) && !new_hash[key].is_a?(ActiveRecord::StatementCache::Substitute)
10
10
  new_hash[bi[:bidx_attribute]] = BlindIndex.generate_bidx(new_hash.delete(key), bi)
11
11
  end
12
12
  end
@@ -29,7 +29,7 @@ module BlindIndex
29
29
  new_hash = super
30
30
  if has_blind_indexes?(klass)
31
31
  hash.each do |key, _|
32
- if (bi = klass.blind_indexes[key]) && !new_hash[key].is_a?(ActiveRecord::StatementCache::Substitute)
32
+ if key.respond_to?(:to_sym) && (bi = klass.blind_indexes[key.to_sym]) && !new_hash[key].is_a?(ActiveRecord::StatementCache::Substitute)
33
33
  new_hash[bi[:bidx_attribute]] = BlindIndex.generate_bidx(new_hash.delete(key), bi)
34
34
  end
35
35
  end
@@ -49,7 +49,12 @@ module BlindIndex
49
49
  end
50
50
 
51
51
  if callback
52
- before_validation method_name, if: -> { changes.key?(attribute.to_s) }
52
+ if ActiveRecord::VERSION::STRING >= "5.1"
53
+ before_validation method_name, if: :"will_save_change_to_#{attribute}?"
54
+ else
55
+ before_validation method_name, if: -> { changes.key?(attribute.to_s) }
56
+ end
57
+
53
58
  end
54
59
 
55
60
  # use include so user can override
@@ -1,3 +1,3 @@
1
1
  module BlindIndex
2
- VERSION = "0.3.2"
2
+ VERSION = "0.3.3"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: blind_index
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
- bindir: exe
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2018-06-18 00:00:00.000000000 Z
11
+ date: 2018-11-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -151,22 +151,14 @@ dependencies:
151
151
  - !ruby/object:Gem::Version
152
152
  version: '0'
153
153
  description:
154
- email:
155
- - andrew@chartkick.com
154
+ email: andrew@chartkick.com
156
155
  executables: []
157
156
  extensions: []
158
157
  extra_rdoc_files: []
159
158
  files:
160
- - ".gitignore"
161
- - ".travis.yml"
162
159
  - CHANGELOG.md
163
- - Gemfile
164
160
  - LICENSE.txt
165
161
  - README.md
166
- - Rakefile
167
- - bin/console
168
- - bin/setup
169
- - blind_index.gemspec
170
162
  - lib/blind_index.rb
171
163
  - lib/blind_index/extensions.rb
172
164
  - lib/blind_index/model.rb
@@ -183,7 +175,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
183
175
  requirements:
184
176
  - - ">="
185
177
  - !ruby/object:Gem::Version
186
- version: '0'
178
+ version: '2.2'
187
179
  required_rubygems_version: !ruby/object:Gem::Requirement
188
180
  requirements:
189
181
  - - ">="
@@ -191,7 +183,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
191
183
  version: '0'
192
184
  requirements: []
193
185
  rubyforge_project:
194
- rubygems_version: 2.7.6
186
+ rubygems_version: 2.7.7
195
187
  signing_key:
196
188
  specification_version: 4
197
189
  summary: Securely search encrypted database fields
data/.gitignore DELETED
@@ -1,9 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /_yardoc/
4
- /coverage/
5
- /doc/
6
- /pkg/
7
- /spec/reports/
8
- /tmp/
9
- *.lock
@@ -1,14 +0,0 @@
1
- language: ruby
2
- rvm: 2.4.2
3
- gemfile:
4
- - Gemfile
5
- - test/gemfiles/activerecord51.gemfile
6
- - test/gemfiles/activerecord50.gemfile
7
- - test/gemfiles/activerecord42.gemfile
8
- sudo: false
9
- before_install: gem install bundler
10
- script: bundle exec rake test
11
- notifications:
12
- email:
13
- on_success: never
14
- on_failure: change
data/Gemfile DELETED
@@ -1,4 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- # Specify your gem's dependencies in blind_index.gemspec
4
- gemspec
data/Rakefile DELETED
@@ -1,56 +0,0 @@
1
- require "bundler/gem_tasks"
2
- require "rake/testtask"
3
-
4
- Rake::TestTask.new(:test) do |t|
5
- t.libs << "test"
6
- t.libs << "lib"
7
- t.test_files = FileList["test/**/*_test.rb"]
8
- t.warning = false
9
- end
10
-
11
- task default: :test
12
-
13
- namespace :benchmark do
14
- task :algorithms do
15
- require "securerandom"
16
- require "benchmark/ips"
17
- require "blind_index"
18
- require "scrypt"
19
- require "argon2"
20
-
21
- key = SecureRandom.random_bytes(32)
22
- value = "secret"
23
-
24
- Benchmark.ips do |x|
25
- x.report("pbkdf2_hmac") { BlindIndex.generate_bidx(value, key: key, algorithm: :pbkdf2_hmac) }
26
- x.report("scrypt") { BlindIndex.generate_bidx(value, key: key, algorithm: :scrypt) }
27
- x.report("argon2") { BlindIndex.generate_bidx(value, key: key, algorithm: :argon2) }
28
- end
29
- end
30
-
31
- task :queries do
32
- require "benchmark/ips"
33
- require "active_record"
34
- require "blind_index"
35
-
36
- ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
37
-
38
- ActiveRecord::Migration.create_table :users do
39
- end
40
-
41
- ActiveRecord::Migration.create_table :cities do
42
- end
43
-
44
- class User < ActiveRecord::Base
45
- blind_index :email
46
- end
47
-
48
- class City < ActiveRecord::Base
49
- end
50
-
51
- Benchmark.ips do |x|
52
- x.report("no index") { City.where(id: 1).first }
53
- x.report("index") { User.where(id: 1).first }
54
- end
55
- end
56
- end
@@ -1,14 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "bundler/setup"
4
- require "blind_index"
5
-
6
- # You can add fixtures and/or initialization code here to make experimenting
7
- # with your gem easier. You can also use a different console, if you like.
8
-
9
- # (If you use this, don't forget to add pry to your Gemfile!)
10
- # require "pry"
11
- # Pry.start
12
-
13
- require "irb"
14
- IRB.start(__FILE__)
data/bin/setup DELETED
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here
@@ -1,34 +0,0 @@
1
-
2
- lib = File.expand_path("../lib", __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require "blind_index/version"
5
-
6
- Gem::Specification.new do |spec|
7
- spec.name = "blind_index"
8
- spec.version = BlindIndex::VERSION
9
- spec.authors = ["Andrew Kane"]
10
- spec.email = ["andrew@chartkick.com"]
11
-
12
- spec.summary = "Securely search encrypted database fields"
13
- spec.homepage = "https://github.com/ankane/blind_index"
14
- spec.license = "MIT"
15
-
16
- spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
- f.match(%r{^(test|spec|features)/})
18
- end
19
- spec.bindir = "exe"
20
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
- spec.require_paths = ["lib"]
22
-
23
- spec.add_dependency "activesupport", ">= 4.2"
24
-
25
- spec.add_development_dependency "bundler"
26
- spec.add_development_dependency "rake"
27
- spec.add_development_dependency "minitest"
28
- spec.add_development_dependency "attr_encrypted"
29
- spec.add_development_dependency "activerecord"
30
- spec.add_development_dependency "sqlite3"
31
- spec.add_development_dependency "scrypt"
32
- spec.add_development_dependency "argon2"
33
- spec.add_development_dependency "benchmark-ips"
34
- end