blind_index 0.3.0 → 0.3.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 651caa81ae68cdce70f5f0f83d3f2b1d0d2365c2c34765414d3ae0e523e5cdab
4
- data.tar.gz: 4a7d274aec56ba615a9569ab19c222b24d4a052166e8acdc0bfd2a5c65b4855b
3
+ metadata.gz: fe8410b6e972d6fe7aa37648396462b1e2a70358813e97db153d62ed5ac3fbad
4
+ data.tar.gz: 37d9baa7fb293ee2aa6e0a9fb5d253f8d0c7a83807dade72a8ac532825dc0220
5
5
  SHA512:
6
- metadata.gz: e169875cc33b23da106311fbbc41a2647bbd6b3abfd5e904f9ad7315ea71117d2dd69cc829ff16b222640397ba5576d12094fe2a62000e9c6962409dc6ccd478
7
- data.tar.gz: a7ee41ba497568c4580d98508c204f956aff7ed1ee04bb4452b78fe2897e98015ec3e9718bc6ef174b432912bfb7cf55bd94db79c45e14041ad057f04a49055f
6
+ metadata.gz: c647598d872e02b829377d5436442f0d929575722ee3330396c773d4dea556aabf74083e4868923fb597478df5648487fbfa26361eb6a341b1709dea3bb2e137
7
+ data.tar.gz: 1a9c501115e25cecf73e59ccb7ee5b23c96ccb01c81e4a62e48c1858546cf67a9c83f4f482cbf212ca2f38de559bbb668c39bf90a131ede9732eb4e390f45d3b
@@ -1,3 +1,13 @@
1
+ ## 0.3.2
2
+
3
+ - Added support for dynamic finders
4
+ - Added support for inherited models
5
+
6
+ ## 0.3.1
7
+
8
+ - Added scrypt and Argon2 algorithms
9
+ - Added `cost` option
10
+
1
11
  ## 0.3.0
2
12
 
3
13
  - Enforce secure key generation
@@ -1,4 +1,4 @@
1
- Copyright (c) 2017 Andrew Kane
1
+ Copyright (c) 2017-2018 Andrew Kane
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -42,7 +42,7 @@ class User < ApplicationRecord
42
42
  end
43
43
  ```
44
44
 
45
- We use environment variables to store the keys ([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). *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)
@@ -143,11 +143,8 @@ end
143
143
 
144
144
  The default is `10000`. Changing this value requires you to recompute the blind index.
145
145
 
146
-
147
146
  ### scrypt
148
147
 
149
- :warning: *Not production ready yet*
150
-
151
148
  Add [scrypt](https://github.com/pbhogan/scrypt) to your Gemfile and use:
152
149
 
153
150
  ```ruby
@@ -156,9 +153,15 @@ class User < ApplicationRecord
156
153
  end
157
154
  ```
158
155
 
159
- ### Argon2
156
+ Set the cost parameters with:
160
157
 
161
- :warning: *Not production ready yet*
158
+ ```ruby
159
+ class User < ApplicationRecord
160
+ blind_index :email, algorithm: :scrypt, cost: {n: 4096, r: 8, p: 1}, ...
161
+ end
162
+ ```
163
+
164
+ ### Argon2
162
165
 
163
166
  Add [argon2](https://github.com/technion/ruby-argon2) to your Gemfile and use:
164
167
 
@@ -168,6 +171,14 @@ class User < ApplicationRecord
168
171
  end
169
172
  ```
170
173
 
174
+ Set the cost parameters with:
175
+
176
+ ```ruby
177
+ class User < ApplicationRecord
178
+ blind_index :email, algorithm: :argon2, cost: {t: 3, m: 12}, ...
179
+ end
180
+ ```
181
+
171
182
  ## Reference
172
183
 
173
184
  By default, blind indexes are encoded in Base64. Set a different encoding with:
@@ -194,7 +205,15 @@ We recommend rotating your key if it doesn’t meet this criteria. You can gener
194
205
  SecureRandom.hex(32)
195
206
  ```
196
207
 
197
- Set the new key and recompute the blind index.
208
+ Update your model to convert the hex key to binary.
209
+
210
+ ```ruby
211
+ class User < ApplicationRecord
212
+ blind_index :email, key: [ENV["EMAIL_BLIND_INDEX_KEY"]].pack("H*")
213
+ end
214
+ ```
215
+
216
+ And recompute the blind index.
198
217
 
199
218
  ```ruby
200
219
  User.find_each do |user|
data/Rakefile CHANGED
@@ -10,19 +10,47 @@ end
10
10
 
11
11
  task default: :test
12
12
 
13
- task :benchmark do
14
- require "securerandom"
15
- require "benchmark/ips"
16
- require "blind_index"
17
- require "scrypt"
18
- require "argon2"
19
-
20
- key = SecureRandom.random_bytes(32)
21
- value = "secret"
22
-
23
- Benchmark.ips do |x|
24
- x.report("pbkdf2_hmac") { BlindIndex.generate_bidx(value, key: key, algorithm: :pbkdf2_hmac) }
25
- x.report("scrypt") { BlindIndex.generate_bidx(value, key: key, algorithm: :scrypt) }
26
- x.report("argon2") { BlindIndex.generate_bidx(value, key: key, algorithm: :argon2) }
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
27
55
  end
28
56
  end
@@ -15,7 +15,8 @@ module BlindIndex
15
15
  iterations: 10000,
16
16
  algorithm: :pbkdf2_hmac,
