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 +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +67 -3
- data/lib/blind_index/extensions.rb +2 -2
- data/lib/blind_index/model.rb +6 -1
- data/lib/blind_index/version.rb +1 -1
- metadata +6 -14
- data/.gitignore +0 -9
- data/.travis.yml +0 -14
- data/Gemfile +0 -4
- data/Rakefile +0 -56
- data/bin/console +0 -14
- data/bin/setup +0 -8
- data/blind_index.gemspec +0 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 26d5a803099fa8b408065a43056697f24eaf10a89c6a778979e5bdd8d54bbb5e
|
4
|
+
data.tar.gz: '0288069afcdd54f3f3917ef25177550bd3c912333aca346d1ae77d0d237eb5ce'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1f062a2b9d1aa2d251dd38b6c815423afa146a34df0825d655bd9ac0ea666af9d0382d958995c7899e16a729b15e7e3d696d661485a246220e93bade67104641
|
7
|
+
data.tar.gz: 1478bb3716c6ad099e42ed95b286d7aa5a13c6be7f75d4ec6e7d5c82898c95d1fc7db2537d53c6daa5754ad398579bca5e924a60551423402e064f24b52ee2ff
|
data/CHANGELOG.md
CHANGED
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://
|
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
|
data/lib/blind_index/model.rb
CHANGED
@@ -49,7 +49,12 @@ module BlindIndex
|
|
49
49
|
end
|
50
50
|
|
51
51
|
if callback
|
52
|
-
|
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
|
data/lib/blind_index/version.rb
CHANGED
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.
|
4
|
+
version: 0.3.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
|
-
bindir:
|
9
|
+
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
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: '
|
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.
|
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
data/.travis.yml
DELETED
@@ -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
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
|
data/bin/console
DELETED
@@ -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
data/blind_index.gemspec
DELETED
@@ -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
|