17
17
  insecure_key: false,
18
- encode: true
18
+ encode: true,
19
+ cost: {}
19
20
  }
20
21
 
21
22
  def self.generate_bidx(value, key:, **options)
@@ -39,16 +40,22 @@ module BlindIndex
39
40
 
40
41
  # gist to compare algorithm results
41
42
  # https://gist.github.com/ankane/fe3ac63fbf1c4550ee12554c664d2b8c
43
+ cost_options = options[:cost]
44
+
42
45
  value =
43
46
  case algorithm
44
47
  when :scrypt
45
- # n, p (keep r at 8)
46
- SCrypt::Engine.scrypt(value.to_s, key, 4096, 8, 1, 32)
48
+ n = cost_options[:n] || 4096
49
+ r = cost_options[:r] || 8
50
+ cp = cost_options[:p] || 1
51
+ SCrypt::Engine.scrypt(value.to_s, key, n, r, cp, 32)
47
52
  when :argon2
48
- # t_cost, m_cost
49
- [Argon2::Engine.hash_argon2i(value.to_s, key, 2, 12)].pack("H*")
53
+ t = cost_options[:t] || 3
54
+ m = cost_options[:m] || 12
55
+ [Argon2::Engine.hash_argon2i(value.to_s, key, t, m)].pack("H*")
50
56
  when :pbkdf2_hmac
51
- OpenSSL::PKCS5.pbkdf2_hmac(value.to_s, key, options[:iterations], 32, "sha256")
57
+ iterations = cost_options[:iterations] || options[:iterations]
58
+ OpenSSL::PKCS5.pbkdf2_hmac(value.to_s, key, iterations, 32, "sha256")
52
59
  else
53
60
  raise BlindIndex::Error, "Unknown algorithm"
54
61
  end
@@ -77,6 +84,8 @@ ActiveSupport.on_load(:active_record) do
77
84
  ActiveRecord::PredicateBuilder.singleton_class.prepend(BlindIndex::Extensions::PredicateBuilder)
78
85
  end
79
86
 
87
+ ActiveRecord::DynamicMatchers::Method.prepend(BlindIndex::Extensions::DynamicMatchers)
88
+
80
89
  unless ActiveRecord::VERSION::STRING.start_with?("5.1.")
81
90
  ActiveRecord::Validations::UniquenessValidator.prepend(BlindIndex::Extensions::UniquenessValidator)
82
91
  end
@@ -67,5 +67,15 @@ module BlindIndex
67
67
  end
68
68
  end
69
69
  end
70
+
71
+ module DynamicMatchers
72
+ def valid?
73
+ attribute_names.all? { |name| model.columns_hash[name] || model.reflect_on_aggregation(name.to_sym) || blind_index?(name.to_sym) }
74
+ end
75
+
76
+ def blind_index?(name)
77
+ model.respond_to?(:blind_indexes) && model.blind_indexes[name]
78
+ end
79
+ end
70
80
  end
71
81
  end
@@ -1,6 +1,6 @@
1
1
  module BlindIndex
2
2
  module Model
3
- def blind_index(name, key: nil, iterations: nil, attribute: nil, expression: nil, bidx_attribute: nil, callback: true, algorithm: nil, insecure_key: nil, encode: nil)
3
+ def blind_index(name, key: nil, iterations: nil, attribute: nil, expression: nil, bidx_attribute: nil, callback: true, algorithm: nil, insecure_key: nil, encode: nil, cost: nil)
4
4
  iterations ||= 10000
5
5
  attribute ||= name
6
6
  bidx_attribute ||= :"encrypted_#{name}_bidx"
@@ -10,15 +10,24 @@ module BlindIndex
10
10
  method_name = :"compute_#{name}_bidx"
11
11
 
12
12
  class_eval do
13
- class << self
14
- def blind_indexes
15
- @blind_indexes ||= {}
16
- end unless method_defined?(:blind_indexes)
13
+ @blind_indexes ||= {}
14
+
15
+ unless respond_to?(:blind_indexes)
16
+ def self.blind_indexes
17
+ parent_indexes =
18
+ if superclass.respond_to?(:blind_indexes)
19
+ superclass.blind_indexes
20
+ else
21
+ {}
22
+ end
23
+
24
+ parent_indexes.merge(@blind_indexes || {})
25
+ end
17
26
  end
18
27
 
19
28
  raise BlindIndex::Error, "Duplicate blind index: #{name}" if blind_indexes[name]
20
29
 
21
- blind_indexes[name] = {
30
+ @blind_indexes[name] = {
22
31
  key: key,
23
32
  iterations: iterations,
24
33
  attribute: attribute,
@@ -26,9 +35,11 @@ module BlindIndex
26
35
  bidx_attribute: bidx_attribute,
27
36
  algorithm: algorithm,
28
37
  insecure_key: insecure_key,
29
- encode: encode
38
+ encode: encode,
39
+ cost: cost
30
40
  }.reject { |_, v| v.nil? }
31
41
 
42
+ # should have been named generate_#{name}_bidx
32
43
  define_singleton_method method_name do |value|
33
44
  BlindIndex.generate_bidx(value, blind_indexes[name])
34
45
  end
@@ -1,3 +1,3 @@
1
1
  module BlindIndex
2
- VERSION = "0.3.0"
2
+ VERSION = "0.3.2"
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.0
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-06-03 00:00:00.000000000 Z
11
+ date: 2018-06-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport